Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / portable / pixel-manipulation.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 // CLASS HEADER
18 #include "pixel-manipulation.h"
19
20 // INTERNAL HEADERS
21 #include <dali/public-api/images/pixel.h>
22 #include <dali/integration-api/debug.h>
23
24 namespace Dali
25 {
26 namespace Internal
27 {
28 namespace Adaptor
29 {
30
31 struct Location
32 {
33   unsigned int bitShift;
34   unsigned int bitMask;
35   bool available;
36 };
37
38 struct Locations
39 {
40   Location luminance;
41   Location alpha;
42   Location red;
43   Location green;
44   Location blue;
45 };
46
47
48 bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel )
49 {
50   switch (pixelFormat)
51   {
52     case Dali::Pixel::A8:
53     {
54       return (channel == ALPHA);
55     }
56     case Dali::Pixel::L8:
57     {
58       return (channel == LUMINANCE);
59     }
60     case Dali::Pixel::LA88:
61     {
62       return ( channel == LUMINANCE || channel == ALPHA );
63     }
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     {
70       return ( channel == RED || channel == GREEN || channel == BLUE );
71     }
72
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:
79     {
80       return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
81     }
82
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:
124     {
125       DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
126       break;
127     }
128   }
129
130   return false;
131 }
132
133 unsigned int ReadChannel( unsigned char* pixelData,
134                           Dali::Pixel::Format pixelFormat,
135                           Channel channel )
136 {
137   switch (pixelFormat)
138   {
139     case Dali::Pixel::A8:
140     {
141       if( channel == ALPHA )
142       {
143         return static_cast<unsigned int>(*pixelData);
144       }
145       else return 0u;
146     }
147     case Dali::Pixel::L8:
148     {
149       if( channel == LUMINANCE )
150       {
151         return static_cast<unsigned int>(*pixelData);
152       }
153       else return 0u;
154     }
155     case Dali::Pixel::LA88:
156     {
157       if( channel == LUMINANCE )
158       {
159         return static_cast<unsigned int>(*pixelData);
160       }
161       else if( channel == ALPHA )
162       {
163         return static_cast<unsigned int>(*(pixelData+1));
164       }
165       else return 0u;
166     }
167     case Dali::Pixel::RGB565:
168     {
169       if( channel == RED )
170       {
171         return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
172       }
173       else if( channel == GREEN )
174       {
175         return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
176           ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
177       }
178       else if( channel == BLUE )
179       {
180         return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
181       }
182       else return 0u;
183     }
184
185     case Dali::Pixel::BGR565:
186     {
187       if( channel == BLUE )
188       {
189         return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
190       }
191       else if( channel == GREEN )
192       {
193         return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
194           ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
195       }
196       else if( channel == RED )
197       {
198         return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
199       }
200       else return 0u;
201     }
202
203     case Dali::Pixel::RGB888:
204     case Dali::Pixel::RGB8888:
205     {
206       if( channel == RED )
207       {
208         return static_cast<unsigned int>(*pixelData);
209       }
210       else if( channel == GREEN )
211       {
212         return static_cast<unsigned int>(*(pixelData+1));
213       }
214       else if( channel == BLUE )
215       {
216         return static_cast<unsigned int>(*(pixelData+2));
217       }
218       else return 0u;
219     }
220
221     case Dali::Pixel::BGR8888:
222     {
223       if( channel == BLUE )
224       {
225         return static_cast<unsigned int>(*pixelData);
226       }
227       else if( channel == GREEN )
228       {
229         return static_cast<unsigned int>(*(pixelData+1));
230       }
231       else if( channel == RED )
232       {
233         return static_cast<unsigned int>(*(pixelData+2));
234       }
235       else return 0u;
236     }
237
238     case Dali::Pixel::RGBA8888:
239     {
240       if( channel == RED )
241       {
242         return static_cast<unsigned int>(*pixelData);
243       }
244       else if( channel == GREEN )
245       {
246         return static_cast<unsigned int>(*(pixelData+1));
247       }
248       else if( channel == BLUE )
249       {
250         return static_cast<unsigned int>(*(pixelData+2));
251       }
252       else if( channel == ALPHA )
253       {
254         return static_cast<unsigned int>(*(pixelData+3));
255       }
256       else return 0u;
257     }
258
259     case Dali::Pixel::BGRA8888:
260     {
261       if( channel == BLUE )
262       {
263         return static_cast<unsigned int>(*pixelData);
264       }
265       else if( channel == GREEN )
266       {
267         return static_cast<unsigned int>(*(pixelData+1));
268       }
269       else if( channel == RED )
270       {
271         return static_cast<unsigned int>(*(pixelData+2));
272       }
273       else if( channel == ALPHA )
274       {
275         return static_cast<unsigned int>(*(pixelData+3));
276       }
277       else return 0u;
278     }
279
280     case Dali::Pixel::RGBA4444:
281     {
282       if( channel == RED )
283       {
284         return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
285       }
286       else if( channel == GREEN )
287       {
288         return (static_cast<unsigned int>(*pixelData) & 0x0F);
289       }
290       else if( channel == BLUE )
291       {
292         return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
293       }
294       else if( channel == ALPHA )
295       {
296         return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
297       }
298       else return 0u;
299     }
300
301     case Dali::Pixel::BGRA4444:
302     {
303       if( channel == BLUE )
304       {
305         return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
306       }
307       else if( channel == GREEN )
308       {
309         return (static_cast<unsigned int>(*pixelData) & 0x0F);
310       }
311       else if( channel == RED )
312       {
313         return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
314       }
315       else if( channel == ALPHA )
316       {
317         return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
318       }
319       else return 0u;
320     }
321
322     case Dali::Pixel::RGBA5551:
323     {
324       if( channel == RED )
325       {
326         return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
327       }
328       else if( channel == GREEN )
329       {
330         return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
331           ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
332       }
333       else if( channel == BLUE )
334       {
335         return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
336       }
337       else if( channel == ALPHA )
338       {
339         return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
340       }
341
342       else return 0u;
343     }
344
345     case Dali::Pixel::BGRA5551:
346     {
347       if( channel == BLUE )
348       {
349         return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
350       }
351       else if( channel == GREEN )
352       {
353         return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
354           ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
355       }
356       else if( channel == RED )
357       {
358         return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
359       }
360       else if( channel == ALPHA )
361       {
362         return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
363       }
364
365       else return 0u;
366     }
367
368     default:
369     {
370       return 0u;
371     }
372   }
373 }
374
375 void WriteChannel( unsigned char* pixelData,
376                    Dali::Pixel::Format pixelFormat,
377                    Channel channel,
378                    unsigned int channelValue )
379 {
380   switch (pixelFormat)
381   {
382     case Dali::Pixel::A8:
383     {
384       if( channel == ALPHA )
385       {
386         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
387       }
388       break;
389     }
390     case Dali::Pixel::L8:
391     {
392       if( channel == LUMINANCE )
393       {
394         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
395       }
396       break;
397     }
398     case Dali::Pixel::LA88:
399     {
400       if( channel == LUMINANCE )
401       {
402         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
403       }
404       else if( channel == ALPHA )
405       {
406         *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
407       }
408       break;
409     }
410     case Dali::Pixel::RGB565:
411     {
412       if( channel == RED )
413       {
414         *pixelData &= ~0xF8;
415         *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
416       }
417       else if( channel == GREEN )
418       {
419         *pixelData &= ~0x07;
420         *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
421
422         *(pixelData+1) &= ~0xE0;
423         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
424       }
425       else if( channel == BLUE )
426       {
427         *(pixelData+1) &= ~0x1F;
428         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
429       }
430       break;
431     }
432
433     case Dali::Pixel::BGR565:
434     {
435       if( channel == BLUE )
436       {
437         *pixelData &= ~0xF8;
438         *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
439       }
440       else if( channel == GREEN )
441       {
442         *pixelData &= ~0x07;
443         *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
444
445         *(pixelData+1) &= ~0xE0;
446         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
447       }
448       else if( channel == RED )
449       {
450         *(pixelData+1) &= ~0x1F;
451         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
452       }
453       break;
454     }
455
456     case Dali::Pixel::RGB888:
457     case Dali::Pixel::RGB8888:
458     {
459       if( channel == RED )
460       {
461         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
462       }
463       else if( channel == GREEN )
464       {
465         *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
466       }
467       else if( channel == BLUE )
468       {
469         *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
470       }
471       break;
472     }
473
474     case Dali::Pixel::BGR8888:
475     {
476       if( channel == BLUE )
477       {
478         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
479       }
480       else if( channel == GREEN )
481       {
482         *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
483       }
484       else if( channel == RED )
485       {
486         *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
487       }
488       break;
489     }
490
491     case Dali::Pixel::RGBA8888:
492     {
493       if( channel == RED )
494       {
495         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
496       }
497       else if( channel == GREEN )
498       {
499         *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
500       }
501       else if( channel == BLUE )
502       {
503         *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
504       }
505       else if( channel == ALPHA )
506       {
507         *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
508       }
509       break;
510     }
511
512     case Dali::Pixel::BGRA8888:
513     {
514       if( channel == BLUE )
515       {
516         *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
517       }
518       else if( channel == GREEN )
519       {
520         *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
521       }
522       else if( channel == RED )
523       {
524         *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
525       }
526       else if( channel == ALPHA )
527       {
528         *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
529       }
530       break;
531     }
532
533     case Dali::Pixel::RGBA4444:
534     {
535       if( channel == RED )
536       {
537         *pixelData &= ~0xF0;
538         *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
539       }
540       else if( channel == GREEN )
541       {
542         *pixelData &= ~0x0F;
543         *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
544       }
545       else if( channel == BLUE )
546       {
547         *(pixelData+1) &= ~0xF0;
548         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
549       }
550       else if( channel == ALPHA )
551       {
552         *(pixelData+1) &= ~0x0F;
553         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
554       }
555       break;
556     }
557
558     case Dali::Pixel::BGRA4444:
559     {
560       if( channel == BLUE )
561       {
562         *pixelData &= ~0xF0;
563         *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
564       }
565       else if( channel == GREEN )
566       {
567         *pixelData &= ~0x0F;
568         *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
569       }
570       else if( channel == RED )
571       {
572         *(pixelData+1) &= ~0xF0;
573         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
574       }
575       else if( channel == ALPHA )
576       {
577         *(pixelData+1) &= ~0x0F;
578         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
579       }
580       break;
581     }
582
583     case Dali::Pixel::RGBA5551:
584     {
585       // rrrrrggg ggbbbbba
586       //    F8  7 C0  3E 1
587       if( channel == RED )
588       {
589         *pixelData &= ~0xF8;
590         *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
591       }
592       else if( channel == GREEN )
593       {
594         *pixelData &= ~0x07;
595         *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
596
597         *(pixelData+1) &= ~0xC0;
598         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
599       }
600       else if( channel == BLUE )
601       {
602         *(pixelData+1) &= ~0x3E;
603         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
604       }
605       else if( channel == ALPHA )
606       {
607         *(pixelData+1) &= ~0x01;
608         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
609       }
610       break;
611     }
612
613     case Dali::Pixel::BGRA5551:
614     {
615       if( channel == BLUE )
616       {
617         *pixelData &= ~0xF8;
618         *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
619       }
620       else if( channel == GREEN )
621       {
622         *pixelData &= ~0x07;
623         *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
624
625         *(pixelData+1) &= ~0xC0;
626         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
627       }
628       else if( channel == RED )
629       {
630         *(pixelData+1) &= ~0x3E;
631         *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
632       }
633       else if( channel == ALPHA )
634       {
635         *(pixelData+1) &= ~0x01;
636         *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
637       }
638       break;
639     }
640
641     default:
642       break;
643   }
644 }
645
646 void ConvertColorChannelsToRGBA8888(
647   unsigned char* srcPixel,  int srcOffset,  Dali::Pixel::Format srcFormat,
648   unsigned char* destPixel, int destOffset )
649 {
650   int red   = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
651   int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
652   int blue  = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
653   switch( srcFormat )
654   {
655     case Dali::Pixel::RGB565:
656     case Dali::Pixel::BGR565:
657     {
658       red = (red<<3) | (red & 0x07);
659       green = (green << 2) | (green & 0x03);
660       blue = (blue<<3) | (blue & 0x07);
661       break;
662     }
663     case Dali::Pixel::RGBA4444:
664     case Dali::Pixel::BGRA4444:
665     {
666       red = (red<<4) | (red&0x0F);
667       green = (green<<4) | (green&0x0F);
668       blue = (blue<<4) | (blue&0x0F);
669       break;
670     }
671     case Dali::Pixel::RGBA5551:
672     case Dali::Pixel::BGRA5551:
673     {
674       red = (red<<3) | (red&0x07);
675       green = (green<<3) | (green&0x07);
676       blue = (blue<<3) | (blue&0x07);
677       break;
678     }
679     default:
680       break;
681   }
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);
685 }
686
687
688 int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
689 {
690   int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
691   int destAlpha = alpha;
692   switch( srcFormat )
693   {
694     case Pixel::RGBA5551:
695     case Pixel::BGRA5551:
696     {
697       destAlpha = (alpha==0)?0:255;
698       break;
699     }
700     case Pixel::RGBA4444:
701     case Pixel::BGRA4444:
702     {
703       destAlpha = (alpha<<4) | (alpha&0x0F);
704       break;
705     }
706     default:
707       break;
708   }
709   return destAlpha;
710 }
711
712 } // Adaptor
713 } // Internal
714 } // Dali