2 * Copyright (c) 2022 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/alpha-mask.h>
18 #include <dali/internal/imaging/common/image-operations.h>
19 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
20 #include <dali/internal/imaging/common/pixel-manipulation.h>
21 #include <dali/public-api/images/image-operations.h> // For ImageDimensions and MultiplyAndNormalizeColor
29 void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
31 int srcAlphaByteOffset = 0;
33 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
35 if(Pixel::HasAlpha(srcPixelFormat))
37 Dali::Pixel::GetAlphaOffsetAndMask(srcPixelFormat, srcAlphaByteOffset, srcAlphaMask);
39 else if(srcPixelFormat == Pixel::L8)
44 int destAlphaByteOffset = 0;
45 int destAlphaMask = 0;
46 Dali::Pixel::Format destPixelFormat = buffer.GetPixelFormat();
47 Dali::Pixel::GetAlphaOffsetAndMask(destPixelFormat, destAlphaByteOffset, destAlphaMask);
49 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
50 unsigned char* srcBuffer = mask.GetBuffer();
51 unsigned char* destBuffer = buffer.GetBuffer();
53 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel(buffer.GetPixelFormat());
54 unsigned int srcStrideBytes = mask.GetStride() * srcBytesPerPixel;
55 unsigned int destStrideBytes = buffer.GetStride() * destBytesPerPixel;
57 // if image is premultiplied, the other channels of the image need to multiply by alpha.
58 if(buffer.IsAlphaPreMultiplied())
60 // Collect all valid channel list before lookup whole buffer
61 std::vector<Channel> validChannelList;
62 for(const Channel& channel : {Adaptor::RED, Adaptor::GREEN, Adaptor::BLUE, Adaptor::LUMINANCE, Adaptor::ALPHA})
64 if(HasChannel(destPixelFormat, channel))
66 validChannelList.emplace_back(channel);
69 if(DALI_LIKELY(!validChannelList.empty()))
71 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
76 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
78 auto srcAlpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
81 // If alpha is 255, we don't need to change color. Skip current pixel
82 // But if alpha is not 255, we should change color.
85 for(const Channel& channel : validChannelList)
87 auto color = ReadChannel(destBuffer + destOffset, destPixelFormat, channel);
88 WriteChannel(destBuffer + destOffset, destPixelFormat, channel, Platform::MultiplyAndNormalizeColor(color, srcAlpha));
93 // If alpha is 0, just set all pixel as zero.
94 memset(destBuffer + destOffset, 0, destBytesPerPixel);
98 srcOffset += srcBytesPerPixel;
99 destOffset += destBytesPerPixel;
101 srcBuffer += srcStrideBytes;
102 destBuffer += destStrideBytes;
108 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
113 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
115 uint8_t srcAlpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
116 uint8_t destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
118 destAlpha = Platform::MultiplyAndNormalizeColor(srcAlpha, destAlpha);
120 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
121 destBuffer[destOffset + destAlphaByteOffset] |= (destAlpha & destAlphaMask);
123 srcOffset += srcBytesPerPixel;
124 destOffset += destBytesPerPixel;
126 srcBuffer += srcStrideBytes;
127 destBuffer += destStrideBytes;
132 PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffer& mask)
134 // Set up source alpha offsets
135 int srcAlphaByteOffset = 0;
136 int srcAlphaMask = 0;
137 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
139 if(Pixel::HasAlpha(srcPixelFormat))
141 Dali::Pixel::GetAlphaOffsetAndMask(srcPixelFormat, srcAlphaByteOffset, srcAlphaMask);
143 else if(srcPixelFormat == Pixel::L8)
148 unsigned char* srcBuffer = mask.GetBuffer();
149 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
150 unsigned int srcStrideBytes = mask.GetStride() * srcBytesPerPixel;
152 // Set up source color offsets
153 Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
154 unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcColorPixelFormat);
155 unsigned int srcColorStrideBytes = buffer.GetStride() * srcColorBytesPerPixel;
157 // Setup destination offsets
158 Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
159 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel(destPixelFormat);
160 int destAlphaByteOffset = 0;
161 int destAlphaMask = 0;
162 Dali::Pixel::GetAlphaOffsetAndMask(destPixelFormat, destAlphaByteOffset, destAlphaMask);
164 PixelBufferPtr newPixelBuffer = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
165 unsigned char* destBuffer = newPixelBuffer->GetBuffer();
166 unsigned char* oldBuffer = buffer.GetBuffer();
167 unsigned int destStrideBytes = newPixelBuffer->GetStride() * destBytesPerPixel;
169 bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
171 unsigned char destAlpha = 0;
173 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
175 int srcAlphaOffset = 0;
176 int srcColorOffset = 0;
178 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
180 unsigned char srcAlpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
182 ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset);
186 destAlpha = ConvertAlphaChannelToA8(oldBuffer, srcColorOffset, srcColorPixelFormat);
187 destAlpha = Platform::MultiplyAndNormalizeColor(srcAlpha, destAlpha);
191 destAlpha = srcAlpha;
194 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
195 destBuffer[destOffset + destAlphaByteOffset] |= (destAlpha & destAlphaMask);
197 srcColorOffset += srcColorBytesPerPixel;
198 srcAlphaOffset += srcBytesPerPixel;
199 destOffset += destBytesPerPixel;
201 oldBuffer += srcColorStrideBytes;
202 srcBuffer += srcStrideBytes;
203 destBuffer += destStrideBytes;
206 return newPixelBuffer;
209 } //namespace Adaptor
211 } // namespace Internal