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:
332 return (channel == RED || channel == GREEN || channel == BLUE);
335 case Dali::Pixel::RGBA8888:
336 case Dali::Pixel::BGRA8888:
337 case Dali::Pixel::RGBA4444:
338 case Dali::Pixel::BGRA4444:
339 case Dali::Pixel::RGBA5551:
340 case Dali::Pixel::BGRA5551:
342 return (channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA);
345 case Dali::Pixel::DEPTH_UNSIGNED_INT:
346 case Dali::Pixel::DEPTH_FLOAT:
348 return (channel == DEPTH);
351 case Dali::Pixel::DEPTH_STENCIL:
353 return (channel == DEPTH || channel == STENCIL);
356 case Dali::Pixel::INVALID:
357 case Dali::Pixel::COMPRESSED_R11_EAC:
358 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
359 case Dali::Pixel::COMPRESSED_RG11_EAC:
360 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
361 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
362 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
363 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
364 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
365 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
366 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
367 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
368 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
369 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
370 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
371 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
372 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
373 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
374 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
375 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
376 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
377 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
378 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
379 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
380 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
381 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
382 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
383 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
384 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
385 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
386 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
387 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
388 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
389 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
390 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
391 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
392 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
393 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
394 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
395 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
396 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
398 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
406 unsigned int ReadChannel(unsigned char* pixelData,
407 Dali::Pixel::Format pixelFormat,
412 case Dali::Pixel::A8:
414 return ReadChannel(pixelData, channel, ALPHA_CHANNEL_ONLY);
416 case Dali::Pixel::L8:
418 return ReadChannel(pixelData, channel, LUMINANCE_CHANNEL_ONLY);
420 case Dali::Pixel::LA88:
422 return ReadChannel(pixelData, channel, LUMINANCE_ALPHA_CHANNELS);
424 case Dali::Pixel::RGB565:
426 return ReadChannel565(pixelData, channel, RED, GREEN, BLUE);
429 case Dali::Pixel::BGR565:
431 return ReadChannel565(pixelData, channel, BLUE, GREEN, RED);
434 case Dali::Pixel::RGB888:
435 case Dali::Pixel::RGB8888:
437 return ReadChannel(pixelData, channel, RGB_CHANNELS);
440 case Dali::Pixel::BGR8888:
442 return ReadChannel(pixelData, channel, BGR_CHANNELS);
445 case Dali::Pixel::RGBA8888:
447 return ReadChannel(pixelData, channel, RGBA_CHANNELS);
450 case Dali::Pixel::BGRA8888:
452 return ReadChannel(pixelData, channel, BGRA_CHANNELS);
455 case Dali::Pixel::RGBA4444:
457 return ReadChannel4444(pixelData, channel, RED, GREEN, BLUE, ALPHA);
460 case Dali::Pixel::BGRA4444:
462 return ReadChannel4444(pixelData, channel, BLUE, GREEN, RED, ALPHA);
465 case Dali::Pixel::RGBA5551:
467 return ReadChannel5551(pixelData, channel, RED, GREEN, BLUE, ALPHA);
470 case Dali::Pixel::BGRA5551:
472 return ReadChannel5551(pixelData, channel, BLUE, GREEN, RED, ALPHA);
475 case Dali::Pixel::DEPTH_UNSIGNED_INT:
476 case Dali::Pixel::DEPTH_FLOAT:
477 case Dali::Pixel::DEPTH_STENCIL:
489 void WriteChannel(unsigned char* pixelData,
490 Dali::Pixel::Format pixelFormat,
492 unsigned int channelValue)
496 case Dali::Pixel::A8:
498 WriteChannel(pixelData, channel, channelValue, ALPHA_CHANNEL_ONLY);
501 case Dali::Pixel::L8:
503 WriteChannel(pixelData, channel, channelValue, LUMINANCE_CHANNEL_ONLY);
506 case Dali::Pixel::LA88:
508 WriteChannel(pixelData, channel, channelValue, LUMINANCE_ALPHA_CHANNELS);
511 case Dali::Pixel::RGB565:
513 WriteChannel565(pixelData, channel, channelValue, RED, GREEN, BLUE);
517 case Dali::Pixel::BGR565:
519 WriteChannel565(pixelData, channel, channelValue, BLUE, GREEN, RED);
523 case Dali::Pixel::RGB888:
524 case Dali::Pixel::RGB8888:
526 WriteChannel(pixelData, channel, channelValue, RGB_CHANNELS);
530 case Dali::Pixel::BGR8888:
532 WriteChannel(pixelData, channel, channelValue, BGR_CHANNELS);
536 case Dali::Pixel::RGBA8888:
538 WriteChannel(pixelData, channel, channelValue, RGBA_CHANNELS);
542 case Dali::Pixel::BGRA8888:
544 WriteChannel(pixelData, channel, channelValue, BGRA_CHANNELS);
548 case Dali::Pixel::RGBA4444:
550 WriteChannel4444(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
554 case Dali::Pixel::BGRA4444:
556 WriteChannel4444(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
560 case Dali::Pixel::RGBA5551:
562 WriteChannel5551(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
566 case Dali::Pixel::BGRA5551:
568 WriteChannel5551(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
572 case Dali::Pixel::DEPTH_UNSIGNED_INT:
573 case Dali::Pixel::DEPTH_FLOAT:
574 case Dali::Pixel::DEPTH_STENCIL:
584 void ConvertColorChannelsToRGBA8888(
585 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat, unsigned char* destPixel, int destOffset)
587 int red = ReadChannel(srcPixel + srcOffset, srcFormat, RED);
588 int green = ReadChannel(srcPixel + srcOffset, srcFormat, GREEN);
589 int blue = ReadChannel(srcPixel + srcOffset, srcFormat, BLUE);
592 case Dali::Pixel::RGB565:
593 case Dali::Pixel::BGR565:
595 red = (red << 3) | (red & 0x07);
596 green = (green << 2) | (green & 0x03);
597 blue = (blue << 3) | (blue & 0x07);
600 case Dali::Pixel::RGBA4444:
601 case Dali::Pixel::BGRA4444:
603 red = (red << 4) | (red & 0x0F);
604 green = (green << 4) | (green & 0x0F);
605 blue = (blue << 4) | (blue & 0x0F);
608 case Dali::Pixel::RGBA5551:
609 case Dali::Pixel::BGRA5551:
611 red = (red << 3) | (red & 0x07);
612 green = (green << 3) | (green & 0x07);
613 blue = (blue << 3) | (blue & 0x07);
619 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, RED, red);
620 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, GREEN, green);
621 WriteChannel(destPixel + destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
624 int ConvertAlphaChannelToA8(unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat)
626 int alpha = ReadChannel(srcPixel + srcOffset, srcFormat, ALPHA);
627 int destAlpha = alpha;
630 case Pixel::RGBA5551:
631 case Pixel::BGRA5551:
633 destAlpha = (alpha == 0) ? 0 : 255;
636 case Pixel::RGBA4444:
637 case Pixel::BGRA4444:
639 destAlpha = (alpha << 4) | (alpha & 0x0F);
648 } // namespace Adaptor
649 } // namespace Internal