@@ -67,6 +67,77 @@ int getOffsetToFirstByteOfComponent(const Channel channel,
6767 return offset;
6868}
6969
70+ using RGBTuple = std::tuple<int , int , int >;
71+ RGBTuple extractRGB565Value (const unsigned char *data, const Endianness endianess)
72+ {
73+ int byte1 = *data;
74+ int byte2 = *(data + 1 );
75+
76+ if (endianess == Endianness::Big)
77+ std::swap (byte1, byte2);
78+
79+ const auto value = byte1 + (byte2 << 8 );
80+
81+ int r = ((value & 0b00000000'00011111 ) << 3 );
82+ int g = ((value & 0b00000111'11100000 ) >> 3 );
83+ int b = ((value & 0b11111000'00000000 ) >> 8 );
84+
85+ return {r, g, b};
86+ }
87+
88+ void convertRGB565ToARGB (const QByteArray &sourceBuffer,
89+ const PixelFormatRGB &srcPixelFormat,
90+ unsigned char *targetBuffer,
91+ const Size frameSize,
92+ const bool componentInvert[4 ],
93+ const int componentScale[4 ],
94+ const bool limitedRange)
95+ {
96+ auto rawData = reinterpret_cast <const unsigned char *>(sourceBuffer.data ());
97+
98+ const auto endianness = srcPixelFormat.getEndianess ();
99+ for (unsigned i = 0 ; i < frameSize.width * frameSize.height ; i++)
100+ {
101+ int byte1 = *rawData;
102+ int byte2 = *(rawData + 1 );
103+
104+ if (endianness == Endianness::Big)
105+ std::swap (byte1, byte2);
106+
107+ const auto value = byte1 + (byte2 << 8 );
108+
109+ int r = ((value & 0b00000000'00011111 ) << 3 );
110+ int g = ((value & 0b00000111'11100000 ) >> 3 );
111+ int b = ((value & 0b11111000'00000000 ) >> 8 );
112+
113+ r = functions::clip (r * componentScale[0 ], 0 , 255 );
114+ g = functions::clip (g * componentScale[1 ], 0 , 255 );
115+ b = functions::clip (b * componentScale[2 ], 0 , 255 );
116+
117+ if (componentInvert[0 ])
118+ r = (255 - r);
119+ if (componentInvert[1 ])
120+ g = (255 - g);
121+ if (componentInvert[2 ])
122+ b = (255 - b);
123+
124+ if (limitedRange)
125+ {
126+ r = LimitedRangeToFullRange.at (r);
127+ g = LimitedRangeToFullRange.at (g);
128+ b = LimitedRangeToFullRange.at (b);
129+ }
130+
131+ targetBuffer[0 ] = r;
132+ targetBuffer[1 ] = g;
133+ targetBuffer[2 ] = b;
134+ targetBuffer[3 ] = 255 ;
135+
136+ rawData += 2 ;
137+ targetBuffer += 4 ;
138+ }
139+ }
140+
70141// Convert the input format to the output RGBA format. Apply inversion, scaling,
71142// limited range conversion and alpha multiplication. The input can be any supported
72143// format. The output is always 8 bit ARGB little endian.
@@ -103,10 +174,10 @@ void convertRGBToARGB(const QByteArray &sourceBuffer,
103174 srcA = ((InValueType)sourceBuffer.data ()) + offsetA;
104175 }
105176
177+ const auto isBigEndian = bitDepth > 8 && srcPixelFormat.getEndianess () == Endianness::Big;
106178 for (unsigned i = 0 ; i < frameSize.width * frameSize.height ; i++)
107179 {
108- const auto isBigEndian = bitDepth > 8 && srcPixelFormat.getEndianess () == Endianness::Big;
109- auto convertValue =
180+ auto convertValue =
110181 [&isBigEndian, &rightShift](const InValueType sourceData, const int scale, const bool invert)
111182 {
112183 auto value = static_cast <int64_t >(sourceData[0 ]);
@@ -205,6 +276,30 @@ void convertRGBPlaneToARGB(const QByteArray &sourceBuffer,
205276 }
206277}
207278
279+ rgba_t getPixelValueForPredefiendFormat (const QByteArray &sourceBuffer,
280+ const PixelFormatRGB &srcPixelFormat,
281+ const Size frameSize,
282+ const QPoint &pixelPos)
283+ {
284+ const auto offsetPixelPos = frameSize.width * pixelPos.y () + pixelPos.x ();
285+ const auto rawData =
286+ reinterpret_cast <const unsigned char *>(sourceBuffer.data () + offsetPixelPos * 2 );
287+
288+ int byte1 = *rawData;
289+ int byte2 = *(rawData + 1 );
290+
291+ if (srcPixelFormat.getEndianess () == Endianness::Big)
292+ std::swap (byte1, byte2);
293+
294+ const auto value = byte1 + (byte2 << 8 );
295+
296+ int r = ((value & 0b00000000'00011111 ));
297+ int g = ((value & 0b00000111'11100000 ) >> 5 );
298+ int b = ((value & 0b11111000'00000000 ) >> 11 );
299+
300+ return {static_cast <unsigned >(r), static_cast <unsigned >(g), static_cast <unsigned >(b), 255 };
301+ }
302+
208303template <int bitDepth>
209304rgba_t getPixelValue (const QByteArray &sourceBuffer,
210305 const PixelFormatRGB &srcPixelFormat,
@@ -251,10 +346,16 @@ void convertInputRGBToARGB(const QByteArray &sourceBuffer,
251346 const bool premultiplyAlpha)
252347{
253348 const auto bitsPerComponent = srcPixelFormat.getBitsPerComponent ();
254- if (bitsPerComponent < 8 || bitsPerComponent > 32 )
255- throw std::invalid_argument (" Invalid bit depth in pixel format for conversion" );
256349
257- if (bitsPerComponent == 8 )
350+ if (srcPixelFormat.getPredefinedPixelFormat ())
351+ convertRGB565ToARGB (sourceBuffer,
352+ srcPixelFormat,
353+ targetBuffer,
354+ frameSize,
355+ componentInvert,
356+ componentScale,
357+ limitedRange);
358+ else if (bitsPerComponent == 8 )
258359 convertRGBToARGB<8 >(sourceBuffer,
259360 srcPixelFormat,
260361 targetBuffer,
@@ -274,7 +375,7 @@ void convertInputRGBToARGB(const QByteArray &sourceBuffer,
274375 limitedRange,
275376 outputHasAlpha,
276377 premultiplyAlpha);
277- else
378+ else if (bitsPerComponent <= 32 )
278379 convertRGBToARGB<32 >(sourceBuffer,
279380 srcPixelFormat,
280381 targetBuffer,
@@ -284,6 +385,8 @@ void convertInputRGBToARGB(const QByteArray &sourceBuffer,
284385 limitedRange,
285386 outputHasAlpha,
286387 premultiplyAlpha);
388+ else
389+ throw std::invalid_argument (" Unable to perform conversion" );
287390}
288391
289392void convertSinglePlaneOfRGBToGreyscaleARGB (const QByteArray &sourceBuffer,
@@ -334,15 +437,17 @@ rgba_t getPixelValueFromBuffer(const QByteArray &sourceBuffer,
334437 const QPoint &pixelPos)
335438{
336439 const auto bitsPerComponent = srcPixelFormat.getBitsPerComponent ();
337- if (bitsPerComponent < 8 || bitsPerComponent > 32 )
338- throw std::invalid_argument (" Invalid bit depth in pixel format for conversion" );
339440
340- if (bitsPerComponent == 8 )
441+ if (srcPixelFormat.getPredefinedPixelFormat ())
442+ return getPixelValueForPredefiendFormat (sourceBuffer, srcPixelFormat, frameSize, pixelPos);
443+ else if (bitsPerComponent == 8 )
341444 return getPixelValue<8 >(sourceBuffer, srcPixelFormat, frameSize, pixelPos);
342445 else if (bitsPerComponent <= 16 )
343446 return getPixelValue<16 >(sourceBuffer, srcPixelFormat, frameSize, pixelPos);
344- else
447+ else if (bitsPerComponent <= 32 )
345448 return getPixelValue<32 >(sourceBuffer, srcPixelFormat, frameSize, pixelPos);
449+
450+ throw std::invalid_argument (" Unable to perform conversion" );
346451}
347452
348453} // namespace video::rgb
0 commit comments