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