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>
33 unsigned int bitShift;
48 bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel )
54 return (channel == ALPHA);
58 return (channel == LUMINANCE);
60 case Dali::Pixel::LA88:
62 return ( channel == LUMINANCE || channel == ALPHA );
64 case Dali::Pixel::RGB565:
65 case Dali::Pixel::BGR565:
66 case Dali::Pixel::RGB888:
67 case Dali::Pixel::RGB8888:
68 case Dali::Pixel::BGR8888:
69 case Dali::Pixel::RGB16F:
70 case Dali::Pixel::RGB32F:
72 return ( channel == RED || channel == GREEN || channel == BLUE );
75 case Dali::Pixel::RGBA8888:
76 case Dali::Pixel::BGRA8888:
77 case Dali::Pixel::RGBA4444:
78 case Dali::Pixel::BGRA4444:
79 case Dali::Pixel::RGBA5551:
80 case Dali::Pixel::BGRA5551:
82 return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
85 case Dali::Pixel::DEPTH_UNSIGNED_INT:
86 case Dali::Pixel::DEPTH_FLOAT:
88 return ( channel == DEPTH );
91 case Dali::Pixel::DEPTH_STENCIL:
93 return ( channel == DEPTH || channel == STENCIL );
96 case Dali::Pixel::INVALID:
97 case Dali::Pixel::COMPRESSED_R11_EAC:
98 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
99 case Dali::Pixel::COMPRESSED_RG11_EAC:
100 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
101 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
102 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
103 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
104 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
105 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
106 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
107 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
108 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
109 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
110 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
111 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
112 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
113 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
114 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
115 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
116 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
117 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
118 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
119 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
120 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
121 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
122 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
123 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
124 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
125 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
126 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
127 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
128 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
129 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
130 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
131 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
132 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
133 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
134 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
135 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
136 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
138 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
146 unsigned int ReadChannel( unsigned char* pixelData,
147 Dali::Pixel::Format pixelFormat,
152 case Dali::Pixel::A8:
154 if( channel == ALPHA )
156 return static_cast<unsigned int>(*pixelData);
160 case Dali::Pixel::L8:
162 if( channel == LUMINANCE )
164 return static_cast<unsigned int>(*pixelData);
168 case Dali::Pixel::LA88:
170 if( channel == LUMINANCE )
172 return static_cast<unsigned int>(*pixelData);
174 else if( channel == ALPHA )
176 return static_cast<unsigned int>(*(pixelData+1));
180 case Dali::Pixel::RGB565:
184 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
186 else if( channel == GREEN )
188 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
189 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
191 else if( channel == BLUE )
193 return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
198 case Dali::Pixel::BGR565:
200 if( channel == BLUE )
202 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
204 else if( channel == GREEN )
206 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
207 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
209 else if( channel == RED )
211 return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
216 case Dali::Pixel::RGB888:
217 case Dali::Pixel::RGB8888:
221 return static_cast<unsigned int>(*pixelData);
223 else if( channel == GREEN )
225 return static_cast<unsigned int>(*(pixelData+1));
227 else if( channel == BLUE )
229 return static_cast<unsigned int>(*(pixelData+2));
234 case Dali::Pixel::BGR8888:
236 if( channel == BLUE )
238 return static_cast<unsigned int>(*pixelData);
240 else if( channel == GREEN )
242 return static_cast<unsigned int>(*(pixelData+1));
244 else if( channel == RED )
246 return static_cast<unsigned int>(*(pixelData+2));
251 case Dali::Pixel::RGBA8888:
255 return static_cast<unsigned int>(*pixelData);
257 else if( channel == GREEN )
259 return static_cast<unsigned int>(*(pixelData+1));
261 else if( channel == BLUE )
263 return static_cast<unsigned int>(*(pixelData+2));
265 else if( channel == ALPHA )
267 return static_cast<unsigned int>(*(pixelData+3));
272 case Dali::Pixel::BGRA8888:
274 if( channel == BLUE )
276 return static_cast<unsigned int>(*pixelData);
278 else if( channel == GREEN )
280 return static_cast<unsigned int>(*(pixelData+1));
282 else if( channel == RED )
284 return static_cast<unsigned int>(*(pixelData+2));
286 else if( channel == ALPHA )
288 return static_cast<unsigned int>(*(pixelData+3));
293 case Dali::Pixel::RGBA4444:
297 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
299 else if( channel == GREEN )
301 return (static_cast<unsigned int>(*pixelData) & 0x0F);
303 else if( channel == BLUE )
305 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
307 else if( channel == ALPHA )
309 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
314 case Dali::Pixel::BGRA4444:
316 if( channel == BLUE )
318 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
320 else if( channel == GREEN )
322 return (static_cast<unsigned int>(*pixelData) & 0x0F);
324 else if( channel == RED )
326 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
328 else if( channel == ALPHA )
330 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
335 case Dali::Pixel::RGBA5551:
339 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
341 else if( channel == GREEN )
343 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
344 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
346 else if( channel == BLUE )
348 return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
350 else if( channel == ALPHA )
352 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
358 case Dali::Pixel::BGRA5551:
360 if( channel == BLUE )
362 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
364 else if( channel == GREEN )
366 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
367 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
369 else if( channel == RED )
371 return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
373 else if( channel == ALPHA )
375 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
381 case Dali::Pixel::DEPTH_UNSIGNED_INT:
382 case Dali::Pixel::DEPTH_FLOAT:
383 case Dali::Pixel::DEPTH_STENCIL:
395 void WriteChannel( unsigned char* pixelData,
396 Dali::Pixel::Format pixelFormat,
398 unsigned int channelValue )
402 case Dali::Pixel::A8:
404 if( channel == ALPHA )
406 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
410 case Dali::Pixel::L8:
412 if( channel == LUMINANCE )
414 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
418 case Dali::Pixel::LA88:
420 if( channel == LUMINANCE )
422 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
424 else if( channel == ALPHA )
426 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
430 case Dali::Pixel::RGB565:
434 *pixelData &= static_cast<unsigned char>( ~0xF8 );
435 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
437 else if( channel == GREEN )
439 *pixelData &= static_cast<unsigned char>( ~0x07 );
440 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
442 *(pixelData+1) &= static_cast<unsigned char>( ~0xE0 );
443 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
445 else if( channel == BLUE )
447 *(pixelData+1) &= static_cast<unsigned char>( ~0x1F );
448 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
453 case Dali::Pixel::BGR565:
455 if( channel == BLUE )
457 *pixelData &= static_cast<unsigned char>( ~0xF8 );
458 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
460 else if( channel == GREEN )
462 *pixelData &= static_cast<unsigned char>( ~0x07 );
463 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
465 *(pixelData+1) &= static_cast<unsigned char>( ~0xE0 );
466 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
468 else if( channel == RED )
470 *(pixelData+1) &= static_cast<unsigned char>( ~0x1F );
471 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
476 case Dali::Pixel::RGB888:
477 case Dali::Pixel::RGB8888:
481 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
483 else if( channel == GREEN )
485 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
487 else if( channel == BLUE )
489 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
494 case Dali::Pixel::BGR8888:
496 if( channel == BLUE )
498 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
500 else if( channel == GREEN )
502 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
504 else if( channel == RED )
506 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
511 case Dali::Pixel::RGBA8888:
515 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
517 else if( channel == GREEN )
519 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
521 else if( channel == BLUE )
523 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
525 else if( channel == ALPHA )
527 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
532 case Dali::Pixel::BGRA8888:
534 if( channel == BLUE )
536 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
538 else if( channel == GREEN )
540 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
542 else if( channel == RED )
544 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
546 else if( channel == ALPHA )
548 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
553 case Dali::Pixel::RGBA4444:
557 *pixelData &= static_cast<unsigned char>( ~0xF0 );
558 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
560 else if( channel == GREEN )
562 *pixelData &= static_cast<unsigned char>( ~0x0F );
563 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
565 else if( channel == BLUE )
567 *(pixelData+1) &= static_cast<unsigned char>( ~0xF0 );
568 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
570 else if( channel == ALPHA )
572 *(pixelData+1) &= static_cast<unsigned char>( ~0x0F );
573 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
578 case Dali::Pixel::BGRA4444:
580 if( channel == BLUE )
582 *pixelData &= static_cast<unsigned char>( ~0xF0 );
583 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
585 else if( channel == GREEN )
587 *pixelData &= static_cast<unsigned char>( ~0x0F );
588 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
590 else if( channel == RED )
592 *(pixelData+1) &= static_cast<unsigned char>( ~0xF0 );
593 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
595 else if( channel == ALPHA )
597 *(pixelData+1) &= static_cast<unsigned char>( ~0x0F );
598 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
603 case Dali::Pixel::RGBA5551:
609 *pixelData &= static_cast<unsigned char>( ~0xF8 );
610 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
612 else if( channel == GREEN )
614 *pixelData &= static_cast<unsigned char>( ~0x07 );
615 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
617 *(pixelData+1) &= static_cast<unsigned char>( ~0xC0 );
618 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
620 else if( channel == BLUE )
622 *(pixelData+1) &= static_cast<unsigned char>( ~0x3E );
623 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
625 else if( channel == ALPHA )
627 *(pixelData+1) &= static_cast<unsigned char>( ~0x01 );
628 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
633 case Dali::Pixel::BGRA5551:
635 if( channel == BLUE )
637 *pixelData &= static_cast<unsigned char>( ~0xF8 );
638 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
640 else if( channel == GREEN )
642 *pixelData &= static_cast<unsigned char>( ~0x07 );
643 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
645 *(pixelData+1) &= static_cast<unsigned char>( ~0xC0 );
646 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
648 else if( channel == RED )
650 *(pixelData+1) &= static_cast<unsigned char>( ~0x3E );
651 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
653 else if( channel == ALPHA )
655 *(pixelData+1) &= static_cast<unsigned char>( ~0x01 );
656 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
661 case Dali::Pixel::DEPTH_UNSIGNED_INT:
662 case Dali::Pixel::DEPTH_FLOAT:
663 case Dali::Pixel::DEPTH_STENCIL:
673 void ConvertColorChannelsToRGBA8888(
674 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
675 unsigned char* destPixel, int destOffset )
677 int red = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
678 int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
679 int blue = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
682 case Dali::Pixel::RGB565:
683 case Dali::Pixel::BGR565:
685 red = (red<<3) | (red & 0x07);
686 green = (green << 2) | (green & 0x03);
687 blue = (blue<<3) | (blue & 0x07);
690 case Dali::Pixel::RGBA4444:
691 case Dali::Pixel::BGRA4444:
693 red = (red<<4) | (red&0x0F);
694 green = (green<<4) | (green&0x0F);
695 blue = (blue<<4) | (blue&0x0F);
698 case Dali::Pixel::RGBA5551:
699 case Dali::Pixel::BGRA5551:
701 red = (red<<3) | (red&0x07);
702 green = (green<<3) | (green&0x07);
703 blue = (blue<<3) | (blue&0x07);
709 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
710 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
711 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
715 int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
717 int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
718 int destAlpha = alpha;
721 case Pixel::RGBA5551:
722 case Pixel::BGRA5551:
724 destAlpha = (alpha==0)?0:255;
727 case Pixel::RGBA4444:
728 case Pixel::BGRA4444:
730 destAlpha = (alpha<<4) | (alpha&0x0F);