9a1a1f7d6f556af87d6902b491807e58ff13798d
[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 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::GetAlphaOffsetAndMask( buffer.GetPixelFormat(), destAlphaByteOffset, destAlphaMask );
48
49   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
50   unsigned char* srcBuffer = mask.GetBuffer();
51   unsigned char* destBuffer = buffer.GetBuffer();
52
53   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
54
55   int srcOffset=0;
56   int destOffset=0;
57
58   float srcAlphaValue = 1.0f;
59
60   for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
61   {
62     for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
63     {
64       unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
65       srcAlphaValue = float(alpha)/255.0f;
66
67       unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
68       float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
69       destAlpha = destAlphaValue;
70       destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
71       destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
72
73       srcOffset  += srcBytesPerPixel;
74       destOffset += destBytesPerPixel;
75     }
76   }
77 }
78
79 PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
80 {
81   // Set up source alpha offsets
82   int srcAlphaByteOffset=0;
83   int srcAlphaMask=0;
84   Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
85
86   if( Pixel::HasAlpha(srcPixelFormat) )
87   {
88     Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
89   }
90   else if( srcPixelFormat == Pixel::L8 )
91   {
92     srcAlphaMask=0xFF;
93   }
94
95   unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
96   unsigned char* srcBuffer = mask.GetBuffer();
97
98   // Set up source color offsets
99   Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
100   unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcColorPixelFormat );
101
102   // Setup destination offsets
103   Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
104   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
105   int destAlphaByteOffset=0;
106   int destAlphaMask=0;
107   Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
108
109   PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(),
110                                                     destPixelFormat );
111   unsigned char* destBuffer = newPixelBuffer->GetBuffer();
112   unsigned char* oldBuffer = buffer.GetBuffer();
113
114   int srcAlphaOffset=0;
115   int srcColorOffset=0;
116   int destOffset=0;
117   bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
118
119   float srcAlphaValue = 1.0f;
120   unsigned char destAlpha = 0;
121
122   for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
123   {
124     for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
125     {
126       unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
127       srcAlphaValue = float(alpha)/255.0f;
128
129       ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
130
131       if( hasAlpha )
132       {
133         destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat );
134         float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
135         destAlpha = destAlphaValue;
136       }
137       else
138       {
139         destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
140       }
141
142       destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
143       destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
144
145       srcColorOffset += srcColorBytesPerPixel;
146       srcAlphaOffset += srcBytesPerPixel;
147       destOffset += destBytesPerPixel;
148     }
149   }
150
151   return newPixelBuffer;
152 }
153
154 } //namespace Adaptor
155
156 }// namespace Internal
157
158 }// namespace Dali