Initial copy from dali-adaptor repository
[platform/core/uifw/dali-adaptor-legacy.git] / dali / internal / imaging / common / alpha-mask.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 #include <dali/internal/imaging/common/pixel-manipulation.h>
18 #include <dali/internal/imaging/common/alpha-mask.h>
19 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
20 #include <dali/public-api/images/image-operations.h> // For ImageDimensions
21 #include <dali/internal/imaging/common/image-operations.h>
22
23 namespace Dali
24 {
25 namespace Internal
26 {
27 namespace Adaptor
28 {
29
30 void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
31 {
32   int srcAlphaByteOffset=0;
33   int srcAlphaMask=0;
34   Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
35
36   if( Pixel::HasAlpha(srcPixelFormat) )
37   {
38     Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
39   }
40   else if( srcPixelFormat == Pixel::L8 )
41   {
42     srcAlphaMask=0xFF;
43   }
44
45   int destAlphaByteOffset=0;
46   int destAlphaMask=0;
47   Dali::Pixel::Format destPixelFormat = buffer.GetPixelFormat();
48   Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
49
50   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
51   unsigned char* srcBuffer = mask.GetBuffer();
52   unsigned char* destBuffer = buffer.GetBuffer();
53
54   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
55
56   int srcOffset=0;
57   int destOffset=0;
58
59   float srcAlphaValue = 1.0f;
60
61   // if image is premultiplied, the other channels of the image need to multiply by alpha.
62   if( buffer.IsAlphaPreMultiplied() )
63   {
64     for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
65     {
66       for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
67       {
68         auto srcAlpha      = ReadChannel( srcBuffer + srcOffset, srcPixelFormat, Adaptor::ALPHA);
69         auto destRed       = ReadChannel( destBuffer + destOffset, destPixelFormat, Adaptor::RED);
70         auto destGreen     = ReadChannel( destBuffer + destOffset, destPixelFormat, Adaptor::GREEN);
71         auto destBlue      = ReadChannel( destBuffer + destOffset, destPixelFormat, Adaptor::BLUE);
72         auto destLuminance = ReadChannel( destBuffer + destOffset, destPixelFormat, Adaptor::LUMINANCE);
73         auto destAlpha     = ReadChannel( destBuffer + destOffset, destPixelFormat, Adaptor::ALPHA);
74
75         WriteChannel( destBuffer + destOffset, destPixelFormat, Adaptor::RED, destRed*srcAlpha / 255 );
76         WriteChannel( destBuffer + destOffset, destPixelFormat, Adaptor::GREEN, destGreen*srcAlpha/255 );
77         WriteChannel( destBuffer + destOffset, destPixelFormat, Adaptor::BLUE, destBlue*srcAlpha/255 );
78         WriteChannel( destBuffer + destOffset, destPixelFormat, Adaptor::LUMINANCE, destLuminance*srcAlpha/255 );
79         WriteChannel( destBuffer + destOffset, destPixelFormat, Adaptor::ALPHA, destAlpha*srcAlpha/255 );
80
81         srcOffset  += srcBytesPerPixel;
82         destOffset += destBytesPerPixel;
83       }
84     }
85   }
86   else
87   {
88     for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
89     {
90       for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
91       {
92         unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
93         srcAlphaValue = float(alpha)/255.0f;
94
95         unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
96         float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
97         destAlpha = destAlphaValue;
98         destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
99         destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
100
101         srcOffset  += srcBytesPerPixel;
102         destOffset += destBytesPerPixel;
103       }
104     }
105   }
106 }
107
108 PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
109 {
110   // Set up source alpha offsets
111   int srcAlphaByteOffset=0;
112   int srcAlphaMask=0;
113   Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
114
115   if( Pixel::HasAlpha(srcPixelFormat) )
116   {
117     Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
118   }
119   else if( srcPixelFormat == Pixel::L8 )
120   {
121     srcAlphaMask=0xFF;
122   }
123
124   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
125   unsigned char* srcBuffer = mask.GetBuffer();
126
127   // Set up source color offsets
128   Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
129   unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcColorPixelFormat );
130
131   // Setup destination offsets
132   Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
133   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
134   int destAlphaByteOffset=0;
135   int destAlphaMask=0;
136   Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
137
138   PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(),
139                                                     destPixelFormat );
140   unsigned char* destBuffer = newPixelBuffer->GetBuffer();
141   unsigned char* oldBuffer = buffer.GetBuffer();
142
143   int srcAlphaOffset=0;
144   int srcColorOffset=0;
145   int destOffset=0;
146   bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
147
148   float srcAlphaValue = 1.0f;
149   unsigned char destAlpha = 0;
150
151   for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
152   {
153     for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
154     {
155       unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
156       srcAlphaValue = float(alpha)/255.0f;
157
158       ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
159
160       if( hasAlpha )
161       {
162         destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat );
163         float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
164         destAlpha = destAlphaValue;
165       }
166       else
167       {
168         destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
169       }
170
171       destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
172       destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
173
174       srcColorOffset += srcColorBytesPerPixel;
175       srcAlphaOffset += srcBytesPerPixel;
176       destOffset += destBytesPerPixel;
177     }
178   }
179
180   return newPixelBuffer;
181 }
182
183 } //namespace Adaptor
184
185 }// namespace Internal
186
187 }// namespace Dali