2 * Copyright (c) 2021 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
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());
58 float srcAlphaValue = 1.0f;
60 // if image is premultiplied, the other channels of the image need to multiply by alpha.
61 if(buffer.IsAlphaPreMultiplied())
63 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
65 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
67 auto srcAlpha = ReadChannel(srcBuffer + srcOffset, srcPixelFormat, Adaptor::ALPHA);
68 auto destRed = ReadChannel(destBuffer + destOffset, destPixelFormat, Adaptor::RED);
69 auto destGreen = ReadChannel(destBuffer + destOffset, destPixelFormat, Adaptor::GREEN);
70 auto destBlue = ReadChannel(destBuffer + destOffset, destPixelFormat, Adaptor::BLUE);
71 auto destLuminance = ReadChannel(destBuffer + destOffset, destPixelFormat, Adaptor::LUMINANCE);
72 auto destAlpha = ReadChannel(destBuffer + destOffset, destPixelFormat, Adaptor::ALPHA);
74 WriteChannel(destBuffer + destOffset, destPixelFormat, Adaptor::RED, destRed * srcAlpha / 255);
75 WriteChannel(destBuffer + destOffset, destPixelFormat, Adaptor::GREEN, destGreen * srcAlpha / 255);
76 WriteChannel(destBuffer + destOffset, destPixelFormat, Adaptor::BLUE, destBlue * srcAlpha / 255);
77 WriteChannel(destBuffer + destOffset, destPixelFormat, Adaptor::LUMINANCE, destLuminance * srcAlpha / 255);
78 WriteChannel(destBuffer + destOffset, destPixelFormat, Adaptor::ALPHA, destAlpha * srcAlpha / 255);
80 srcOffset += srcBytesPerPixel;
81 destOffset += destBytesPerPixel;
87 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
89 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
91 unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
92 srcAlphaValue = float(alpha) / 255.0f;
94 unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
95 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
96 destAlpha = destAlphaValue;
97 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
98 destBuffer[destOffset + destAlphaByteOffset] |= (destAlpha & destAlphaMask);
100 srcOffset += srcBytesPerPixel;
101 destOffset += destBytesPerPixel;
107 PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffer& mask)
109 // Set up source alpha offsets
110 int srcAlphaByteOffset = 0;
111 int srcAlphaMask = 0;
112 Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
114 if(Pixel::HasAlpha(srcPixelFormat))
116 Dali::Pixel::GetAlphaOffsetAndMask(srcPixelFormat, srcAlphaByteOffset, srcAlphaMask);
118 else if(srcPixelFormat == Pixel::L8)
123 unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
124 unsigned char* srcBuffer = mask.GetBuffer();
126 // Set up source color offsets
127 Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
128 unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcColorPixelFormat);
130 // Setup destination offsets
131 Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
132 unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel(destPixelFormat);
133 int destAlphaByteOffset = 0;
134 int destAlphaMask = 0;
135 Dali::Pixel::GetAlphaOffsetAndMask(destPixelFormat, destAlphaByteOffset, destAlphaMask);
137 PixelBufferPtr newPixelBuffer = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
138 unsigned char* destBuffer = newPixelBuffer->GetBuffer();
139 unsigned char* oldBuffer = buffer.GetBuffer();
141 int srcAlphaOffset = 0;
142 int srcColorOffset = 0;
144 bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
146 float srcAlphaValue = 1.0f;
147 unsigned char destAlpha = 0;
149 for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
151 for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
153 unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
154 srcAlphaValue = float(alpha) / 255.0f;
156 ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset);
160 destAlpha = ConvertAlphaChannelToA8(oldBuffer, srcColorOffset, srcColorPixelFormat);
161 float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
162 destAlpha = destAlphaValue;
166 destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
169 destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
170 destBuffer[destOffset + destAlphaByteOffset] |= (destAlpha & destAlphaMask);
172 srcColorOffset += srcColorBytesPerPixel;
173 srcAlphaOffset += srcBytesPerPixel;
174 destOffset += destBytesPerPixel;
178 return newPixelBuffer;
181 } //namespace Adaptor
183 } // namespace Internal