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 <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>
30 void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
32 int srcAlphaByteOffset=0;
34 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
36 if( Pixel::HasAlpha(srcPixelFormat) )
38 Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
40 else if( srcPixelFormat == Pixel::L8 )
45 int destAlphaByteOffset=0;
47 Dali::Pixel::Format destPixelFormat = buffer.GetPixelFormat();
48 Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
50 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
51 unsigned char* srcBuffer = mask.GetBuffer();
52 unsigned char* destBuffer = buffer.GetBuffer();
54 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
59 float srcAlphaValue = 1.0f;
61 // if image is premultiplied, the other channels of the image need to multiply by alpha.
62 if( buffer.IsAlphaPreMultiplied() )
64 for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
66 for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
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);
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 );
81 srcOffset += srcBytesPerPixel;
82 destOffset += destBytesPerPixel;
88 for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
90 for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
92 unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
93 srcAlphaValue = float(alpha)/255.0f;
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 );
101 srcOffset += srcBytesPerPixel;
102 destOffset += destBytesPerPixel;
108 PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
110 // Set up source alpha offsets
111 int srcAlphaByteOffset=0;
113 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
115 if( Pixel::HasAlpha(srcPixelFormat) )
117 Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
119 else if( srcPixelFormat == Pixel::L8 )
124 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
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();
141 unsigned char* oldBuffer = buffer.GetBuffer();
143 int srcAlphaOffset=0;
144 int srcColorOffset=0;
146 bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
148 float srcAlphaValue = 1.0f;
149 unsigned char destAlpha = 0;
151 for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
153 for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
155 unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
156 srcAlphaValue = float(alpha)/255.0f;
158 ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
162 destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat );
163 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
164 destAlpha = destAlphaValue;
168 destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
171 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
172 destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
174 srcColorOffset += srcColorBytesPerPixel;
175 srcAlphaOffset += srcBytesPerPixel;
176 destOffset += destBytesPerPixel;
180 return newPixelBuffer;
183 } //namespace Adaptor
185 }// namespace Internal