2 * Copyright (c) 2021 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>
32 constexpr Channel ALPHA_CHANNEL_ONLY[] = {ALPHA};
33 constexpr Channel LUMINANCE_CHANNEL_ONLY[] = {LUMINANCE};
34 constexpr Channel LUMINANCE_ALPHA_CHANNELS[] = {LUMINANCE, ALPHA};
35 constexpr Channel RGB_CHANNELS[] = {RED, GREEN, BLUE};
36 constexpr Channel BGR_CHANNELS[] = {BLUE, GREEN, RED};
37 constexpr Channel RGBA_CHANNELS[] = {RED, GREEN, BLUE, ALPHA};
38 constexpr Channel BGRA_CHANNELS[] = {BLUE, GREEN, RED, ALPHA};
41 * @brief Template to Read from a buffer with pixel formats that have one byte per channel.
43 * @tparam NumberOfChannels The number of channels to check
44 * @param pixelData The pixel data to retrieve the value from
45 * @param channel The channel we're after
46 * @param channels The array of channels in the pixel format
47 * @return The value of the required channel
49 template<size_t NumberOfChannels>
50 unsigned int ReadChannel(unsigned char* pixelData, Channel channel, const Channel (&channels)[NumberOfChannels])
54 for(auto current : channels)
56 if(channel == current)
58 retVal = static_cast<unsigned int>(*(pixelData + num));
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 channels The array of channels in the pixel format
75 template<size_t NumberOfChannels>
76 void WriteChannel(unsigned char* pixelData, Channel channel, unsigned int channelValue, const Channel (&channels)[NumberOfChannels])
79 for(auto current : channels)
81 if(channel == current)
83 *(pixelData + num) = static_cast<unsigned char>(channelValue & 0xFF);
91 * @brief Reads from buffers with a pixel format of 565.
93 * @param pixelData The pixel data to read from
94 * @param channel The channel we're after
95 * @param one The first channel of the pixel format
96 * @param two The second channel of the pixel format
97 * @param three The third channel of the pixel format
98 * @return The value of the required channel
100 unsigned int ReadChannel565(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three)
104 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
106 else if(channel == two)
108 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
109 ((static_cast<unsigned int>(*(pixelData + 1)) & 0xE0) >> 5);
111 else if(channel == three)
113 return static_cast<unsigned int>(*(pixelData + 1)) & 0x1F;
119 * @brief Writes to the buffer with a pixel format of 565.
121 * @param pixelData The pixel data to write to
122 * @param channel The channel we're after
123 * @param channelValue The value to write
124 * @param one The first channel of the pixel format
125 * @param two The second channel of the pixel format
126 * @param three The third channel of the pixel format
128 void WriteChannel565(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three)
132 *pixelData &= static_cast<unsigned char>(~0xF8);
133 *pixelData |= static_cast<unsigned char>((channelValue << 3) & 0xF8);
135 else if(channel == two)
137 *pixelData &= static_cast<unsigned char>(~0x07);
138 *pixelData |= static_cast<unsigned char>((channelValue >> 3) & 0x07);
140 *(pixelData + 1) &= static_cast<unsigned char>(~0xE0);
141 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 5) & 0xE0);
143 else if(channel == three)
145 *(pixelData + 1) &= static_cast<unsigned char>(~0x1F);
146 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x1F);
151 * @brief Reads from buffers with a pixel format of 4444.
153 * @param pixelData The pixel data to read from
154 * @param channel The channel we're after
155 * @param one The first channel of the pixel format
156 * @param two The second channel of the pixel format
157 * @param three The third channel of the pixel format
158 * @param four The fourth channel of the pixel format
161 unsigned int ReadChannel4444(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
165 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
167 else if(channel == two)
169 return (static_cast<unsigned int>(*pixelData) & 0x0F);
171 else if(channel == three)
173 return (static_cast<unsigned int>(*(pixelData + 1)) & 0xF0) >> 4;
175 else if(channel == four)
177 return (static_cast<unsigned int>(*(pixelData + 1)) & 0x0F);
183 * @brief Writes to the buffer with a pixel format of 565.
185 * @param pixelData The pixel data to write to
186 * @param channel The channel we're after
187 * @param channelValue The value to write
188 * @param one The first channel of the pixel format
189 * @param two The second channel of the pixel format
190 * @param three The third channel of the pixel format
191 * @param four The fourth channel of the pixel format
193 void WriteChannel4444(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
197 *pixelData &= static_cast<unsigned char>(~0xF0);
198 *pixelData |= static_cast<unsigned char>((channelValue << 4) & 0xF0);
200 else if(channel == two)
202 *pixelData &= static_cast<unsigned char>(~0x0F);
203 *pixelData |= static_cast<unsigned char>(channelValue & 0x0F);
205 else if(channel == three)
207 *(pixelData + 1) &= static_cast<unsigned char>(~0xF0);
208 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 4) & 0xF0);
210 else if(channel == four)
212 *(pixelData + 1) &= static_cast<unsigned char>(~0x0F);
213 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x0F);
218 * @brief Reads from buffers with a pixel format of 5551.
220 * @param pixelData The pixel data to read from
221 * @param channel The channel we're after
222 * @param one The first channel of the pixel format
223 * @param two The second channel of the pixel format
224 * @param three The third channel of the pixel format
225 * @param four The fourth channel of the pixel format
228 unsigned int ReadChannel5551(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
232 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
234 else if(channel == two)
236 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
237 ((static_cast<unsigned int>(*(pixelData + 1)) & 0xC0) >> 6);
239 else if(channel == three)
241 return (static_cast<unsigned int>(*(pixelData + 1)) & 0x3E) >> 1;
243 else if(channel == four)
245 return static_cast<unsigned int>(*(pixelData + 1)) & 0x01;
251 * @brief Writes to the buffer with a pixel format of 5551.
253 * @param pixelData The pixel data to write to
254 * @param channel The channel we're after
255 * @param channelValue The value to write
256 * @param one The first channel of the pixel format
257 * @param two The second channel of the pixel format
258 * @param three The third channel of the pixel format
259 * @param four The fourth channel of the pixel format
261 void WriteChannel5551(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
267 *pixelData &= static_cast<unsigned char>(~0xF8);
268 *pixelData |= static_cast<unsigned char>((channelValue << 3) & 0xF8);
270 else if(channel == two)
272 *pixelData &= static_cast<unsigned char>(~0x07);
273 *pixelData |= static_cast<unsigned char>((channelValue >> 2) & 0x07);
275 *(pixelData + 1) &= static_cast<unsigned char>(~0xC0);
276 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 6) & 0xC0);
278 else if(channel == three)
280 *(pixelData + 1) &= static_cast<unsigned char>(~0x3E);
281 *(pixelData + 1) |= static_cast<unsigned char>((channelValue << 1) & 0x3E);
283 else if(channel == four)
285 *(pixelData + 1) &= static_cast<unsigned char>(~0x01);
286 *(pixelData + 1) |= static_cast<unsigned char>(channelValue & 0x01);
290 } // unnamed namespace
294 unsigned int bitShift;
295 unsigned int bitMask;
308 bool HasChannel(Dali::Pixel::Format pixelFormat, Channel channel)
312 case Dali::Pixel::A8:
314 return (channel == ALPHA);
316 case Dali::Pixel::L8:
318 return (channel == LUMINANCE);
320 case Dali::Pixel::LA88:
322 return (channel == LUMINANCE || channel == ALPHA);
324 case Dali::Pixel::RGB565:
325 case Dali::Pixel::BGR565:
326 case Dali::Pixel::RGB888:
327 case Dali::Pixel::RGB8888:
328 case Dali::Pixel::BGR8888:
329 case Dali::Pixel::RGB16F:
330 case Dali::Pixel::RGB32F:
331 case Dali::Pixel::R11G11B10F:
333 return (channel == RED || channel == GREEN || channel == BLUE);
336 case Dali::Pixel::RGBA8888:
337 case Dali::Pixel::BGRA8888:
338 case Dali::Pixel::RGBA4444:
339 case Dali::Pixel::BGRA4444:
340 case Dali::Pixel::RGBA5551:
341 case Dali::Pixel::BGRA5551:
343 return (channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA);
346 case Dali::Pixel::DEPTH_UNSIGNED_INT:
347 case Dali::Pixel::DEPTH_FLOAT:
349 return (channel == DEPTH);
352 case Dali::Pixel::DEPTH_STENCIL:
354 return (channel == DEPTH || channel == STENCIL);
357 case Dali::Pixel::INVALID:
358 case Dali::Pixel::COMPRESSED_R11_EAC:
359 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
360 case Dali::Pixel::COMPRESSED_RG11_EAC:
361 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
362 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
363 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
364 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
365 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
366 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
367 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
368 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
369 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
370 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
371 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
372 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
373 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
374 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
375 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
376 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
377 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
378 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
379 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
380 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
381 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
382 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
383 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
384 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
385 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
386 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
387 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
388 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
389 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
390 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
391 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
392 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
393 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
394 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
395 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
396 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
397 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
399 DALI_LOG_ERROR("Pixel formats for compressed images 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 ReadChannel(pixelData, channel, ALPHA_CHANNEL_ONLY);
417 case Dali::Pixel::L8:
419 return ReadChannel(pixelData, channel, LUMINANCE_CHANNEL_ONLY);
421 case Dali::Pixel::LA88:
423 return ReadChannel(pixelData, channel, LUMINANCE_ALPHA_CHANNELS);
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 ReadChannel(pixelData, channel, RGB_CHANNELS);
441 case Dali::Pixel::BGR8888:
443 return ReadChannel(pixelData, channel, BGR_CHANNELS);
446 case Dali::Pixel::RGBA8888:
448 return ReadChannel(pixelData, channel, RGBA_CHANNELS);
451 case Dali::Pixel::BGRA8888:
453 return ReadChannel(pixelData, channel, BGRA_CHANNELS);
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 WriteChannel(pixelData, channel, channelValue, ALPHA_CHANNEL_ONLY);
502 case Dali::Pixel::L8:
504 WriteChannel(pixelData, channel, channelValue, LUMINANCE_CHANNEL_ONLY);
507 case Dali::Pixel::LA88:
509 WriteChannel(pixelData, channel, channelValue, LUMINANCE_ALPHA_CHANNELS);
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 WriteChannel(pixelData, channel, channelValue, RGB_CHANNELS);
531 case Dali::Pixel::BGR8888:
533 WriteChannel(pixelData, channel, channelValue, BGR_CHANNELS);
537 case Dali::Pixel::RGBA8888:
539 WriteChannel(pixelData, channel, channelValue, RGBA_CHANNELS);
543 case Dali::Pixel::BGRA8888:
545 WriteChannel(pixelData, channel, channelValue, BGRA_CHANNELS);
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