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.
17 #include "pixel-manipulation.h"
18 #include "alpha-mask.h"
19 #include "pixel-buffer-impl.h"
29 void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
31 const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
32 const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
35 if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
40 int srcAlphaByteOffset=0;
42 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
44 Channel alphaChannel = ALPHA;
45 if( Pixel::HasAlpha(srcPixelFormat) )
47 Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
49 else if( srcPixelFormat == Pixel::L8 )
52 alphaChannel = LUMINANCE;
55 int destAlphaByteOffset=0;
57 Dali::Pixel::GetAlphaOffsetAndMask( buffer.GetPixelFormat(), destAlphaByteOffset, destAlphaMask );
59 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
60 int srcStride = mask.GetWidth() * srcBytesPerPixel;
61 unsigned char* srcBuffer = mask.GetBuffer();
62 unsigned char* destBuffer = buffer.GetBuffer();
64 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
69 float srcAlphaValue = 1.0f;
71 for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
73 for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
77 srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
78 unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
79 srcAlphaValue = float(alpha)/255.0f;
83 srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
86 unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
87 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
88 destAlpha = destAlphaValue;
89 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
90 destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
92 destOffset += destBytesPerPixel;
97 PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
99 const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
100 const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
103 if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
108 // Set up source alpha offsets
109 int srcAlphaByteOffset=0;
111 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
112 Channel alphaChannel = ALPHA;
113 if( Pixel::HasAlpha(srcPixelFormat) )
115 Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
117 else if( srcPixelFormat == Pixel::L8 )
120 alphaChannel = LUMINANCE;
123 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
124 int srcStride = mask.GetWidth() * srcBytesPerPixel;
125 unsigned char* srcBuffer = mask.GetBuffer();
127 // Set up source color offsets
128 Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
129 unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcColorPixelFormat );
131 // Setup destination offsets
132 Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
133 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
134 int destAlphaByteOffset=0;
136 Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
138 PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(),
140 unsigned char* destBuffer = newPixelBuffer->GetBuffer();
142 unsigned char* oldBuffer = buffer.GetBuffer();
144 int srcAlphaOffset=0;
145 int srcColorOffset=0;
147 bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
149 float srcAlphaValue = 1.0f;
150 unsigned char destAlpha = 0;
152 for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
154 for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
156 if( numSamples == 1 )
158 srcAlphaOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
159 unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
160 srcAlphaValue = float(alpha)/255.0f;
164 srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
167 ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
171 destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat );
172 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
173 destAlpha = destAlphaValue;
177 destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
180 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
181 destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
183 srcColorOffset += srcColorBytesPerPixel;
184 destOffset += destBytesPerPixel;
188 return newPixelBuffer;
192 float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel alphaChannel )
194 int srcRow = floorf( y );
195 int srcCol = floorf( x );
197 int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( pixelFormat );
198 int srcOffset = srcRow * stride + srcCol * bytesPerPixel;
201 samples[0] = ReadChannel( buffer + srcOffset, pixelFormat, alphaChannel );
203 if( srcCol < width-1 )
205 samples[1] = ReadChannel( buffer + srcOffset+bytesPerPixel, pixelFormat, alphaChannel );
209 samples[1] = samples[0];
212 if( srcRow < height-1 )
214 samples[2] = ReadChannel( buffer + stride + srcOffset, pixelFormat, alphaChannel );
218 samples[2] = samples[0];
221 if( srcRow < height-1 && srcCol < width-1 )
223 samples[3] = ReadChannel( buffer + stride + srcOffset + bytesPerPixel, pixelFormat, alphaChannel );
227 samples[3] = samples[2];
230 // Bilinear interpolation:
232 weight[0] = float(srcRow+1.0f) - y;
233 weight[1] = y - float(srcRow);
234 weight[2] = float(srcCol+1.0f) - x;
235 weight[3] = x - float(srcCol);
237 return ( weight[2] * (samples[0] * weight[0] + samples[1] * weight[1]) +
238 weight[3] * (samples[2] * weight[0] + samples[3] * weight[1]) ) / 255.0f;
241 } //namespace Adaptor
243 }// namespace Internal