/*
* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { PixelMapTransformation } from './PixelMapTransformation';
import { Size } from '@kit.ArkUI';
import { image } from '@kit.ImageKit';
export interface rgbColor {
r_color: number,
g_color: number,
b_color: number,
}
/**
* 图片变换:圆环裁剪效果
*/
@Sendable
export class CropCircleWithBorderTransformation extends PixelMapTransformation {
private mBorderSize: number = 5;
private mCenterX: number = 0;
private mCenterY: number = 0;
private mRadius: number = 0;
private mRColor: number = 0;
private mGColor: number = 0;
private mBColor: number = 0;
constructor(borderSize: number, value: rgbColor) {
super();
this.mRColor = value.g_color;
this.mGColor = value.g_color;
this.mBColor = value.b_color;
this.mBorderSize = borderSize;
}
getConstructorParams() {
return JSON.stringify([this.mBorderSize, {
r_color: this.mRColor,
g_color: this.mGColor,
b_color: this.mBColor
}]);
}
getName(): string {
return this.constructor.name + ';mBorderSize:' + this.mBorderSize + ';mCenterX:' + this.mCenterX + ';mCenterY:'
+ this.mCenterY + ';mRadius:' + this.mRadius + ';mRColor:' + this.mRColor + ';mGColor:' + this.mGColor + ';mBColor:' + this.mBColor;
}
async transform(context: Context, toTransform: PixelMap, width: number, height: number): Promise<PixelMap> {
return await this.transformPixelMap(toTransform);
}
private async transformPixelMap(pixelMap: PixelMap): Promise<PixelMap> {
let imageInfo: image.ImageInfo = await pixelMap.getImageInfo();
let size: Size = {
width: imageInfo.size.width,
height: imageInfo.size.height
};
if (!size) {
console.error('CropCircleWithBorderTransformation The image size does not exist.');
return pixelMap;
}
let height: number = size.height;
let width: number = size.width;
this.mRadius = 0;
if (width > height) {
this.mRadius = height / 2;
} else {
this.mRadius = width / 2;
}
this.mCenterX = width / 2;
this.mCenterY = height / 2;
let bufferData = new ArrayBuffer(pixelMap.getPixelBytesNumber());
await pixelMap.readPixelsToBuffer(bufferData);
let dataArray = new Uint8Array(bufferData);
for (let h = 0; h <= height; h++) {
for (let w = 0; w <= width; w++) {
// 不在大圆之内的设置透明
// 在大圆与小圆之间的 设置rgb值
// 小圆之内的不变
let isSmallCircle: boolean = this.isContainsSmallCircle(w, h);
let isBigCircle: boolean = this.isContainsCircle(w, h);
if (isSmallCircle) {
continue;
}
let index = (h * width + w) * 4;
if (!isBigCircle) {
// 设置透明
dataArray[index] = 0;
dataArray[index+1] = 0;
dataArray[index+2] = 0;
dataArray[index+3] = 0;
} else {
// 设置broke
dataArray[index] = this.mRColor;
dataArray[index+1] = this.mGColor;
dataArray[index+2] = this.mBColor;
}
}
}
await pixelMap.writeBufferToPixels(bufferData);
return pixelMap;
}
isContainsCircle(x: number, y: number): boolean {
let a: number = Math.pow((this.mCenterX - x), 2);
let b: number = Math.pow((this.mCenterY - y), 2);
let c: number = Math.sqrt((a + b));
return c <= this.mRadius;
}
isContainsSmallCircle(x: number, y: number): boolean {
let a: number = Math.pow((this.mCenterX - x), 2);
let b: number = Math.pow((this.mCenterY - y), 2);
let c: number = Math.sqrt((a + b));
return c <= (this.mRadius - this.mBorderSize);
}
}