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:
70 return ( channel == RED || channel == GREEN || channel == BLUE );
73 case Dali::Pixel::RGBA8888:
74 case Dali::Pixel::BGRA8888:
75 case Dali::Pixel::RGBA4444:
76 case Dali::Pixel::BGRA4444:
77 case Dali::Pixel::RGBA5551:
78 case Dali::Pixel::BGRA5551:
80 return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
83 case Dali::Pixel::INVALID:
84 case Dali::Pixel::COMPRESSED_R11_EAC:
85 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
86 case Dali::Pixel::COMPRESSED_RG11_EAC:
87 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
88 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
89 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
90 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
91 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
92 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
93 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
94 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
95 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
96 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
97 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
98 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
99 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
100 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
101 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
102 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
103 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
104 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
105 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
106 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
107 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
108 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
109 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
110 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
111 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
112 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
113 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
114 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
115 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
116 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
117 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
118 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
119 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
120 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
121 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
122 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
123 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
125 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
133 unsigned int ReadChannel( unsigned char* pixelData,
134 Dali::Pixel::Format pixelFormat,
139 case Dali::Pixel::A8:
141 if( channel == ALPHA )
143 return static_cast<unsigned int>(*pixelData);
147 case Dali::Pixel::L8:
149 if( channel == LUMINANCE )
151 return static_cast<unsigned int>(*pixelData);
155 case Dali::Pixel::LA88:
157 if( channel == LUMINANCE )
159 return static_cast<unsigned int>(*pixelData);
161 else if( channel == ALPHA )
163 return static_cast<unsigned int>(*(pixelData+1));
167 case Dali::Pixel::RGB565:
171 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
173 else if( channel == GREEN )
175 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
176 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
178 else if( channel == BLUE )
180 return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
185 case Dali::Pixel::BGR565:
187 if( channel == BLUE )
189 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
191 else if( channel == GREEN )
193 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
194 ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
196 else if( channel == RED )
198 return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
203 case Dali::Pixel::RGB888:
204 case Dali::Pixel::RGB8888:
208 return static_cast<unsigned int>(*pixelData);
210 else if( channel == GREEN )
212 return static_cast<unsigned int>(*(pixelData+1));
214 else if( channel == BLUE )
216 return static_cast<unsigned int>(*(pixelData+2));
221 case Dali::Pixel::BGR8888:
223 if( channel == BLUE )
225 return static_cast<unsigned int>(*pixelData);
227 else if( channel == GREEN )
229 return static_cast<unsigned int>(*(pixelData+1));
231 else if( channel == RED )
233 return static_cast<unsigned int>(*(pixelData+2));
238 case Dali::Pixel::RGBA8888:
242 return static_cast<unsigned int>(*pixelData);
244 else if( channel == GREEN )
246 return static_cast<unsigned int>(*(pixelData+1));
248 else if( channel == BLUE )
250 return static_cast<unsigned int>(*(pixelData+2));
252 else if( channel == ALPHA )
254 return static_cast<unsigned int>(*(pixelData+3));
259 case Dali::Pixel::BGRA8888:
261 if( channel == BLUE )
263 return static_cast<unsigned int>(*pixelData);
265 else if( channel == GREEN )
267 return static_cast<unsigned int>(*(pixelData+1));
269 else if( channel == RED )
271 return static_cast<unsigned int>(*(pixelData+2));
273 else if( channel == ALPHA )
275 return static_cast<unsigned int>(*(pixelData+3));
280 case Dali::Pixel::RGBA4444:
284 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
286 else if( channel == GREEN )
288 return (static_cast<unsigned int>(*pixelData) & 0x0F);
290 else if( channel == BLUE )
292 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
294 else if( channel == ALPHA )
296 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
301 case Dali::Pixel::BGRA4444:
303 if( channel == BLUE )
305 return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
307 else if( channel == GREEN )
309 return (static_cast<unsigned int>(*pixelData) & 0x0F);
311 else if( channel == RED )
313 return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
315 else if( channel == ALPHA )
317 return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
322 case Dali::Pixel::RGBA5551:
326 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
328 else if( channel == GREEN )
330 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
331 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
333 else if( channel == BLUE )
335 return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
337 else if( channel == ALPHA )
339 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
345 case Dali::Pixel::BGRA5551:
347 if( channel == BLUE )
349 return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
351 else if( channel == GREEN )
353 return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
354 ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
356 else if( channel == RED )
358 return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
360 else if( channel == ALPHA )
362 return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
375 void WriteChannel( unsigned char* pixelData,
376 Dali::Pixel::Format pixelFormat,
378 unsigned int channelValue )
382 case Dali::Pixel::A8:
384 if( channel == ALPHA )
386 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
390 case Dali::Pixel::L8:
392 if( channel == LUMINANCE )
394 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
398 case Dali::Pixel::LA88:
400 if( channel == LUMINANCE )
402 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
404 else if( channel == ALPHA )
406 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
410 case Dali::Pixel::RGB565:
415 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
417 else if( channel == GREEN )
420 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
422 *(pixelData+1) &= ~0xE0;
423 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
425 else if( channel == BLUE )
427 *(pixelData+1) &= ~0x1F;
428 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
433 case Dali::Pixel::BGR565:
435 if( channel == BLUE )
438 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
440 else if( channel == GREEN )
443 *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
445 *(pixelData+1) &= ~0xE0;
446 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
448 else if( channel == RED )
450 *(pixelData+1) &= ~0x1F;
451 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
456 case Dali::Pixel::RGB888:
457 case Dali::Pixel::RGB8888:
461 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
463 else if( channel == GREEN )
465 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
467 else if( channel == BLUE )
469 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
474 case Dali::Pixel::BGR8888:
476 if( channel == BLUE )
478 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
480 else if( channel == GREEN )
482 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
484 else if( channel == RED )
486 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
491 case Dali::Pixel::RGBA8888:
495 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
497 else if( channel == GREEN )
499 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
501 else if( channel == BLUE )
503 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
505 else if( channel == ALPHA )
507 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
512 case Dali::Pixel::BGRA8888:
514 if( channel == BLUE )
516 *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
518 else if( channel == GREEN )
520 *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
522 else if( channel == RED )
524 *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
526 else if( channel == ALPHA )
528 *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
533 case Dali::Pixel::RGBA4444:
538 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
540 else if( channel == GREEN )
543 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
545 else if( channel == BLUE )
547 *(pixelData+1) &= ~0xF0;
548 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
550 else if( channel == ALPHA )
552 *(pixelData+1) &= ~0x0F;
553 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
558 case Dali::Pixel::BGRA4444:
560 if( channel == BLUE )
563 *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
565 else if( channel == GREEN )
568 *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
570 else if( channel == RED )
572 *(pixelData+1) &= ~0xF0;
573 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
575 else if( channel == ALPHA )
577 *(pixelData+1) &= ~0x0F;
578 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
583 case Dali::Pixel::RGBA5551:
590 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
592 else if( channel == GREEN )
595 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
597 *(pixelData+1) &= ~0xC0;
598 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
600 else if( channel == BLUE )
602 *(pixelData+1) &= ~0x3E;
603 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
605 else if( channel == ALPHA )
607 *(pixelData+1) &= ~0x01;
608 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
613 case Dali::Pixel::BGRA5551:
615 if( channel == BLUE )
618 *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
620 else if( channel == GREEN )
623 *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
625 *(pixelData+1) &= ~0xC0;
626 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
628 else if( channel == RED )
630 *(pixelData+1) &= ~0x3E;
631 *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
633 else if( channel == ALPHA )
635 *(pixelData+1) &= ~0x01;
636 *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
646 void ConvertColorChannelsToRGBA8888(
647 unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat,
648 unsigned char* destPixel, int destOffset )
650 int red = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
651 int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
652 int blue = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
655 case Dali::Pixel::RGB565:
656 case Dali::Pixel::BGR565:
658 red = (red<<3) | (red & 0x07);
659 green = (green << 2) | (green & 0x03);
660 blue = (blue<<3) | (blue & 0x07);
663 case Dali::Pixel::RGBA4444:
664 case Dali::Pixel::BGRA4444:
666 red = (red<<4) | (red&0x0F);
667 green = (green<<4) | (green&0x0F);
668 blue = (blue<<4) | (blue&0x0F);
671 case Dali::Pixel::RGBA5551:
672 case Dali::Pixel::BGRA5551:
674 red = (red<<3) | (red&0x07);
675 green = (green<<3) | (green&0x07);
676 blue = (blue<<3) | (blue&0x07);
682 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
683 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
684 WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
688 int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
690 int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
691 int destAlpha = alpha;
694 case Pixel::RGBA5551:
695 case Pixel::BGRA5551:
697 destAlpha = (alpha==0)?0:255;
700 case Pixel::RGBA4444:
701 case Pixel::BGRA4444:
703 destAlpha = (alpha<<4) | (alpha&0x0F);