2 * Copyright (c) 2020 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/public-api/images/pixel.h>
22 #include <dali/integration-api/debug.h>
34 constexpr Channel ALPHA_CHANNEL_ONLY[] = {ALPHA};
35 constexpr Channel LUMINANCE_CHANNEL_ONLY[] = {LUMINANCE};
36 constexpr Channel LUMINANCE_ALPHA_CHANNELS[] = {LUMINANCE, ALPHA};
37 constexpr Channel RGB_CHANNELS[] = {RED, GREEN, BLUE};
38 constexpr Channel BGR_CHANNELS[] = {BLUE, GREEN, RED};
39 constexpr Channel RGBA_CHANNELS[] = {RED, GREEN, BLUE, ALPHA};
40 constexpr Channel BGRA_CHANNELS[] = {BLUE, GREEN, RED, ALPHA};
43 * @brief Template to Read from a buffer with pixel formats that have one byte per channel.
45 * @tparam NumberOfChannels The number of channels to check
46 * @param pixelData The pixel data to retrieve the value from
47 * @param channel The channel we're after
48 * @param channels The array of channels in the pixel format
49 * @return The value of the required channel
51 template<size_t NumberOfChannels>
52 unsigned int ReadChannel(unsigned char* pixelData, Channel channel, const Channel (&channels)[NumberOfChannels])
56 for(auto current : channels)
58 if( channel == current )
60 retVal = static_cast<unsigned int>(*(pixelData + num));
69 * @brief Template to Write to a buffer with pixel formats that have one byte per channel.
71 * @tparam NumberOfChannels The number of channels to check
72 * @param pixelData The pixel data to write the value to
73 * @param channel The channel we're after
74 * @param channelValue The value of the channel to set
75 * @param channels The array of channels in the pixel format
77 template<size_t NumberOfChannels>
78 void WriteChannel(unsigned char* pixelData, Channel channel, unsigned int channelValue, const Channel (&channels)[NumberOfChannels])
81 for( auto current : channels )
83 if( channel == current )
85 *(pixelData + num) = static_cast<unsigned char>( channelValue & 0xFF );
93 * @brief Reads from buffers with a pixel format of 565.
95 * @param pixelData The pixel data to read from
96 * @param channel The channel we're after
97 * @param one The first channel of the pixel format
98 * @param two The second channel of the pixel format
99 * @param three The third channel of the pixel format
100 * @return The value of the required channel
102 unsigned int ReadChannel565(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three)
106 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
108 else if( channel == two )
110 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
111 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
113 else if( channel == three )
115 return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
121 * @brief Writes to the buffer with a pixel format of 565.
123 * @param pixelData The pixel data to write to
124 * @param channel The channel we're after
125 * @param channelValue The value to write
126 * @param one The first channel of the pixel format
127 * @param two The second channel of the pixel format
128 * @param three The third channel of the pixel format
130 void WriteChannel565(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three)
134 *pixelData &= static_cast<unsigned char>( ~0xF8 );
135 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
137 else if( channel == two )
139 *pixelData &= static_cast<unsigned char>( ~0x07 );
140 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
142 *(pixelData+1) &= static_cast<unsigned char>( ~0xE0 );
143 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
145 else if( channel == three )
147 *(pixelData+1) &= static_cast<unsigned char>( ~0x1F );
148 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
153 * @brief Reads from buffers with a pixel format of 4444.
155 * @param pixelData The pixel data to read from
156 * @param channel The channel we're after
157 * @param one The first channel of the pixel format
158 * @param two The second channel of the pixel format
159 * @param three The third channel of the pixel format
160 * @param four The fourth channel of the pixel format
163 unsigned int ReadChannel4444(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
167 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
169 else if( channel == two )
171 return (static_cast<unsigned int>(*pixelData) & 0x0F);
173 else if( channel == three )
175 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
177 else if( channel == four )
179 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
185 * @brief Writes to the buffer with a pixel format of 565.
187 * @param pixelData The pixel data to write to
188 * @param channel The channel we're after
189 * @param channelValue The value to write
190 * @param one The first channel of the pixel format
191 * @param two The second channel of the pixel format
192 * @param three The third channel of the pixel format
193 * @param four The fourth channel of the pixel format
195 void WriteChannel4444(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
199 *pixelData &= static_cast<unsigned char>( ~0xF0 );
200 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
202 else if( channel == two )
204 *pixelData &= static_cast<unsigned char>( ~0x0F );
205 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
207 else if( channel == three )
209 *(pixelData+1) &= static_cast<unsigned char>( ~0xF0 );
210 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
212 else if( channel == four )
214 *(pixelData+1) &= static_cast<unsigned char>( ~0x0F );
215 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
220 * @brief Reads from buffers with a pixel format of 5551.
222 * @param pixelData The pixel data to read from
223 * @param channel The channel we're after
224 * @param one The first channel of the pixel format
225 * @param two The second channel of the pixel format
226 * @param three The third channel of the pixel format
227 * @param four The fourth channel of the pixel format
230 unsigned int ReadChannel5551(unsigned char* pixelData, Channel channel, Channel one, Channel two, Channel three, Channel four)
234 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
236 else if( channel == two )
238 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
239 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
241 else if( channel == three )
243 return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
245 else if( channel == four )
247 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
253 * @brief Writes to the buffer with a pixel format of 5551.
255 * @param pixelData The pixel data to write to
256 * @param channel The channel we're after
257 * @param channelValue The value to write
258 * @param one The first channel of the pixel format
259 * @param two The second channel of the pixel format
260 * @param three The third channel of the pixel format
261 * @param four The fourth channel of the pixel format
263 void WriteChannel5551(unsigned char* pixelData, Channel channel, unsigned int channelValue, Channel one, Channel two, Channel three, Channel four)
269 *pixelData &= static_cast<unsigned char>( ~0xF8 );
270 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
272 else if( channel == two )
274 *pixelData &= static_cast<unsigned char>( ~0x07 );
275 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
277 *(pixelData+1) &= static_cast<unsigned char>( ~0xC0 );
278 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
280 else if( channel == three )
282 *(pixelData+1) &= static_cast<unsigned char>( ~0x3E );
283 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
285 else if( channel == four )
287 *(pixelData+1) &= static_cast<unsigned char>( ~0x01 );
288 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
292 } // unnamed namespace
296 unsigned int bitShift;
297 unsigned int bitMask;
311 bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel )
315 case Dali::Pixel::A8:
317 return (channel == ALPHA);
319 case Dali::Pixel::L8:
321 return (channel == LUMINANCE);
323 case Dali::Pixel::LA88:
325 return ( channel == LUMINANCE || channel == ALPHA );
327 case Dali::Pixel::RGB565:
328 case Dali::Pixel::BGR565:
329 case Dali::Pixel::RGB888:
330 case Dali::Pixel::RGB8888:
331 case Dali::Pixel::BGR8888:
332 case Dali::Pixel::RGB16F:
333 case Dali::Pixel::RGB32F:
335 return ( channel == RED || channel == GREEN || channel == BLUE );
338 case Dali::Pixel::RGBA8888:
339 case Dali::Pixel::BGRA8888:
340 case Dali::Pixel::RGBA4444:
341 case Dali::Pixel::BGRA4444:
342 case Dali::Pixel::RGBA5551:
343 case Dali::Pixel::BGRA5551:
345 return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
348 case Dali::Pixel::DEPTH_UNSIGNED_INT:
349 case Dali::Pixel::DEPTH_FLOAT:
351 return ( channel == DEPTH );
354 case Dali::Pixel::DEPTH_STENCIL:
356 return ( channel == DEPTH || channel == STENCIL );
359 case Dali::Pixel::INVALID:
360 case Dali::Pixel::COMPRESSED_R11_EAC:
361 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
362 case Dali::Pixel::COMPRESSED_RG11_EAC:
363 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
364 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
365 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
366 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
367 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
368 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
369 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
370 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
371 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
372 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
373 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
374 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
375 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
376 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
377 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
378 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
379 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
380 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
381 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
382 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
383 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
384 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
385 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
386 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
387 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
388 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
389 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
390 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
391 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
392 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
393 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
394 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
395 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
396 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
397 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
398 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
399 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
401 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
409 unsigned int ReadChannel( unsigned char* pixelData,
410 Dali::Pixel::Format pixelFormat,
415 case Dali::Pixel::A8:
417 return ReadChannel(pixelData, channel, ALPHA_CHANNEL_ONLY);
419 case Dali::Pixel::L8:
421 return ReadChannel(pixelData, channel, LUMINANCE_CHANNEL_ONLY);
423 case Dali::Pixel::LA88:
425 return ReadChannel(pixelData, channel, LUMINANCE_ALPHA_CHANNELS);
427 case Dali::Pixel::RGB565:
429 return ReadChannel565(pixelData, channel, RED, GREEN, BLUE);
432 case Dali::Pixel::BGR565:
434 return ReadChannel565(pixelData, channel, BLUE, GREEN, RED);
437 case Dali::Pixel::RGB888:
438 case Dali::Pixel::RGB8888:
440 return ReadChannel(pixelData, channel, RGB_CHANNELS);
443 case Dali::Pixel::BGR8888:
445 return ReadChannel(pixelData, channel, BGR_CHANNELS);
448 case Dali::Pixel::RGBA8888:
450 return ReadChannel(pixelData, channel, RGBA_CHANNELS);
453 case Dali::Pixel::BGRA8888:
455 return ReadChannel(pixelData, channel, BGRA_CHANNELS);
458 case Dali::Pixel::RGBA4444:
460 return ReadChannel4444(pixelData, channel, RED, GREEN, BLUE, ALPHA);
463 case Dali::Pixel::BGRA4444:
465 return ReadChannel4444(pixelData, channel, BLUE, GREEN, RED, ALPHA);
468 case Dali::Pixel::RGBA5551:
470 return ReadChannel5551(pixelData, channel, RED, GREEN, BLUE, ALPHA);
473 case Dali::Pixel::BGRA5551:
475 return ReadChannel5551(pixelData, channel, BLUE, GREEN, RED, ALPHA);
478 case Dali::Pixel::DEPTH_UNSIGNED_INT:
479 case Dali::Pixel::DEPTH_FLOAT:
480 case Dali::Pixel::DEPTH_STENCIL:
492 void WriteChannel( unsigned char* pixelData,
493 Dali::Pixel::Format pixelFormat,
495 unsigned int channelValue )
499 case Dali::Pixel::A8:
501 WriteChannel(pixelData, channel, channelValue, ALPHA_CHANNEL_ONLY);
504 case Dali::Pixel::L8:
506 WriteChannel(pixelData, channel, channelValue, LUMINANCE_CHANNEL_ONLY);
509 case Dali::Pixel::LA88:
511 WriteChannel(pixelData, channel, channelValue, LUMINANCE_ALPHA_CHANNELS);
514 case Dali::Pixel::RGB565:
516 WriteChannel565(pixelData, channel, channelValue, RED, GREEN, BLUE);
520 case Dali::Pixel::BGR565:
522 WriteChannel565(pixelData, channel, channelValue, BLUE, GREEN, RED);
526 case Dali::Pixel::RGB888:
527 case Dali::Pixel::RGB8888:
529 WriteChannel(pixelData, channel, channelValue, RGB_CHANNELS);
533 case Dali::Pixel::BGR8888:
535 WriteChannel(pixelData, channel, channelValue, BGR_CHANNELS);
539 case Dali::Pixel::RGBA8888:
541 WriteChannel(pixelData, channel, channelValue, RGBA_CHANNELS);
545 case Dali::Pixel::BGRA8888:
547 WriteChannel(pixelData, channel, channelValue, BGRA_CHANNELS);
551 case Dali::Pixel::RGBA4444:
553 WriteChannel4444(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
557 case Dali::Pixel::BGRA4444:
559 WriteChannel4444(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
563 case Dali::Pixel::RGBA5551:
565 WriteChannel5551(pixelData, channel, channelValue, RED, GREEN, BLUE, ALPHA);
569 case Dali::Pixel::BGRA5551:
571 WriteChannel5551(pixelData, channel, channelValue, BLUE, GREEN, RED, ALPHA);
575 case Dali::Pixel::DEPTH_UNSIGNED_INT:
576 case Dali::Pixel::DEPTH_FLOAT:
577 case Dali::Pixel::DEPTH_STENCIL:
587 void ConvertColorChannelsToRGBA8888(
588 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
589 unsigned char* destPixel, int destOffset )
591 int red = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
592 int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
593 int blue = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
596 case Dali::Pixel::RGB565:
597 case Dali::Pixel::BGR565:
599 red = (red<<3) | (red & 0x07);
600 green = (green << 2) | (green & 0x03);
601 blue = (blue<<3) | (blue & 0x07);
604 case Dali::Pixel::RGBA4444:
605 case Dali::Pixel::BGRA4444:
607 red = (red<<4) | (red&0x0F);
608 green = (green<<4) | (green&0x0F);
609 blue = (blue<<4) | (blue&0x0F);
612 case Dali::Pixel::RGBA5551:
613 case Dali::Pixel::BGRA5551:
615 red = (red<<3) | (red&0x07);
616 green = (green<<3) | (green&0x07);
617 blue = (blue<<3) | (blue&0x07);
623 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
624 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
625 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
629 int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
631 int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
632 int destAlpha = alpha;
635 case Pixel::RGBA5551:
636 case Pixel::BGRA5551:
638 destAlpha = (alpha==0)?0:255;
641 case Pixel::RGBA4444:
642 case Pixel::BGRA4444:
644 destAlpha = (alpha<<4) | (alpha&0x0F);