2 * Copyright (c) 2017 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 "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::INVALID:
86 case Dali::Pixel::COMPRESSED_R11_EAC:
87 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
88 case Dali::Pixel::COMPRESSED_RG11_EAC:
89 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
90 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
91 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
92 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
93 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
94 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
95 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
96 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
97 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
98 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
99 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
100 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
101 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
102 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
103 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
104 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
105 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
106 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
107 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
108 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
109 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
110 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
111 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
112 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
113 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
114 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
115 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
116 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
117 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
118 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
119 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
120 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
121 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
122 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
123 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
124 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
125 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
127 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
135 unsigned int ReadChannel( unsigned char* pixelData,
136 Dali::Pixel::Format pixelFormat,
141 case Dali::Pixel::A8:
143 if( channel == ALPHA )
145 return static_cast<unsigned int>(*pixelData);
149 case Dali::Pixel::L8:
151 if( channel == LUMINANCE )
153 return static_cast<unsigned int>(*pixelData);
157 case Dali::Pixel::LA88:
159 if( channel == LUMINANCE )
161 return static_cast<unsigned int>(*pixelData);
163 else if( channel == ALPHA )
165 return static_cast<unsigned int>(*(pixelData+1));
169 case Dali::Pixel::RGB565:
173 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
175 else if( channel == GREEN )
177 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
178 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
180 else if( channel == BLUE )
182 return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
187 case Dali::Pixel::BGR565:
189 if( channel == BLUE )
191 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
193 else if( channel == GREEN )
195 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
196 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
198 else if( channel == RED )
200 return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
205 case Dali::Pixel::RGB888:
206 case Dali::Pixel::RGB8888:
210 return static_cast<unsigned int>(*pixelData);
212 else if( channel == GREEN )
214 return static_cast<unsigned int>(*(pixelData+1));
216 else if( channel == BLUE )
218 return static_cast<unsigned int>(*(pixelData+2));
223 case Dali::Pixel::BGR8888:
225 if( channel == BLUE )
227 return static_cast<unsigned int>(*pixelData);
229 else if( channel == GREEN )
231 return static_cast<unsigned int>(*(pixelData+1));
233 else if( channel == RED )
235 return static_cast<unsigned int>(*(pixelData+2));
240 case Dali::Pixel::RGBA8888:
244 return static_cast<unsigned int>(*pixelData);
246 else if( channel == GREEN )
248 return static_cast<unsigned int>(*(pixelData+1));
250 else if( channel == BLUE )
252 return static_cast<unsigned int>(*(pixelData+2));
254 else if( channel == ALPHA )
256 return static_cast<unsigned int>(*(pixelData+3));
261 case Dali::Pixel::BGRA8888:
263 if( channel == BLUE )
265 return static_cast<unsigned int>(*pixelData);
267 else if( channel == GREEN )
269 return static_cast<unsigned int>(*(pixelData+1));
271 else if( channel == RED )
273 return static_cast<unsigned int>(*(pixelData+2));
275 else if( channel == ALPHA )
277 return static_cast<unsigned int>(*(pixelData+3));
282 case Dali::Pixel::RGBA4444:
286 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
288 else if( channel == GREEN )
290 return (static_cast<unsigned int>(*pixelData) & 0x0F);
292 else if( channel == BLUE )
294 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
296 else if( channel == ALPHA )
298 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
303 case Dali::Pixel::BGRA4444:
305 if( channel == BLUE )
307 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
309 else if( channel == GREEN )
311 return (static_cast<unsigned int>(*pixelData) & 0x0F);
313 else if( channel == RED )
315 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
317 else if( channel == ALPHA )
319 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
324 case Dali::Pixel::RGBA5551:
328 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
330 else if( channel == GREEN )
332 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
333 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
335 else if( channel == BLUE )
337 return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
339 else if( channel == ALPHA )
341 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
347 case Dali::Pixel::BGRA5551:
349 if( channel == BLUE )
351 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
353 else if( channel == GREEN )
355 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
356 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
358 else if( channel == RED )
360 return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
362 else if( channel == ALPHA )
364 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
377 void WriteChannel( unsigned char* pixelData,
378 Dali::Pixel::Format pixelFormat,
380 unsigned int channelValue )
384 case Dali::Pixel::A8:
386 if( channel == ALPHA )
388 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
392 case Dali::Pixel::L8:
394 if( channel == LUMINANCE )
396 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
400 case Dali::Pixel::LA88:
402 if( channel == LUMINANCE )
404 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
406 else if( channel == ALPHA )
408 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
412 case Dali::Pixel::RGB565:
417 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
419 else if( channel == GREEN )
422 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
424 *(pixelData+1) &= ~0xE0;
425 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
427 else if( channel == BLUE )
429 *(pixelData+1) &= ~0x1F;
430 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
435 case Dali::Pixel::BGR565:
437 if( channel == BLUE )
440 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
442 else if( channel == GREEN )
445 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
447 *(pixelData+1) &= ~0xE0;
448 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
450 else if( channel == RED )
452 *(pixelData+1) &= ~0x1F;
453 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
458 case Dali::Pixel::RGB888:
459 case Dali::Pixel::RGB8888:
463 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
465 else if( channel == GREEN )
467 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
469 else if( channel == BLUE )
471 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
476 case Dali::Pixel::BGR8888:
478 if( channel == BLUE )
480 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
482 else if( channel == GREEN )
484 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
486 else if( channel == RED )
488 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
493 case Dali::Pixel::RGBA8888:
497 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
499 else if( channel == GREEN )
501 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
503 else if( channel == BLUE )
505 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
507 else if( channel == ALPHA )
509 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
514 case Dali::Pixel::BGRA8888:
516 if( channel == BLUE )
518 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
520 else if( channel == GREEN )
522 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
524 else if( channel == RED )
526 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
528 else if( channel == ALPHA )
530 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
535 case Dali::Pixel::RGBA4444:
540 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
542 else if( channel == GREEN )
545 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
547 else if( channel == BLUE )
549 *(pixelData+1) &= ~0xF0;
550 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
552 else if( channel == ALPHA )
554 *(pixelData+1) &= ~0x0F;
555 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
560 case Dali::Pixel::BGRA4444:
562 if( channel == BLUE )
565 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
567 else if( channel == GREEN )
570 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
572 else if( channel == RED )
574 *(pixelData+1) &= ~0xF0;
575 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
577 else if( channel == ALPHA )
579 *(pixelData+1) &= ~0x0F;
580 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
585 case Dali::Pixel::RGBA5551:
592 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
594 else if( channel == GREEN )
597 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
599 *(pixelData+1) &= ~0xC0;
600 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
602 else if( channel == BLUE )
604 *(pixelData+1) &= ~0x3E;
605 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
607 else if( channel == ALPHA )
609 *(pixelData+1) &= ~0x01;
610 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
615 case Dali::Pixel::BGRA5551:
617 if( channel == BLUE )
620 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
622 else if( channel == GREEN )
625 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
627 *(pixelData+1) &= ~0xC0;
628 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
630 else if( channel == RED )
632 *(pixelData+1) &= ~0x3E;
633 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
635 else if( channel == ALPHA )
637 *(pixelData+1) &= ~0x01;
638 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
648 void ConvertColorChannelsToRGBA8888(
649 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
650 unsigned char* destPixel, int destOffset )
652 int red = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
653 int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
654 int blue = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
657 case Dali::Pixel::RGB565:
658 case Dali::Pixel::BGR565:
660 red = (red<<3) | (red & 0x07);
661 green = (green << 2) | (green & 0x03);
662 blue = (blue<<3) | (blue & 0x07);
665 case Dali::Pixel::RGBA4444:
666 case Dali::Pixel::BGRA4444:
668 red = (red<<4) | (red&0x0F);
669 green = (green<<4) | (green&0x0F);
670 blue = (blue<<4) | (blue&0x0F);
673 case Dali::Pixel::RGBA5551:
674 case Dali::Pixel::BGRA5551:
676 red = (red<<3) | (red&0x07);
677 green = (green<<3) | (green&0x07);
678 blue = (blue<<3) | (blue&0x07);
684 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
685 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
686 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
690 int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
692 int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
693 int destAlpha = alpha;
696 case Pixel::RGBA5551:
697 case Pixel::BGRA5551:
699 destAlpha = (alpha==0)?0:255;
702 case Pixel::RGBA4444:
703 case Pixel::BGRA4444:
705 destAlpha = (alpha<<4) | (alpha&0x0F);