缩短非GPU加速下图片马赛克处理近3倍时间
Signed-off-by: Bo Lan <mai925093@gmail.com>
This commit is contained in:
parent
4d5728dc3a
commit
6cc1d077d6
|
@ -13,20 +13,20 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CalculatePixelUtils} from "./CalculatePixelUtils"
|
import { CalculatePixelUtils } from "./CalculatePixelUtils"
|
||||||
import {PixelEntry} from "../entry/PixelEntry"
|
import { PixelEntry } from "../entry/PixelEntry"
|
||||||
import {AsyncTransform} from "../transform/AsyncTransform"
|
import { AsyncTransform } from "../transform/AsyncTransform"
|
||||||
import {ColorUtils} from "./ColorUtils"
|
import { ColorUtils } from "./ColorUtils"
|
||||||
import {Size} from "../../imageknife/RequestOption"
|
import { Size } from "../../imageknife/RequestOption"
|
||||||
import {GPUImagePixelationFilter} from '@ohos/gpu_transform'
|
import { GPUImagePixelationFilter } from '@ohos/gpu_transform'
|
||||||
import image from '@ohos.multimedia.image';
|
import image from '@ohos.multimedia.image';
|
||||||
|
|
||||||
export namespace pixelUtils {
|
export namespace pixelUtils {
|
||||||
|
|
||||||
export async function pixel(bitmap: PixelMap, pixel: number, func?: AsyncTransform<PixelMap>) {
|
export async function pixel(bitmap: PixelMap, pixel: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
|
||||||
let imageInfo:image.ImageInfo= await bitmap.getImageInfo();
|
let imageInfo: image.ImageInfo = await bitmap.getImageInfo();
|
||||||
let size:Size = {
|
let size: Size = {
|
||||||
width: imageInfo.size.width,
|
width: imageInfo.size.width,
|
||||||
height: imageInfo.size.height
|
height: imageInfo.size.height
|
||||||
}
|
}
|
||||||
|
@ -34,43 +34,14 @@ export namespace pixelUtils {
|
||||||
func?.asyncTransform("GrayscaleTransformation The image size does not exist.", null)
|
func?.asyncTransform("GrayscaleTransformation The image size does not exist.", null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let targetWidth:number = size.width;
|
|
||||||
let targetHeight:number = size.height;
|
|
||||||
|
|
||||||
let pixEntry: Array<PixelEntry> = new Array()
|
let targetWidth: number = size.width;
|
||||||
let inPixels: Array<Array<number>> = CalculatePixelUtils.createInt2DArray(targetHeight, targetWidth);
|
let targetHeight: number = size.height;
|
||||||
|
|
||||||
let bufferData = new ArrayBuffer(bitmap.getPixelBytesNumber());
|
let bufferData = new ArrayBuffer(bitmap.getPixelBytesNumber());
|
||||||
await bitmap.readPixelsToBuffer(bufferData);
|
await bitmap.readPixelsToBuffer(bufferData);
|
||||||
let dataArray = new Uint8Array(bufferData);
|
let dataArray = new Uint8Array(bufferData);
|
||||||
|
|
||||||
let ph:number = 0;
|
|
||||||
let pw:number = 0;
|
|
||||||
|
|
||||||
|
|
||||||
for (let index = 0; index < dataArray.length; index += 4) {
|
|
||||||
const r = dataArray[index];
|
|
||||||
const g = dataArray[index+1];
|
|
||||||
const b = dataArray[index+2];
|
|
||||||
const f = dataArray[index+3];
|
|
||||||
|
|
||||||
let entry = new PixelEntry();
|
|
||||||
entry.a = 0;
|
|
||||||
entry.b = b;
|
|
||||||
entry.g = g;
|
|
||||||
entry.r = r;
|
|
||||||
entry.f = f;
|
|
||||||
entry.pixel = ColorUtils.rgb(entry.r, entry.g, entry.b);
|
|
||||||
pixEntry.push(entry);
|
|
||||||
inPixels[ph][pw] = ColorUtils.rgb(entry.r, entry.g, entry.b);
|
|
||||||
if (pw == targetWidth - 1) {
|
|
||||||
pw = 0;
|
|
||||||
ph++;
|
|
||||||
} else {
|
|
||||||
pw++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let realPixel_W = pixel > targetWidth ? targetWidth : pixel;
|
let realPixel_W = pixel > targetWidth ? targetWidth : pixel;
|
||||||
let realPixel_H = pixel > targetHeight ? targetHeight : pixel;
|
let realPixel_H = pixel > targetHeight ? targetHeight : pixel;
|
||||||
|
|
||||||
|
@ -78,54 +49,54 @@ export namespace pixelUtils {
|
||||||
let x_index = Math.floor(targetWidth / realPixel_W);
|
let x_index = Math.floor(targetWidth / realPixel_W);
|
||||||
// 纵排的正方形个数
|
// 纵排的正方形个数
|
||||||
let y_index = Math.floor(targetHeight / realPixel_H);
|
let y_index = Math.floor(targetHeight / realPixel_H);
|
||||||
|
let inPixels: Array<Array<number>> = CalculatePixelUtils.createInt2DArray(y_index, x_index)
|
||||||
|
|
||||||
|
// 每个马赛克块左上角的像素在图片一维数组中对应的索引位置
|
||||||
|
let startIndex = 0
|
||||||
|
// 像素步进数
|
||||||
|
const PIXEL_STEP = 4
|
||||||
|
// 图片马赛克化之后,一行马赛克所包含的像素数
|
||||||
|
const mosaicRowPixels = targetWidth * pixel * PIXEL_STEP
|
||||||
for (let ch = 0; ch < y_index; ch++) {
|
for (let ch = 0; ch < y_index; ch++) {
|
||||||
for (let cw = 0; cw < x_index; cw++) {
|
for (let cw = 0; cw < x_index; cw++) {
|
||||||
|
startIndex = mosaicRowPixels * ch + cw * pixel * PIXEL_STEP
|
||||||
let max_x = (cw + 1) * realPixel_W > targetWidth ? targetWidth : (cw + 1) * realPixel_W;
|
const r = dataArray[startIndex]
|
||||||
let max_y = (ch + 1) * realPixel_H > targetHeight ? targetHeight : (ch + 1) * realPixel_H;
|
const g = dataArray[startIndex+1];
|
||||||
|
const b = dataArray[startIndex+2];
|
||||||
|
const f = dataArray[startIndex+3];
|
||||||
let min_x = cw * realPixel_W;
|
let entry = new PixelEntry();
|
||||||
let min_y = ch * realPixel_H;
|
entry.a = 0;
|
||||||
|
entry.b = b;
|
||||||
// 取左上角的像素值
|
entry.g = g;
|
||||||
let center_p = inPixels[min_y+1][min_x+1];
|
entry.r = r;
|
||||||
// 设置该正方形里的像素统一
|
entry.f = f;
|
||||||
for (let zh = min_y; zh < max_y; zh++) {
|
inPixels[ch][cw] = ColorUtils.rgb(entry.r, entry.g, entry.b);
|
||||||
for (let zw = min_x; zw < max_x; zw++) {
|
|
||||||
inPixels[zh][zw] = center_p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let bufferNewData = new ArrayBuffer(bitmap.getPixelBytesNumber());
|
let bufferNewData = new ArrayBuffer(bitmap.getPixelBytesNumber());
|
||||||
let dataNewArray = new Uint8Array(bufferNewData);
|
let dataNewArray = new Uint8Array(bufferNewData);
|
||||||
let index = 0;
|
|
||||||
let mh = 0;
|
|
||||||
let nw = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < dataNewArray.length; i += 4) {
|
for (let i = 0; i < dataNewArray.length; i += PIXEL_STEP) {
|
||||||
let pixel_1 = inPixels[mh][nw];
|
// 像素在二维数组中纵轴方向上的索引
|
||||||
|
let y = Math.floor(i / targetHeight / PIXEL_STEP)
|
||||||
|
// 像素在二维数组中横轴方向上的索引
|
||||||
|
let x = Math.floor((i - (y * targetHeight * PIXEL_STEP)) / PIXEL_STEP)
|
||||||
|
|
||||||
if (nw == targetWidth - 1) {
|
// 对应马赛克块二维数组的位置
|
||||||
nw = 0;
|
y = Math.floor(y / pixel)
|
||||||
mh++;
|
x = Math.floor(x / pixel)
|
||||||
} else {
|
|
||||||
nw++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let p_r = ColorUtils.red(pixel_1);
|
// 未被马赛克覆盖的部分,用最近的色块颜色覆盖
|
||||||
let p_g = ColorUtils.green(pixel_1);
|
y = y >= y_index ? y_index - 1 : y
|
||||||
let p_b = ColorUtils.blue(pixel_1);
|
x = x >= x_index ? x_index - 1 : x
|
||||||
|
|
||||||
dataNewArray[i] = p_r;
|
const color = inPixels[y][x]
|
||||||
dataNewArray[i+1] = p_g;
|
|
||||||
dataNewArray[i+2] = p_b;
|
dataNewArray[i] = ColorUtils.red(color);
|
||||||
dataNewArray[i+3] = pixEntry[index].f;
|
dataNewArray[i+1] = ColorUtils.green(color);
|
||||||
index++;
|
dataNewArray[i+2] = ColorUtils.blue(color);
|
||||||
|
dataNewArray[i+3] = ColorUtils.alpha(color)
|
||||||
}
|
}
|
||||||
await bitmap.writeBufferToPixels(bufferNewData);
|
await bitmap.writeBufferToPixels(bufferNewData);
|
||||||
if (func) {
|
if (func) {
|
||||||
|
@ -134,8 +105,8 @@ export namespace pixelUtils {
|
||||||
}
|
}
|
||||||
export async function pixelGPU(bitmap: PixelMap, pixel: number, func?: AsyncTransform<PixelMap>) {
|
export async function pixelGPU(bitmap: PixelMap, pixel: number, func?: AsyncTransform<PixelMap>) {
|
||||||
|
|
||||||
let imageInfo:image.ImageInfo = await bitmap.getImageInfo();
|
let imageInfo: image.ImageInfo = await bitmap.getImageInfo();
|
||||||
let size:Size = {
|
let size: Size = {
|
||||||
width: imageInfo.size.width,
|
width: imageInfo.size.width,
|
||||||
height: imageInfo.size.height
|
height: imageInfo.size.height
|
||||||
}
|
}
|
||||||
|
@ -153,7 +124,7 @@ export namespace pixelUtils {
|
||||||
filter.setPixel(pixel)
|
filter.setPixel(pixel)
|
||||||
filter.getPixelMapBuf(0, 0, w, h).then((buf) => {
|
filter.getPixelMapBuf(0, 0, w, h).then((buf) => {
|
||||||
bitmap.writeBufferToPixels(buf);
|
bitmap.writeBufferToPixels(buf);
|
||||||
if (func!=undefined) {
|
if (func != undefined) {
|
||||||
func?.asyncTransform("success", bitmap);
|
func?.asyncTransform("success", bitmap);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue