2 * Copyright (c) 2016 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.
19 #include <dali/internal/event/images/pixel-data-impl.h>
25 #include <dali/internal/event/images/pixel-manipulation.h>
33 PixelData::PixelData( unsigned char* buffer,
34 unsigned int bufferSize,
37 Dali::Pixel::Format pixelFormat,
38 Dali::PixelData::ReleaseFunction releaseFunction )
40 mBufferSize( bufferSize ),
43 mPixelFormat( pixelFormat ),
44 mReleaseFunction( releaseFunction )
48 PixelData::~PixelData()
56 PixelDataPtr PixelData::New(unsigned char* buffer,
57 unsigned int bufferSize,
60 Dali::Pixel::Format pixelFormat,
61 Dali::PixelData::ReleaseFunction releaseFunction)
63 return new PixelData( buffer, bufferSize, width, height, pixelFormat, releaseFunction );
66 unsigned int PixelData::GetWidth() const
71 unsigned int PixelData::GetHeight() const
76 Dali::Pixel::Format PixelData::GetPixelFormat() const
81 unsigned char* PixelData::GetBuffer() const
86 unsigned int PixelData::GetBufferSize() const
91 void PixelData::ReleaseBuffer()
93 if( mReleaseFunction == Dali::PixelData::FREE)
103 void PixelData::ApplyMask( const PixelData& mask )
107 Dali::Pixel::GetAlphaOffsetAndMask(mPixelFormat, byteOffset, bitMask);
109 if( Dali::Pixel::HasAlpha( mPixelFormat ) && bitMask == 255 )
111 ApplyMaskToAlphaChannel( mask );
115 AddAlphaChannel(mask);
119 void PixelData::ApplyMaskToAlphaChannel( const PixelData& mask )
121 const float rowFactor = float(mask.mHeight) / (1.0f * mHeight);
122 const float colFactor = float(mask.mWidth) / (1.0f * mWidth) ;
125 if( mask.mHeight > mHeight || mask.mWidth > mWidth )
130 int srcAlphaByteOffset=0;
132 Dali::Pixel::GetAlphaOffsetAndMask( mask.mPixelFormat, srcAlphaByteOffset, srcAlphaMask );
134 int destAlphaByteOffset=0;
136 Dali::Pixel::GetAlphaOffsetAndMask( mPixelFormat, destAlphaByteOffset, destAlphaMask );
138 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mask.mPixelFormat );
139 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
140 int srcStride = mask.mWidth * srcBytesPerPixel;
145 float srcAlphaValue = 1.0f;
147 for( unsigned int row = 0; row < mHeight; ++row )
149 for( unsigned int col = 0; col < mWidth; ++col )
151 if( numSamples == 1 )
153 srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
154 unsigned char alpha = mask.mBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
155 srcAlphaValue = float(alpha)/255.0f;
159 srcAlphaValue = mask.ReadWeightedSample( col*colFactor, row*rowFactor );
162 unsigned char destAlpha = mBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
163 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
164 destAlpha = destAlphaValue;
165 mBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
166 mBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
168 destOffset += destBytesPerPixel;
173 void PixelData::AddAlphaChannel( const PixelData& mask )
175 const float rowFactor = float(mask.mHeight) / (1.0f * mHeight);
176 const float colFactor = float(mask.mWidth) / (1.0f * mWidth) ;
179 if( mask.mHeight > mHeight || mask.mWidth > mWidth )
184 // Set up source alpha offsets
185 int srcAlphaByteOffset=0;
187 Dali::Pixel::GetAlphaOffsetAndMask( mask.mPixelFormat, srcAlphaByteOffset, srcAlphaMask );
189 unsigned int srcAlphaBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mask.mPixelFormat );
190 int srcAlphaStride = mask.mWidth * srcAlphaBytesPerPixel;
192 // Set up source color offsets
193 unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
195 // Setup destination offsets
196 Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
197 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
198 int destAlphaByteOffset=0;
200 Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
202 int destBufferSize = mWidth * mHeight * destBytesPerPixel;
203 unsigned char* destBuffer = static_cast<unsigned char*>( malloc( destBufferSize ) );
205 int srcAlphaOffset=0;
206 int srcColorOffset=0;
208 bool hasAlpha = Dali::Pixel::HasAlpha(mPixelFormat);
210 float srcAlphaValue = 1.0f;
211 unsigned char destAlpha = 0;
213 for( unsigned int row = 0; row < mHeight; ++row )
215 for( unsigned int col = 0; col < mWidth; ++col )
217 if( numSamples == 1 )
219 srcAlphaOffset = floorf(row * rowFactor) * srcAlphaStride + floorf(col * colFactor) * srcAlphaBytesPerPixel;
220 unsigned char alpha = mask.mBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
221 srcAlphaValue = float(alpha)/255.0f;
225 srcAlphaValue = mask.ReadWeightedSample( col*colFactor, row*rowFactor );
228 Pixel::ConvertColorChannelsToRGBA8888(mBuffer, srcColorOffset, mPixelFormat, destBuffer, destOffset );
232 destAlpha = mBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
233 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
234 destAlpha = destAlphaValue;
238 destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
241 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
242 destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
244 srcColorOffset += srcColorBytesPerPixel;
245 destOffset += destBytesPerPixel;
251 mBuffer = destBuffer;
252 mBufferSize = destBufferSize;
253 mPixelFormat = Dali::Pixel::RGBA8888;
254 mReleaseFunction = Dali::PixelData::FREE;
257 float PixelData::ReadWeightedSample( float x, float y ) const
259 unsigned int srcRow = floorf( y );
260 unsigned int srcCol = floorf( x );
262 int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
263 int stride = mWidth * bytesPerPixel;
264 int srcOffset = srcRow * stride + srcCol * bytesPerPixel;
267 samples[0] = ReadChannel( mBuffer + srcOffset, mPixelFormat, Pixel::ALPHA );
269 if( srcCol < mWidth-1 )
271 samples[1] = ReadChannel( mBuffer + srcOffset+bytesPerPixel, mPixelFormat, Pixel::ALPHA );
275 samples[1] = samples[0];
278 if( srcRow < mHeight-1 )
280 samples[2] = ReadChannel( mBuffer + stride + srcOffset, mPixelFormat, Pixel::ALPHA );
284 samples[2] = samples[0];
287 if( srcRow < mHeight-1 && srcCol < mWidth-1 )
289 samples[3] = ReadChannel( mBuffer + stride + srcOffset + bytesPerPixel, mPixelFormat, Pixel::ALPHA );
293 samples[3] = samples[2];
296 // Bilinear interpolation:
298 weight[0] = float(srcRow+1.0f) - y;
299 weight[1] = y - float(srcRow);
300 weight[2] = float(srcCol+1.0f) - x;
301 weight[3] = x - float(srcCol);
303 return ( weight[2] * (samples[0] * weight[0] + samples[1] * weight[1]) +
304 weight[3] * (samples[2] * weight[0] + samples[3] * weight[1]) ) / 256.0f;
308 }// namespace Internal