pixel-data-js 0.24.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.dev.cjs +1476 -1834
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +1465 -1816
- package/dist/index.dev.js.map +1 -1
- package/dist/index.prod.cjs +1475 -1833
- package/dist/index.prod.cjs.map +1 -1
- package/dist/index.prod.d.ts +233 -310
- package/dist/index.prod.js +1465 -1816
- package/dist/index.prod.js.map +1 -1
- package/package.json +1 -1
- package/src/Algorithm/floodFillSelection.ts +2 -2
- package/src/Canvas/canvas-blend-modes.ts +28 -0
- package/src/History/PixelAccumulator.ts +52 -29
- package/src/History/PixelEngineConfig.ts +7 -9
- package/src/History/PixelMutator/mutatorBlendPaintMask.ts +60 -0
- package/src/History/PixelMutator/mutatorBlendPixelData.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataAlphaMask.ts +2 -2
- package/src/History/PixelMutator/mutatorBlendPixelDataBinaryMask.ts +2 -2
- package/src/History/PixelMutator.ts +0 -20
- package/src/History/PixelPatchTiles.ts +2 -2
- package/src/History/PixelWriter.ts +132 -9
- package/src/Internal/helpers.ts +2 -0
- package/src/Paint/PaintBuffer.ts +269 -0
- package/src/{PixelTile/PaintBufferRenderer.ts → Paint/PaintBufferCanvasRenderer.ts} +13 -5
- package/src/Paint/makeCirclePaintAlphaMask.ts +41 -0
- package/src/{Mask/CircleBinaryMask.ts → Paint/makeCirclePaintBinaryMask.ts} +5 -6
- package/src/Paint/makePaintMask.ts +28 -0
- package/src/Paint/makeRectFalloffPaintAlphaMask.ts +47 -0
- package/src/PixelData/PixelBuffer32.ts +2 -2
- package/src/PixelData/PixelData.ts +1 -1
- package/src/PixelData/applyAlphaMaskToPixelData.ts +2 -2
- package/src/PixelData/applyBinaryMaskToPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelData.ts +2 -2
- package/src/PixelData/blendColorPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendColorPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixel.ts +2 -2
- package/src/PixelData/blendPixelData.ts +3 -3
- package/src/PixelData/blendPixelDataAlphaMask.ts +3 -3
- package/src/PixelData/blendPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/blendPixelDataPaintBuffer.ts +3 -3
- package/src/PixelData/clearPixelData.ts +2 -2
- package/src/PixelData/extractPixelData.ts +4 -4
- package/src/PixelData/extractPixelDataBuffer.ts +4 -4
- package/src/PixelData/fillPixelData.ts +5 -5
- package/src/PixelData/fillPixelDataBinaryMask.ts +3 -3
- package/src/PixelData/fillPixelDataFast.ts +5 -5
- package/src/PixelData/invertPixelData.ts +2 -2
- package/src/PixelData/pixelDataToAlphaMask.ts +2 -2
- package/src/PixelData/reflectPixelData.ts +3 -3
- package/src/PixelData/resamplePixelData.ts +2 -2
- package/src/PixelData/writePaintBufferToPixelData.ts +26 -0
- package/src/PixelData/writePixelDataBuffer.ts +5 -5
- package/src/Rect/trimMaskRectBounds.ts +121 -0
- package/src/Rect/trimRectBounds.ts +25 -116
- package/src/_types.ts +16 -15
- package/src/index.ts +11 -24
- package/src/History/PixelMutator/mutatorApplyCircleBrushStroke.ts +0 -182
- package/src/History/PixelMutator/mutatorApplyCirclePencil.ts +0 -59
- package/src/History/PixelMutator/mutatorApplyCirclePencilStroke.ts +0 -172
- package/src/History/PixelMutator/mutatorApplyRectBrush.ts +0 -64
- package/src/History/PixelMutator/mutatorApplyRectBrushStroke.ts +0 -184
- package/src/History/PixelMutator/mutatorApplyRectPencil.ts +0 -65
- package/src/History/PixelMutator/mutatorApplyRectPencilStroke.ts +0 -166
- package/src/History/PixelMutator/mutatorBlendColorCircleMask.ts +0 -71
- package/src/Mask/CircleAlphaMask.ts +0 -32
- package/src/PixelData/applyRectBrushToPixelData.ts +0 -98
- package/src/PixelData/blendColorPixelDataCircleMask.ts +0 -92
- package/src/PixelTile/PaintBuffer.ts +0 -122
- package/src/Rect/getCircleBrushOrPencilBounds.ts +0 -43
- package/src/Rect/getCircleBrushOrPencilStrokeBounds.ts +0 -24
- package/src/Rect/getRectBrushOrPencilBounds.ts +0 -38
- package/src/Rect/getRectBrushOrPencilStrokeBounds.ts +0 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IPixelData32, Rect } from '../_types'
|
|
2
2
|
import { extractPixelDataBuffer } from './extractPixelDataBuffer'
|
|
3
3
|
import { PixelData } from './PixelData'
|
|
4
4
|
|
|
@@ -6,10 +6,10 @@ import { PixelData } from './PixelData'
|
|
|
6
6
|
* High-level extraction that returns a new PixelData instance.
|
|
7
7
|
* Leverages extractPixelDataBuffer for optimized 32-bit memory moves.
|
|
8
8
|
*/
|
|
9
|
-
export function extractPixelData(source:
|
|
10
|
-
export function extractPixelData(source:
|
|
9
|
+
export function extractPixelData(source: IPixelData32, rect: Rect): PixelData
|
|
10
|
+
export function extractPixelData(source: IPixelData32, x: number, y: number, w: number, h: number): PixelData
|
|
11
11
|
export function extractPixelData(
|
|
12
|
-
source:
|
|
12
|
+
source: IPixelData32,
|
|
13
13
|
_x: Rect | number,
|
|
14
14
|
_y?: number,
|
|
15
15
|
_w?: number,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IPixelData32, Rect } from '../_types'
|
|
2
2
|
import { makeClippedBlit, resolveBlitClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_BLIT = makeClippedBlit()
|
|
@@ -7,10 +7,10 @@ const SCRATCH_BLIT = makeClippedBlit()
|
|
|
7
7
|
* Extracts a rectangular region of pixels from PixelData.
|
|
8
8
|
* Returns a new Uint32Array containing the extracted pixels.
|
|
9
9
|
*/
|
|
10
|
-
export function extractPixelDataBuffer(source:
|
|
11
|
-
export function extractPixelDataBuffer(source:
|
|
10
|
+
export function extractPixelDataBuffer(source: IPixelData32, rect: Rect): Uint32Array
|
|
11
|
+
export function extractPixelDataBuffer(source: IPixelData32, x: number, y: number, w: number, h: number): Uint32Array
|
|
12
12
|
export function extractPixelDataBuffer(
|
|
13
|
-
source:
|
|
13
|
+
source: IPixelData32,
|
|
14
14
|
_x: Rect | number,
|
|
15
15
|
_y?: number,
|
|
16
16
|
_w?: number,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Color32,
|
|
1
|
+
import type { Color32, IPixelData32, Rect } from '../_types'
|
|
2
2
|
import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_RECT = makeClippedRect()
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Fills a region or the {@link
|
|
7
|
+
* Fills a region or the {@link IPixelData32} buffer with a solid color.
|
|
8
8
|
*
|
|
9
9
|
* @param dst - The target to modify.
|
|
10
10
|
* @param color - The color to apply.
|
|
@@ -12,7 +12,7 @@ const SCRATCH_RECT = makeClippedRect()
|
|
|
12
12
|
* @returns true if any pixels were actually modified.
|
|
13
13
|
*/
|
|
14
14
|
export function fillPixelData(
|
|
15
|
-
dst:
|
|
15
|
+
dst: IPixelData32,
|
|
16
16
|
color: Color32,
|
|
17
17
|
rect?: Partial<Rect>,
|
|
18
18
|
): boolean
|
|
@@ -25,7 +25,7 @@ export function fillPixelData(
|
|
|
25
25
|
* @param h - Height of the fill area.
|
|
26
26
|
*/
|
|
27
27
|
export function fillPixelData(
|
|
28
|
-
dst:
|
|
28
|
+
dst: IPixelData32,
|
|
29
29
|
color: Color32,
|
|
30
30
|
x: number,
|
|
31
31
|
y: number,
|
|
@@ -33,7 +33,7 @@ export function fillPixelData(
|
|
|
33
33
|
h: number,
|
|
34
34
|
): boolean
|
|
35
35
|
export function fillPixelData(
|
|
36
|
-
dst:
|
|
36
|
+
dst: IPixelData32,
|
|
37
37
|
color: Color32,
|
|
38
38
|
_x?: Partial<Rect> | number,
|
|
39
39
|
_y?: number,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { BinaryMask, Color32,
|
|
1
|
+
import type { BinaryMask, Color32, IPixelData32 } from '../_types'
|
|
2
2
|
import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_RECT = makeClippedRect()
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Fills a region of the {@link
|
|
7
|
+
* Fills a region of the {@link IPixelData32} buffer with a solid color using a mask.
|
|
8
8
|
* @param dst - The target to modify.
|
|
9
9
|
* @param color - The color to apply.
|
|
10
10
|
* @param mask - The mask defining the area to fill.
|
|
@@ -13,7 +13,7 @@ const SCRATCH_RECT = makeClippedRect()
|
|
|
13
13
|
* @param y - Starting vertical coordinate for the mask placement.
|
|
14
14
|
*/
|
|
15
15
|
export function fillPixelDataBinaryMask(
|
|
16
|
-
dst:
|
|
16
|
+
dst: IPixelData32,
|
|
17
17
|
color: Color32,
|
|
18
18
|
mask: BinaryMask,
|
|
19
19
|
alpha = 255,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Color32,
|
|
1
|
+
import type { Color32, IPixelData32, Rect } from '../_types'
|
|
2
2
|
import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_RECT = makeClippedRect()
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Fills a region or the {@link
|
|
7
|
+
* Fills a region or the {@link IPixelData32} buffer with a solid color.
|
|
8
8
|
* This function is faster than {@link fillPixelData} but does not
|
|
9
9
|
* return a boolean value indicating changes were made.
|
|
10
10
|
*
|
|
@@ -14,7 +14,7 @@ const SCRATCH_RECT = makeClippedRect()
|
|
|
14
14
|
* buffer is filled.
|
|
15
15
|
*/
|
|
16
16
|
export function fillPixelDataFast(
|
|
17
|
-
dst:
|
|
17
|
+
dst: IPixelData32,
|
|
18
18
|
color: Color32,
|
|
19
19
|
rect?: Partial<Rect>,
|
|
20
20
|
): void
|
|
@@ -27,7 +27,7 @@ export function fillPixelDataFast(
|
|
|
27
27
|
* @param h - Height of the fill area.
|
|
28
28
|
*/
|
|
29
29
|
export function fillPixelDataFast(
|
|
30
|
-
dst:
|
|
30
|
+
dst: IPixelData32,
|
|
31
31
|
color: Color32,
|
|
32
32
|
x: number,
|
|
33
33
|
y: number,
|
|
@@ -35,7 +35,7 @@ export function fillPixelDataFast(
|
|
|
35
35
|
h: number,
|
|
36
36
|
): void
|
|
37
37
|
export function fillPixelDataFast(
|
|
38
|
-
dst:
|
|
38
|
+
dst: IPixelData32,
|
|
39
39
|
color: Color32,
|
|
40
40
|
_x?: Partial<Rect> | number,
|
|
41
41
|
_y?: number,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type IPixelData32, type PixelMutateOptions } from '../_types'
|
|
2
2
|
import { makeClippedRect, resolveRectClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_RECT = makeClippedRect()
|
|
5
5
|
|
|
6
6
|
export function invertPixelData(
|
|
7
|
-
pixelData:
|
|
7
|
+
pixelData: IPixelData32,
|
|
8
8
|
opts: PixelMutateOptions = {},
|
|
9
9
|
): boolean {
|
|
10
10
|
const dst = pixelData
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AlphaMask,
|
|
1
|
+
import type { AlphaMask, IPixelData32 } from '../_types'
|
|
2
2
|
import { makeAlphaMask } from '../Mask/AlphaMask'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,7 +6,7 @@ import { makeAlphaMask } from '../Mask/AlphaMask'
|
|
|
6
6
|
* Returns a Uint8Array branded as AlphaMask.
|
|
7
7
|
*/
|
|
8
8
|
export function pixelDataToAlphaMask(
|
|
9
|
-
pixelData:
|
|
9
|
+
pixelData: IPixelData32,
|
|
10
10
|
): AlphaMask {
|
|
11
11
|
const {
|
|
12
12
|
data32,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IPixelData32 } from '../_types'
|
|
2
2
|
|
|
3
|
-
export function reflectPixelDataHorizontal(pixelData:
|
|
3
|
+
export function reflectPixelDataHorizontal(pixelData: IPixelData32): void {
|
|
4
4
|
const width = pixelData.width
|
|
5
5
|
const height = pixelData.height
|
|
6
6
|
const data = pixelData.data32
|
|
@@ -20,7 +20,7 @@ export function reflectPixelDataHorizontal(pixelData: IPixelData): void {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export function reflectPixelDataVertical(pixelData:
|
|
23
|
+
export function reflectPixelDataVertical(pixelData: IPixelData32): void {
|
|
24
24
|
const width = pixelData.width
|
|
25
25
|
const height = pixelData.height
|
|
26
26
|
const data = pixelData.data32
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type IPixelData32, PixelData } from '../index'
|
|
2
2
|
import { resample32 } from '../Internal/resample32'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,7 +6,7 @@ import { resample32 } from '../Internal/resample32'
|
|
|
6
6
|
* Factor > 1 upscales, Factor < 1 downscales.
|
|
7
7
|
*/
|
|
8
8
|
export function resamplePixelData(
|
|
9
|
-
pixelData:
|
|
9
|
+
pixelData: IPixelData32,
|
|
10
10
|
factor: number,
|
|
11
11
|
): PixelData {
|
|
12
12
|
const { data, width, height } = resample32(pixelData.data32, pixelData.width, pixelData.height, factor)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { IPixelData } from '../_types'
|
|
2
|
+
import type { PaintBuffer } from '../Paint/PaintBuffer'
|
|
3
|
+
import { writePixelDataBuffer } from './writePixelDataBuffer'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param writePixelDataBufferFn - @hidden
|
|
7
|
+
*/
|
|
8
|
+
export function writePaintBufferToPixelData(
|
|
9
|
+
target: IPixelData,
|
|
10
|
+
paintBuffer: PaintBuffer,
|
|
11
|
+
writePixelDataBufferFn = writePixelDataBuffer,
|
|
12
|
+
) {
|
|
13
|
+
const tileShift = paintBuffer.config.tileShift
|
|
14
|
+
const lookup = paintBuffer.lookup
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < lookup.length; i++) {
|
|
17
|
+
const tile = lookup[i]
|
|
18
|
+
|
|
19
|
+
if (tile) {
|
|
20
|
+
const dx = tile.tx << tileShift
|
|
21
|
+
const dy = tile.ty << tileShift
|
|
22
|
+
|
|
23
|
+
writePixelDataBufferFn(target, tile.data32, dx, dy, tile.width, tile.height)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type IPixelData32, type Rect } from '../_types'
|
|
2
2
|
import { makeClippedBlit, resolveBlitClipping } from '../Internal/resolveClipping'
|
|
3
3
|
|
|
4
4
|
const SCRATCH_BLIT = makeClippedBlit()
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Copies a pixel buffer into a specific region of a {@link
|
|
7
|
+
* Copies a pixel buffer into a specific region of a {@link IPixelData32} object.
|
|
8
8
|
*
|
|
9
9
|
* This function performs a direct memory copy from a {@link Uint32Array}
|
|
10
10
|
* into the target buffer.
|
|
11
11
|
*/
|
|
12
12
|
export function writePixelDataBuffer(
|
|
13
|
-
target:
|
|
13
|
+
target: IPixelData32,
|
|
14
14
|
data: Uint32Array,
|
|
15
15
|
rect: Rect,
|
|
16
16
|
): void
|
|
17
17
|
export function writePixelDataBuffer(
|
|
18
|
-
target:
|
|
18
|
+
target: IPixelData32,
|
|
19
19
|
data: Uint32Array,
|
|
20
20
|
x: number,
|
|
21
21
|
y: number,
|
|
@@ -23,7 +23,7 @@ export function writePixelDataBuffer(
|
|
|
23
23
|
h: number,
|
|
24
24
|
): void
|
|
25
25
|
export function writePixelDataBuffer(
|
|
26
|
-
target:
|
|
26
|
+
target: IPixelData32,
|
|
27
27
|
data: Uint32Array,
|
|
28
28
|
_x: Rect | number,
|
|
29
29
|
_y?: number,
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { NullableMaskRect, Rect } from '../_types'
|
|
2
|
+
import { extractMaskBuffer } from '../Mask/extractMaskBuffer'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Intersects a target rectangle with a boundary, trimming dimensions and masks in-place.
|
|
6
|
+
* This utility calculates the axis-aligned intersection between the `target` and `bounds`.
|
|
7
|
+
* If the `target` includes a `mask` (as in a {@link NullableMaskRect}), the mask is physically
|
|
8
|
+
* cropped and re-aligned using `extractMaskBuffer` to match the new dimensions.
|
|
9
|
+
* @param target - The rectangle or selection object to be trimmed. **Note:** This object is mutated in-place.
|
|
10
|
+
* @param bounds - The boundary rectangle defining the maximum allowable area (e.g., canvas dimensions).
|
|
11
|
+
* @example
|
|
12
|
+
* const selection = { x: -10, y: -10, w: 50, h: 50, mask: new Uint8Array(2500) };
|
|
13
|
+
* const canvas = { x: 0, y: 0, w: 100, h: 100 };
|
|
14
|
+
* // Selection will be moved to (0,0) and resized to 40x40.
|
|
15
|
+
* // The mask is cropped by 10 px on the top and left.
|
|
16
|
+
* trimRectBounds(selection, canvas);
|
|
17
|
+
*/
|
|
18
|
+
export function trimMaskRectBounds<T extends NullableMaskRect>(
|
|
19
|
+
target: T,
|
|
20
|
+
bounds: Rect,
|
|
21
|
+
): void {
|
|
22
|
+
const originalX = target.x
|
|
23
|
+
const originalY = target.y
|
|
24
|
+
const originalW = target.w
|
|
25
|
+
|
|
26
|
+
const intersectedX = Math.max(target.x, bounds.x)
|
|
27
|
+
const intersectedY = Math.max(target.y, bounds.y)
|
|
28
|
+
|
|
29
|
+
const intersectedMaxX = Math.min(
|
|
30
|
+
target.x + target.w,
|
|
31
|
+
bounds.x + bounds.w,
|
|
32
|
+
)
|
|
33
|
+
const intersectedMaxY = Math.min(
|
|
34
|
+
target.y + target.h,
|
|
35
|
+
bounds.y + bounds.h,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
// Intersection check
|
|
39
|
+
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
40
|
+
target.w = 0
|
|
41
|
+
target.h = 0
|
|
42
|
+
|
|
43
|
+
if ('data' in target && target.data) {
|
|
44
|
+
target.data = new Uint8Array(0)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const intersectedW = intersectedMaxX - intersectedX
|
|
51
|
+
const intersectedH = intersectedMaxY - intersectedY
|
|
52
|
+
const offsetX = intersectedX - originalX
|
|
53
|
+
const offsetY = intersectedY - originalY
|
|
54
|
+
|
|
55
|
+
target.x = intersectedX
|
|
56
|
+
target.y = intersectedY
|
|
57
|
+
target.w = intersectedW
|
|
58
|
+
target.h = intersectedH
|
|
59
|
+
|
|
60
|
+
if ('data' in target && target.data) {
|
|
61
|
+
const currentMaskBuffer = extractMaskBuffer(
|
|
62
|
+
target.data,
|
|
63
|
+
originalW,
|
|
64
|
+
offsetX,
|
|
65
|
+
offsetY,
|
|
66
|
+
intersectedW,
|
|
67
|
+
intersectedH,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
let minX = intersectedW
|
|
71
|
+
let maxX = -1
|
|
72
|
+
let minY = intersectedH
|
|
73
|
+
let maxY = -1
|
|
74
|
+
|
|
75
|
+
// Scan for content
|
|
76
|
+
for (let y = 0; y < intersectedH; y++) {
|
|
77
|
+
for (let x = 0; x < intersectedW; x++) {
|
|
78
|
+
if (currentMaskBuffer[y * intersectedW + x] !== 0) {
|
|
79
|
+
if (x < minX) minX = x
|
|
80
|
+
if (x > maxX) maxX = x
|
|
81
|
+
if (y < minY) minY = y
|
|
82
|
+
if (y > maxY) maxY = y
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// If no content is found (all zeros)
|
|
88
|
+
if (maxX === -1) {
|
|
89
|
+
target.w = 0
|
|
90
|
+
target.h = 0
|
|
91
|
+
target.data = new Uint8Array(0)
|
|
92
|
+
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const finalW = maxX - minX + 1
|
|
97
|
+
const finalH = maxY - minY + 1
|
|
98
|
+
|
|
99
|
+
// Only shift and crop if the content is smaller than the intersection
|
|
100
|
+
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
101
|
+
const newMaskBuffer = extractMaskBuffer(
|
|
102
|
+
currentMaskBuffer,
|
|
103
|
+
intersectedW,
|
|
104
|
+
minX,
|
|
105
|
+
minY,
|
|
106
|
+
finalW,
|
|
107
|
+
finalH,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
target.x += minX
|
|
111
|
+
target.y += minY
|
|
112
|
+
target.w = finalW
|
|
113
|
+
target.h = finalH
|
|
114
|
+
target.data = newMaskBuffer
|
|
115
|
+
} else {
|
|
116
|
+
target.w = finalW
|
|
117
|
+
target.h = finalH
|
|
118
|
+
target.data = currentMaskBuffer
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -1,121 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
export function trimRectBounds<T extends NullableMaskRect>(
|
|
19
|
-
target: T,
|
|
20
|
-
bounds: Rect,
|
|
21
|
-
): void {
|
|
22
|
-
const originalX = target.x
|
|
23
|
-
const originalY = target.y
|
|
24
|
-
const originalW = target.w
|
|
25
|
-
|
|
26
|
-
const intersectedX = Math.max(target.x, bounds.x)
|
|
27
|
-
const intersectedY = Math.max(target.y, bounds.y)
|
|
28
|
-
|
|
29
|
-
const intersectedMaxX = Math.min(
|
|
30
|
-
target.x + target.w,
|
|
31
|
-
bounds.x + bounds.w,
|
|
32
|
-
)
|
|
33
|
-
const intersectedMaxY = Math.min(
|
|
34
|
-
target.y + target.h,
|
|
35
|
-
bounds.y + bounds.h,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
// Intersection check
|
|
39
|
-
if (intersectedMaxX <= intersectedX || intersectedMaxY <= intersectedY) {
|
|
40
|
-
target.w = 0
|
|
41
|
-
target.h = 0
|
|
42
|
-
|
|
43
|
-
if ('data' in target && target.data) {
|
|
44
|
-
target.data = new Uint8Array(0)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return
|
|
1
|
+
import { type Rect } from '../_types'
|
|
2
|
+
|
|
3
|
+
export function trimRectBounds(
|
|
4
|
+
x: number,
|
|
5
|
+
y: number,
|
|
6
|
+
w: number,
|
|
7
|
+
h: number,
|
|
8
|
+
targetWidth: number,
|
|
9
|
+
targetHeight: number,
|
|
10
|
+
out?: Rect,
|
|
11
|
+
): Rect {
|
|
12
|
+
const res = out ?? {
|
|
13
|
+
x: 0,
|
|
14
|
+
y: 0,
|
|
15
|
+
w: 0,
|
|
16
|
+
h: 0,
|
|
48
17
|
}
|
|
49
18
|
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
target.x = intersectedX
|
|
56
|
-
target.y = intersectedY
|
|
57
|
-
target.w = intersectedW
|
|
58
|
-
target.h = intersectedH
|
|
19
|
+
const left = Math.max(0, x)
|
|
20
|
+
const top = Math.max(0, y)
|
|
21
|
+
const right = Math.min(targetWidth, x + w)
|
|
22
|
+
const bottom = Math.min(targetHeight, y + h)
|
|
59
23
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
offsetX,
|
|
65
|
-
offsetY,
|
|
66
|
-
intersectedW,
|
|
67
|
-
intersectedH,
|
|
68
|
-
)
|
|
24
|
+
res.x = left
|
|
25
|
+
res.y = top
|
|
26
|
+
res.w = Math.max(0, right - left)
|
|
27
|
+
res.h = Math.max(0, bottom - top)
|
|
69
28
|
|
|
70
|
-
|
|
71
|
-
let maxX = -1
|
|
72
|
-
let minY = intersectedH
|
|
73
|
-
let maxY = -1
|
|
74
|
-
|
|
75
|
-
// Scan for content
|
|
76
|
-
for (let y = 0; y < intersectedH; y++) {
|
|
77
|
-
for (let x = 0; x < intersectedW; x++) {
|
|
78
|
-
if (currentMaskBuffer[y * intersectedW + x] !== 0) {
|
|
79
|
-
if (x < minX) minX = x
|
|
80
|
-
if (x > maxX) maxX = x
|
|
81
|
-
if (y < minY) minY = y
|
|
82
|
-
if (y > maxY) maxY = y
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// If no content is found (all zeros)
|
|
88
|
-
if (maxX === -1) {
|
|
89
|
-
target.w = 0
|
|
90
|
-
target.h = 0
|
|
91
|
-
target.data = new Uint8Array(0)
|
|
92
|
-
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const finalW = maxX - minX + 1
|
|
97
|
-
const finalH = maxY - minY + 1
|
|
98
|
-
|
|
99
|
-
// Only shift and crop if the content is smaller than the intersection
|
|
100
|
-
if (finalW !== intersectedW || finalH !== intersectedH) {
|
|
101
|
-
const newMaskBuffer = extractMaskBuffer(
|
|
102
|
-
currentMaskBuffer,
|
|
103
|
-
intersectedW,
|
|
104
|
-
minX,
|
|
105
|
-
minY,
|
|
106
|
-
finalW,
|
|
107
|
-
finalH,
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
target.x += minX
|
|
111
|
-
target.y += minY
|
|
112
|
-
target.w = finalW
|
|
113
|
-
target.h = finalH
|
|
114
|
-
target.data = newMaskBuffer
|
|
115
|
-
} else {
|
|
116
|
-
target.w = finalW
|
|
117
|
-
target.h = finalH
|
|
118
|
-
target.data = currentMaskBuffer
|
|
119
|
-
}
|
|
120
|
-
}
|
|
29
|
+
return res
|
|
121
30
|
}
|
package/src/_types.ts
CHANGED
|
@@ -80,19 +80,18 @@ export interface AlphaMask extends Mask {
|
|
|
80
80
|
readonly type: MaskType.ALPHA
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
interface
|
|
84
|
-
readonly
|
|
85
|
-
readonly
|
|
86
|
-
readonly minOffset: number
|
|
83
|
+
interface BasePaintMask {
|
|
84
|
+
readonly centerOffsetX: number
|
|
85
|
+
readonly centerOffsetY: number
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
export interface
|
|
88
|
+
export interface PaintAlphaMask extends BasePaintMask, AlphaMask {
|
|
90
89
|
}
|
|
91
90
|
|
|
92
|
-
export interface
|
|
91
|
+
export interface PaintBinaryMask extends BasePaintMask, BinaryMask {
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
export type
|
|
94
|
+
export type PaintMask = PaintAlphaMask | PaintBinaryMask
|
|
96
95
|
|
|
97
96
|
/**
|
|
98
97
|
* Configuration for pixel manipulation operations.
|
|
@@ -192,7 +191,6 @@ export interface BasePixelBlendOptions {
|
|
|
192
191
|
}
|
|
193
192
|
|
|
194
193
|
export interface PixelBlendOptions extends PixelRect, Alpha, BasePixelBlendOptions {
|
|
195
|
-
|
|
196
194
|
}
|
|
197
195
|
|
|
198
196
|
export interface PixelBlendMaskOptions extends PixelRect, Alpha, MaskOffset, InvertMask, BasePixelBlendOptions {
|
|
@@ -212,15 +210,14 @@ export interface ColorBlendOptions extends PixelRect, Alpha {
|
|
|
212
210
|
export interface ColorBlendMaskOptions extends ColorBlendOptions, MaskOffset, InvertMask {
|
|
213
211
|
}
|
|
214
212
|
|
|
215
|
-
export type
|
|
216
|
-
type:
|
|
213
|
+
export type MaskRect<T extends MaskType> = Rect & {
|
|
214
|
+
type: T
|
|
217
215
|
data: Uint8Array
|
|
218
216
|
}
|
|
219
217
|
|
|
220
|
-
export type
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
218
|
+
export type BinaryMaskRect = MaskRect<MaskType.BINARY>
|
|
219
|
+
|
|
220
|
+
export type AlphaMaskRect = MaskRect<MaskType.ALPHA>
|
|
224
221
|
|
|
225
222
|
export type NullableBinaryMaskRect = Rect & ({
|
|
226
223
|
type: MaskType.BINARY
|
|
@@ -240,8 +237,12 @@ export type NullableMaskRect = Rect & ({
|
|
|
240
237
|
|
|
241
238
|
export type HistoryMutator<T extends {}, D extends {}> = (writer: PixelWriter<any>, deps?: Partial<D>) => T
|
|
242
239
|
|
|
243
|
-
export interface
|
|
240
|
+
export interface IPixelData32 {
|
|
244
241
|
readonly data32: Uint32Array
|
|
245
242
|
readonly width: number
|
|
246
243
|
readonly height: number
|
|
247
244
|
}
|
|
245
|
+
|
|
246
|
+
export interface IPixelData<T extends ImageDataLike = ImageData> extends IPixelData32 {
|
|
247
|
+
readonly imageData: T
|
|
248
|
+
}
|