build: compile release APK and update dependencies (expo-image-manipulator/loader)
This commit is contained in:
+36
@@ -0,0 +1,36 @@
|
||||
import { CodedError } from 'expo-modules-core';
|
||||
|
||||
import { ActionCrop } from '../../ImageManipulator.types';
|
||||
import { getContext } from '../utils.web';
|
||||
|
||||
const clamp = (value: number, max: number): number => Math.max(0, Math.min(max, value));
|
||||
|
||||
export default (canvas: HTMLCanvasElement, options: ActionCrop['crop']) => {
|
||||
// ensure values are defined.
|
||||
let { originX = 0, originY = 0, width = 0, height = 0 } = options;
|
||||
// lock within bounds.
|
||||
width = clamp(width, canvas.width);
|
||||
height = clamp(height, canvas.height);
|
||||
originX = clamp(originX, canvas.width);
|
||||
originY = clamp(originY, canvas.height);
|
||||
|
||||
// lock sum of crop.
|
||||
width = Math.min(originX + width, canvas.width) - originX;
|
||||
height = Math.min(originY + height, canvas.height) - originY;
|
||||
|
||||
if (width === 0 || height === 0) {
|
||||
throw new CodedError(
|
||||
'ERR_IMAGE_MANIPULATOR_CROP',
|
||||
'Crop size must be greater than 0: ' + JSON.stringify(options, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
const result = document.createElement('canvas');
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
|
||||
const context = getContext(result);
|
||||
context.drawImage(canvas, originX, originY, width, height, 0, 0, width, height);
|
||||
|
||||
return result;
|
||||
};
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { CodedError } from 'expo-modules-core';
|
||||
|
||||
import { ActionExtent } from '../../ImageManipulator.types';
|
||||
import { getContext } from '../utils.web';
|
||||
|
||||
export default (canvas: HTMLCanvasElement, options: ActionExtent['extent']) => {
|
||||
// ensure values are defined.
|
||||
const { backgroundColor = null, originX = 0, originY = 0, width = 0, height = 0 } = options;
|
||||
|
||||
if (width === 0 || height === 0) {
|
||||
throw new CodedError(
|
||||
'ERR_IMAGE_MANIPULATOR_EXTENT',
|
||||
'Extent size must be greater than 0: ' + JSON.stringify(options, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
const result = document.createElement('canvas');
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
|
||||
const sx = originX < 0 ? 0 : originX;
|
||||
const sy = originY < 0 ? 0 : originY;
|
||||
const sw =
|
||||
originX < 0 ? Math.min(canvas.width, width + originX) : Math.min(canvas.width - originX, width);
|
||||
const sh =
|
||||
originY < 0
|
||||
? Math.min(canvas.height, height + originY)
|
||||
: Math.min(canvas.height - originY, height);
|
||||
|
||||
const dx = originX < 0 ? -originX : 0;
|
||||
const dy = originY < 0 ? -originY : 0;
|
||||
|
||||
const context = getContext(result);
|
||||
|
||||
if (backgroundColor != null) {
|
||||
context.fillStyle = backgroundColor;
|
||||
context.fillRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
context.drawImage(canvas, sx, sy, sw, sh, dx, dy, sw, sh);
|
||||
|
||||
return result;
|
||||
};
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { ActionFlip, FlipType } from '../../ImageManipulator.types';
|
||||
import { getContext } from '../utils.web';
|
||||
|
||||
export default (canvas: HTMLCanvasElement, flip: ActionFlip['flip']) => {
|
||||
const xFlip = flip === FlipType.Horizontal;
|
||||
const yFlip = flip === FlipType.Vertical;
|
||||
|
||||
const result = document.createElement('canvas');
|
||||
result.width = canvas.width;
|
||||
result.height = canvas.height;
|
||||
|
||||
const context = getContext(result);
|
||||
|
||||
// Set the origin to the center of the image
|
||||
context.translate(canvas.width / 2, canvas.height / 2);
|
||||
|
||||
// Flip/flop the canvas
|
||||
const xScale = xFlip ? -1 : 1;
|
||||
const yScale = yFlip ? -1 : 1;
|
||||
context.scale(xScale, yScale);
|
||||
|
||||
// Draw the image
|
||||
context.drawImage(canvas, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
|
||||
|
||||
return result;
|
||||
};
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
import { ActionResize } from '../../ImageManipulator.types';
|
||||
import { getContext } from '../utils.web';
|
||||
|
||||
/**
|
||||
* Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
|
||||
* https://stackoverflow.com/a/18320662/4047926
|
||||
*
|
||||
* @param {HTMLCanvasElement} canvas
|
||||
* @param {int} width
|
||||
* @param {int} height
|
||||
* @param {boolean} resizeCanvas if true, canvas will be resized. Optional.
|
||||
*/
|
||||
function resampleSingle(
|
||||
canvas: HTMLCanvasElement,
|
||||
width: number,
|
||||
height: number,
|
||||
resizeCanvas: boolean = false
|
||||
): HTMLCanvasElement {
|
||||
const result = document.createElement('canvas');
|
||||
result.width = canvas.width;
|
||||
result.height = canvas.height;
|
||||
|
||||
const widthSource = canvas.width;
|
||||
const heightSource = canvas.height;
|
||||
width = Math.round(width);
|
||||
height = Math.round(height);
|
||||
|
||||
const wRatio = widthSource / width;
|
||||
const hRatio = heightSource / height;
|
||||
const wRatioHalf = Math.ceil(wRatio / 2);
|
||||
const hRatioHalf = Math.ceil(hRatio / 2);
|
||||
|
||||
const ctx = getContext(canvas);
|
||||
|
||||
const img = ctx.getImageData(0, 0, widthSource, heightSource);
|
||||
const img2 = ctx.createImageData(width, height);
|
||||
const data = img.data;
|
||||
const data2 = img2.data;
|
||||
|
||||
for (let j = 0; j < height; j++) {
|
||||
for (let i = 0; i < width; i++) {
|
||||
const x2 = (i + j * width) * 4;
|
||||
let weight = 0;
|
||||
let weights = 0;
|
||||
let weightsAlpha = 0;
|
||||
let gx_r = 0;
|
||||
let gx_g = 0;
|
||||
let gx_b = 0;
|
||||
let gx_a = 0;
|
||||
const yCenter = (j + 0.5) * hRatio;
|
||||
const yy_start = Math.floor(j * hRatio);
|
||||
const yy_stop = Math.ceil((j + 1) * hRatio);
|
||||
for (let yy = yy_start; yy < yy_stop; yy++) {
|
||||
const dy = Math.abs(yCenter - (yy + 0.5)) / hRatioHalf;
|
||||
const center_x = (i + 0.5) * wRatio;
|
||||
const w0 = dy * dy; //pre-calc part of w
|
||||
const xx_start = Math.floor(i * wRatio);
|
||||
const xx_stop = Math.ceil((i + 1) * wRatio);
|
||||
for (let xx = xx_start; xx < xx_stop; xx++) {
|
||||
const dx = Math.abs(center_x - (xx + 0.5)) / wRatioHalf;
|
||||
const w = Math.sqrt(w0 + dx * dx);
|
||||
if (w >= 1) {
|
||||
//pixel too far
|
||||
continue;
|
||||
}
|
||||
//hermite filter
|
||||
weight = 2 * w * w * w - 3 * w * w + 1;
|
||||
const xPosition = 4 * (xx + yy * widthSource);
|
||||
//alpha
|
||||
gx_a += weight * data[xPosition + 3];
|
||||
weightsAlpha += weight;
|
||||
//colors
|
||||
if (data[xPosition + 3] < 255) {
|
||||
weight = (weight * data[xPosition + 3]) / 250;
|
||||
}
|
||||
gx_r += weight * data[xPosition];
|
||||
gx_g += weight * data[xPosition + 1];
|
||||
gx_b += weight * data[xPosition + 2];
|
||||
weights += weight;
|
||||
}
|
||||
}
|
||||
data2[x2] = gx_r / weights;
|
||||
data2[x2 + 1] = gx_g / weights;
|
||||
data2[x2 + 2] = gx_b / weights;
|
||||
data2[x2 + 3] = gx_a / weightsAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
//resize canvas
|
||||
if (resizeCanvas) {
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
}
|
||||
|
||||
//draw
|
||||
const context = getContext(result);
|
||||
context.putImageData(img2, 0, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default (canvas: HTMLCanvasElement, { width, height }: ActionResize['resize']) => {
|
||||
const imageRatio = canvas.width / canvas.height;
|
||||
|
||||
let requestedWidth: number = 0;
|
||||
let requestedHeight: number = 0;
|
||||
if (width !== undefined) {
|
||||
requestedWidth = width;
|
||||
requestedHeight = requestedWidth / imageRatio;
|
||||
}
|
||||
if (height !== undefined) {
|
||||
requestedHeight = height;
|
||||
if (requestedWidth === 0) {
|
||||
requestedWidth = requestedHeight * imageRatio;
|
||||
}
|
||||
}
|
||||
|
||||
return resampleSingle(canvas, requestedWidth, requestedHeight, true);
|
||||
};
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { ActionRotate } from '../../ImageManipulator.types';
|
||||
import { getContext } from '../utils.web';
|
||||
|
||||
function sizeFromAngle(
|
||||
width: number,
|
||||
height: number,
|
||||
angle: number
|
||||
): { width: number; height: number } {
|
||||
const radians = (angle * Math.PI) / 180;
|
||||
let c = Math.cos(radians);
|
||||
let s = Math.sin(radians);
|
||||
if (s < 0) {
|
||||
s = -s;
|
||||
}
|
||||
if (c < 0) {
|
||||
c = -c;
|
||||
}
|
||||
return { width: height * s + width * c, height: height * c + width * s };
|
||||
}
|
||||
|
||||
export default (canvas: HTMLCanvasElement, degrees: ActionRotate['rotate']) => {
|
||||
const { width, height } = sizeFromAngle(canvas.width, canvas.height, degrees);
|
||||
|
||||
const result = document.createElement('canvas');
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
|
||||
const context = getContext(result);
|
||||
|
||||
// Set the origin to the center of the image
|
||||
context.translate(result.width / 2, result.height / 2);
|
||||
|
||||
// Rotate the canvas around the origin
|
||||
const radians = (degrees * Math.PI) / 180;
|
||||
context.rotate(radians);
|
||||
|
||||
// Draw the image
|
||||
context.drawImage(canvas, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
|
||||
|
||||
return result;
|
||||
};
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export { default as crop } from './CropAction.web';
|
||||
export { default as extent } from './ExtentAction.web';
|
||||
export { default as flip } from './FlipAction.web';
|
||||
export { default as resize } from './ResizeAction.web';
|
||||
export { default as rotate } from './RotateAction.web';
|
||||
Reference in New Issue
Block a user