2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali/internal/imaging/common/pixel-manipulation.h>
21 #include <dali/integration-api/debug.h>
22 #include <dali/public-api/images/pixel.h>
34 * @brief Pre-defined offset tables for each Channel.
35 * If invalid channel, return -1. else, return the offset bytes.
37 // | LUMINANCE | RED | GREEN | BLUE | ALPHA | DEPTH | STENCIL |
38 constexpr std::int8_t ALPHA_ONLY_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { -1 , -1 , -1 , -1 , 0 , -1 , -1 };
39 constexpr std::int8_t LUMINANCE_ONLY_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { 0 , -1 , -1 , -1 , -1 , -1 , -1 };
40 constexpr std::int8_t LUMINANCE_ALPHA_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { 0 , -1 , -1 , -1 , 1 , -1 , -1 };
41 constexpr std::int8_t RGB_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { -1 , 0 , 1 , 2 , -1 , -1 , -1 };
42 constexpr std::int8_t BGR_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { -1 , 2 , 1 , 0 , -1 , -1 , -1 };
43 constexpr std::int8_t RGBA_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { -1 , 0 , 1 , 2 , 3 , -1 , -1 };
44 constexpr std::int8_t BGRA_OFFSET_TABLE[MAX_NUMBER_OF_CHANNELS] = { -1 , 2 , 1 , 0 , 3 , -1 , -1 };
48 * @brief Template to Read from a buffer with pixel formats that have one byte per channel.
50 * @tparam NumberOfChannels The number of channels to check
51 * @param pixelData The pixel data to retrieve the value from
52 * @param channel The channel we're after
53 * @param offsetTable The array of offset bytes for each channels in the pixel format
54 * @return The value of the required channel
56 unsigned int ReadChannelTable(unsigned char* pixelData, Channel channel, const std::int8_t (&offsetTable)[MAX_NUMBER_OF_CHANNELS])
59 if(offsetTable[channel] >= 0)
61 retVal = static_cast<unsigned int>(*(pixelData + offsetTable[channel]));
67 * @brief Template to Write to a buffer with pixel formats that have one byte per channel.
69 * @tparam NumberOfChannels The number of channels to check
70 * @param pixelData The pixel data to write the value to
71 * @param channel The channel we're after
72 * @param channelValue The value of the channel to set
73 * @param offsetTable The array of offset bytes for each channels in the pixel format
75 void WriteChannelTable(unsigned char* pixelData, Channel channel, unsigned int channelValue, const std::int8_t (&offsetTable)[MAX_NUMBER_OF_CHANNELS])
77 if(offsetTable[channel] >= 0)
79 *(pixelData + offsetTable[channel]) = static_cast<unsigned char>(channelValue & 0xFF);
84 * @brief Reads from buffers with a pixel format of 565.
86 * @param pixelData The pixel data to read from
87 * @param channel The channel we're after
88 * @param one The first channel of the pixel format
89 * @param two The second channel of the pixel format
90 * @param three The third channel of the pixel format
91 * @return The value of the required channel
93 unsigned int ReadChannel565(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three)
97 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
99 else if(channel == two)
101 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
102 ((static_cast<unsigned int>(*(pixelData + 1)) & 0xE0) >> 5);
104 else if(channel == three)
106 return static_cast<unsigned int>(*(pixelData + 1)) & 0x1F;
112 * @brief Writes to the buffer with a pixel format of 565.
114 * @param pixelData The pixel data to write to
115 * @param channel The channel we're after
116 * @param channelValue The value to write
117 * @param one The first channel of the pixel format
118 * @param two The second channel of the pixel format
119 * @param three The third channel of the pixel format
121 void WriteChannel565(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three)
125 *pixelData &= static_cast<unsigned char>(~0xF8);
126 *pixelData |= static_cast<unsigned char>((channelValue << 3) & 0xF8);
128 else if(channel == two)
130 *pixelData &= static_cast<unsigned char>(~0x07);
131 *pixelData |= static_cast<unsigned char>((channelValue >> 3) & 0x07);
133 *(pixelData + 1) &= static_cast<unsigned char>(~0xE0);
134 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 5) & 0xE0);
136 else if(channel == three)
138 *(pixelData + 1) &= static_cast<unsigned char>(~0x1F);
139 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x1F);
144 * @brief Reads from buffers with a pixel format of 4444.
146 * @param pixelData The pixel data to read from
147 * @param channel The channel we're after
148 * @param one The first channel of the pixel format
149 * @param two The second channel of the pixel format
150 * @param three The third channel of the pixel format
151 * @param four The fourth channel of the pixel format
154 unsigned int ReadChannel4444(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
158 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
160 else if(channel == two)
162 return (static_cast<unsigned int>(*pixelData) & 0x0F);
164 else if(channel == three)
166 return (static_cast<unsigned int>(*(pixelData + 1)) & 0xF0) >> 4;
168 else if(channel == four)
170 return (static_cast<unsigned int>(*(pixelData + 1)) & 0x0F);
176 * @brief Writes to the buffer with a pixel format of 565.
178 * @param pixelData The pixel data to write to
179 * @param channel The channel we're after
180 * @param channelValue The value to write
181 * @param one The first channel of the pixel format
182 * @param two The second channel of the pixel format
183 * @param three The third channel of the pixel format
184 * @param four The fourth channel of the pixel format
186 void WriteChannel4444(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
190 *pixelData &= static_cast<unsigned char>(~0xF0);
191 *pixelData |= static_cast<unsigned char>((channelValue << 4) & 0xF0);
193 else if(channel == two)
195 *pixelData &= static_cast<unsigned char>(~0x0F);
196 *pixelData |= static_cast<unsigned char>(channelValue & 0x0F);
198 else if(channel == three)
200 *(pixelData + 1) &= static_cast<unsigned char>(~0xF0);
201 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 4) & 0xF0);
203 else if(channel == four)
205 *(pixelData + 1) &= static_cast<unsigned char>(~0x0F);
206 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x0F);
211 * @brief Reads from buffers with a pixel format of 5551.
213 * @param pixelData The pixel data to read from
214 * @param channel The channel we're after
215 * @param one The first channel of the pixel format
216 * @param two The second channel of the pixel format
217 * @param three The third channel of the pixel format
218 * @param four The fourth channel of the pixel format
221 unsigned int ReadChannel5551(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
225 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
227 else if(channel == two)
229 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
230 ((static_cast<unsigned int>(*(pixelData + 1)) & 0xC0) >> 6);
232 else if(channel == three)
234 return (static_cast<unsigned int>(*(pixelData + 1)) & 0x3E) >> 1;
236 else if(channel == four)
238 return static_cast<unsigned int>(*(pixelData + 1)) & 0x01;
244 * @brief Writes to the buffer with a pixel format of 5551.
246 * @param pixelData The pixel data to write to
247 * @param channel The channel we're after
248 * @param channelValue The value to write
249 * @param one The first channel of the pixel format
250 * @param two The second channel of the pixel format
251 * @param three The third channel of the pixel format
252 * @param four The fourth channel of the pixel format
254 void WriteChannel5551(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
260 *pixelData &= static_cast<unsigned char>(~0xF8);
261 *pixelData |= static_cast<unsigned char>((channelValue << 3) & 0xF8);
263 else if(channel == two)
265 *pixelData &= static_cast<unsigned char>(~0x07);
266 *pixelData |= static_cast<unsigned char>((channelValue >> 2) & 0x07);
268 *(pixelData + 1) &= static_cast<unsigned char>(~0xC0);
269 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 6) & 0xC0);
271 else if(channel == three)
273 *(pixelData + 1) &= static_cast<unsigned char>(~0x3E);
274 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 1) & 0x3E);
276 else if(channel == four)
278 *(pixelData + 1) &= static_cast<unsigned char>(~0x01);
279 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x01);
283 } // unnamed namespace
287 unsigned int bitShift;
288 unsigned int bitMask;
301 bool HasChannel(Dali::Pixel::Format pixelFormat, Channel channel)
305 case Dali::Pixel::A8:
307 return (channel == ALPHA);
309 case Dali::Pixel::L8:
311 return (channel == LUMINANCE);
313 case Dali::Pixel::LA88:
315 return (channel == LUMINANCE || channel == ALPHA);
317 case Dali::Pixel::RGB565:
318 case Dali::Pixel::BGR565:
319 case Dali::Pixel::RGB888:
320 case Dali::Pixel::RGB8888:
321 case Dali::Pixel::BGR8888:
322 case Dali::Pixel::RGB16F:
323 case Dali::Pixel::RGB32F:
324 case Dali::Pixel::R11G11B10F:
326 return (channel == RED || channel == GREEN || channel == BLUE);
329 case Dali::Pixel::RGBA8888:
330 case Dali::Pixel::BGRA8888:
331 case Dali::Pixel::RGBA4444:
332 case Dali::Pixel::BGRA4444:
333 case Dali::Pixel::RGBA5551:
334 case Dali::Pixel::BGRA5551:
336 return (channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA);
339 case Dali::Pixel::DEPTH_UNSIGNED_INT:
340 case Dali::Pixel::DEPTH_FLOAT:
342 return (channel == DEPTH);
345 case Dali::Pixel::DEPTH_STENCIL:
347 return (channel == DEPTH || channel == STENCIL);
350 case Dali::Pixel::INVALID:
351 case Dali::Pixel::COMPRESSED_R11_EAC:
352 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
353 case Dali::Pixel::COMPRESSED_RG11_EAC:
354 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
355 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
356 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
357 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
358 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
359 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
360 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
361 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
362 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
363 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
364 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
365 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
366 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
367 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
368 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
369 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
370 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
371 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
372 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
373 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
374 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
375 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
376 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
377 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
378 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
379 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
380 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
381 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
382 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
383 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
384 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
385 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
386 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
387 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
388 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
389 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
390 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
392 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
396 case Dali::Pixel::CHROMINANCE_U:
397 case Dali::Pixel::CHROMINANCE_V:
399 DALI_LOG_ERROR("Pixel formats for chrominance are not compatible with simple channels.\n");
407 unsigned int ReadChannel(unsigned char* pixelData,
408 Dali::Pixel::Format pixelFormat,
413 case Dali::Pixel::A8:
415 return ReadChannelTable(pixelData, channel, ALPHA_ONLY_OFFSET_TABLE);
417 case Dali::Pixel::L8:
419 return ReadChannelTable(pixelData, channel, LUMINANCE_ONLY_OFFSET_TABLE);
421 case Dali::Pixel::LA88:
423 return ReadChannelTable(pixelData, channel, LUMINANCE_ALPHA_OFFSET_TABLE);
425 case Dali::Pixel::RGB565:
427 return ReadChannel565(pixelData, channel, RED, GREEN, BLUE);
430 case Dali::Pixel::BGR565:
432 return ReadChannel565(pixelData, channel, BLUE, GREEN, RED);
435 case Dali::Pixel::RGB888:
436 case Dali::Pixel::RGB8888:
438 return ReadChannelTable(pixelData, channel, RGB_OFFSET_TABLE);
441 case Dali::Pixel::BGR8888:
443 return ReadChannelTable(pixelData, channel, BGR_OFFSET_TABLE);
446 case Dali::Pixel::RGBA8888:
448 return ReadChannelTable(pixelData, channel, RGBA_OFFSET_TABLE);
451 case Dali::Pixel::BGRA8888:
453 return ReadChannelTable(pixelData, channel, BGRA_OFFSET_TABLE);
456 case Dali::Pixel::RGBA4444:
458 return ReadChannel4444(pixelData, channel, RED, GREEN, BLUE, ALPHA);
461 case Dali::Pixel::BGRA4444:
463 return ReadChannel4444(pixelData, channel, BLUE, GREEN, RED, ALPHA);
466 case Dali::Pixel::RGBA5551:
468 return ReadChannel5551(pixelData, channel, RED, GREEN, BLUE, ALPHA);
471 case Dali::Pixel::BGRA5551:
473 return ReadChannel5551(pixelData, channel, BLUE, GREEN, RED, ALPHA);
476 case Dali::Pixel::DEPTH_UNSIGNED_INT:
477 case Dali::Pixel::DEPTH_FLOAT:
478 case Dali::Pixel::DEPTH_STENCIL:
490 void WriteChannel(unsigned char* pixelData,
491 Dali::Pixel::Format pixelFormat,
493 unsigned int channelValue)
497 case Dali::Pixel::A8:
499 WriteChannelTable(pixelData, channel, channelValue, ALPHA_ONLY_OFFSET_TABLE);
502 case Dali::Pixel::L8:
504 WriteChannelTable(pixelData, channel, channelValue, LUMINANCE_ONLY_OFFSET_TABLE);
507 case Dali::Pixel::LA88:
509 WriteChannelTable(pixelData, channel, channelValue, LUMINANCE_ALPHA_OFFSET_TABLE);
512 case Dali::Pixel::RGB565:
514 WriteChannel565(pixelData, channel, channelValue, RED, GREEN, BLUE);
518 case Dali::Pixel::BGR565:
520 WriteChannel565(pixelData, channel, channelValue, BLUE, GREEN, RED);
524 case Dali::Pixel::RGB888:
525 case Dali::Pixel::RGB8888:
527 WriteChannelTable(pixelData, channel, channelValue, RGB_OFFSET_TABLE);
531 case Dali::Pixel::BGR8888:
533 WriteChannelTable(pixelData, channel, channelValue, BGR_OFFSET_TABLE);
537 case Dali::Pixel::RGBA8888:
539 WriteChannelTable(pixelData, channel, channelValue, RGBA_OFFSET_TABLE);
543 case Dali::Pixel::BGRA8888:
545 WriteChannelTable(pixelData, channel, channelValue, BGRA_OFFSET_TABLE);
549 case Dali::Pixel::RGBA4444:
551 WriteChannel4444(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
555 case Dali::Pixel::BGRA4444:
557 WriteChannel4444(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
561 case Dali::Pixel::RGBA5551:
563 WriteChannel5551(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
567 case Dali::Pixel::BGRA5551:
569 WriteChannel5551(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
573 case Dali::Pixel::DEPTH_UNSIGNED_INT:
574 case Dali::Pixel::DEPTH_FLOAT:
575 case Dali::Pixel::DEPTH_STENCIL:
585 void ConvertColorChannelsToRGBA8888(
586 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat, unsigned char* destPixel, int destOffset)
588 int red = ReadChannel(srcPixel + srcOffset, srcFormat, RED);
589 int green = ReadChannel(srcPixel + srcOffset, srcFormat, GREEN);
590 int blue = ReadChannel(srcPixel + srcOffset, srcFormat, BLUE);
593 case Dali::Pixel::RGB565:
594 case Dali::Pixel::BGR565:
596 red = (red << 3) | (red & 0x07);
597 green = (green << 2) | (green & 0x03);
598 blue = (blue << 3) | (blue & 0x07);
601 case Dali::Pixel::RGBA4444:
602 case Dali::Pixel::BGRA4444:
604 red = (red << 4) | (red & 0x0F);
605 green = (green << 4) | (green & 0x0F);
606 blue = (blue << 4) | (blue & 0x0F);
609 case Dali::Pixel::RGBA5551:
610 case Dali::Pixel::BGRA5551:
612 red = (red << 3) | (red & 0x07);
613 green = (green << 3) | (green & 0x07);
614 blue = (blue << 3) | (blue & 0x07);
620 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, RED, red);
621 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, GREEN, green);
622 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
625 int ConvertAlphaChannelToA8(unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat)
627 int alpha = ReadChannel(srcPixel + srcOffset, srcFormat, ALPHA);
628 int destAlpha = alpha;
631 case Pixel::RGBA5551:
632 case Pixel::BGRA5551:
634 destAlpha = (alpha == 0) ? 0 : 255;
637 case Pixel::RGBA4444:
638 case Pixel::BGRA4444:
640 destAlpha = (alpha << 4) | (alpha & 0x0F);
649 } // namespace Adaptor
650 } // namespace Internal