pixel-data-js 0.32.0 → 0.34.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pixel-data-js",
3
3
  "type": "module",
4
- "version": "0.32.0",
4
+ "version": "0.34.0",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "description": "JS Pixel and ImageData operations",
7
7
  "author": {
@@ -1,7 +1,9 @@
1
1
  import type { ImageDataLike } from './_ImageData-types'
2
2
 
3
- export function copyImageData({ data, width, height }: ImageDataLike): ImageData {
4
- return new ImageData(data.slice(), width, height)
3
+ export function copyImageData(source: ImageDataLike): ImageData {
4
+ const dataCopy = new Uint8ClampedArray(source.data)
5
+
6
+ return new ImageData(dataCopy, source.width, source.height)
5
7
  }
6
8
 
7
9
  export function copyImageDataLike({ data, width, height }: ImageDataLike): ImageDataLike {
@@ -42,8 +42,7 @@ export function extractImageData(
42
42
  ? _x
43
43
  : { x: _x, y: _y!, w: _w!, h: _h! }
44
44
 
45
- if (w <= 0) return null
46
- if (h <= 0) return null
45
+ if (w <= 0 || h <= 0) return null
47
46
 
48
47
  const result = new ImageData(w, h)
49
48
 
@@ -40,8 +40,7 @@ export function extractImageDataBuffer(
40
40
  const { x, y, w, h } = typeof _x === 'object'
41
41
  ? _x
42
42
  : { x: _x, y: _y!, w: _w!, h: _h! }
43
- if (w <= 0) return new Uint8ClampedArray(0)
44
- if (h <= 0) return new Uint8ClampedArray(0)
43
+ if (w <= 0 || h <= 0) return new Uint8ClampedArray(0)
45
44
 
46
45
  const srcW = imageData.width
47
46
  const srcH = imageData.height
@@ -72,8 +71,7 @@ export function extractImageDataBuffer(
72
71
  copyW = Math.min(copyW, srcW - srcX)
73
72
  copyH = Math.min(copyH, srcH - srcY)
74
73
 
75
- if (copyW <= 0) return out
76
- if (copyH <= 0) return out
74
+ if (copyW <= 0 || copyH <= 0) return out
77
75
 
78
76
  // 2. Perform high-speed block copy
79
77
  // Attempt to use a 32-bit view if the buffer is memory-aligned.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Writes image data from a source to a target with support for clipping and alpha masking.
2
+ * Writes image data from a source to a target.
3
3
  *
4
4
  * @param target - The destination ImageData to write to.
5
5
  * @param source - The source ImageData to read from.
@@ -9,8 +9,8 @@
9
9
  export function writeImageData(
10
10
  target: ImageData,
11
11
  source: ImageData,
12
- x: number,
13
- y: number,
12
+ x = 0,
13
+ y = 0,
14
14
  ): void {
15
15
  const dstW = target.width
16
16
  const dstH = target.height
@@ -42,8 +42,7 @@ export function writeImageData(
42
42
  copyW = Math.min(copyW, dstW - dstX)
43
43
  copyH = Math.min(copyH, dstH - dstY)
44
44
 
45
- if (copyW <= 0) return
46
- if (copyH <= 0) return
45
+ if (copyW <= 0 || copyH <= 0) return
47
46
 
48
47
  const isDstAligned = dst.byteOffset % 4 === 0
49
48
  const isSrcAligned = src.byteOffset % 4 === 0
@@ -57,8 +57,7 @@ export function writeImageDataBuffer(
57
57
  h = _h!
58
58
  }
59
59
 
60
- if (w <= 0) return
61
- if (h <= 0) return
60
+ if (w <= 0 || h <= 0) return
62
61
 
63
62
  const dstW = target.width
64
63
  const dstH = target.height
@@ -87,8 +86,7 @@ export function writeImageDataBuffer(
87
86
  copyW = Math.min(copyW, dstW - dstX)
88
87
  copyH = Math.min(copyH, dstH - dstY)
89
88
 
90
- if (copyW <= 0) return
91
- if (copyH <= 0) return
89
+ if (copyW <= 0 || copyH <= 0) return
92
90
 
93
91
  // Fast-path: Both arrays must be 4-byte aligned to use Uint32Array safely
94
92
  const isDstAligned = dst.byteOffset % 4 === 0
@@ -1,11 +1,10 @@
1
1
  import { forEachLinePoint } from '../Algorithm/forEachLinePoint'
2
2
  import type { PixelEngineConfig } from '../History/PixelEngineConfig'
3
- import { _macro_paintRectCenterOffset } from '../Internal/macros'
4
3
  import type { Rect } from '../Rect/_rect-types'
5
4
  import { trimRectBounds } from '../Rect/trimRectBounds'
6
5
  import type { AlphaMaskTile } from '../Tile/_tile-types'
7
6
  import type { TilePool } from '../Tile/TilePool'
8
- import type { PaintAlphaMask, PaintBinaryMask } from './_paint-types'
7
+ import type { PaintAlphaMask, PaintBinaryMask, PaintRect } from './_paint-types'
9
8
  import { eachTileInBounds } from './eachTileInBounds'
10
9
 
11
10
  export class AlphaMaskPaintBuffer {
@@ -187,15 +186,13 @@ export class AlphaMaskPaintBuffer {
187
186
 
188
187
  paintRect(
189
188
  alpha: number,
190
- brushWidth: number,
191
- brushHeight: number,
189
+ brush: PaintRect,
192
190
  x: number,
193
191
  y: number,
194
192
  ): boolean
195
193
  paintRect(
196
194
  alpha: number,
197
- brushWidth: number,
198
- brushHeight: number,
195
+ brush: PaintRect,
199
196
  startX: number,
200
197
  startY: number,
201
198
  endX: number,
@@ -203,8 +200,7 @@ export class AlphaMaskPaintBuffer {
203
200
  ): boolean
204
201
  paintRect(
205
202
  alpha: number,
206
- brushWidth: number,
207
- brushHeight: number,
203
+ brush: PaintRect,
208
204
  x0: number,
209
205
  y0: number,
210
206
  x1: number = x0,
@@ -218,8 +214,10 @@ export class AlphaMaskPaintBuffer {
218
214
  const tileMask = config.tileMask
219
215
  const target = config.target
220
216
 
221
- const centerOffsetX = _macro_paintRectCenterOffset(brushWidth)
222
- const centerOffsetY = _macro_paintRectCenterOffset(brushHeight)
217
+ const brushWidth = brush.w
218
+ const brushHeight = brush.h
219
+ const centerOffsetX = brush.centerOffsetX
220
+ const centerOffsetY = brush.centerOffsetY
223
221
 
224
222
  const trimRectBoundsFn = this.trimRectBoundsFn
225
223
  const eachTileInBoundsFn = this.eachTileInBoundsFn
@@ -1,11 +1,10 @@
1
1
  import { forEachLinePoint } from '../Algorithm/forEachLinePoint'
2
2
  import type { PixelEngineConfig } from '../History/PixelEngineConfig'
3
- import { _macro_paintRectCenterOffset } from '../Internal/macros'
4
3
  import type { Rect } from '../Rect/_rect-types'
5
4
  import { trimRectBounds } from '../Rect/trimRectBounds'
6
5
  import type { BinaryMaskTile } from '../Tile/_tile-types'
7
6
  import type { TilePool } from '../Tile/TilePool'
8
- import type { PaintBinaryMask } from './_paint-types'
7
+ import type { PaintBinaryMask, PaintRect } from './_paint-types'
9
8
  import { eachTileInBounds } from './eachTileInBounds'
10
9
 
11
10
  export class BinaryMaskPaintBuffer {
@@ -104,22 +103,19 @@ export class BinaryMaskPaintBuffer {
104
103
  }
105
104
 
106
105
  paintRect(
107
- brushWidth: number,
108
- brushHeight: number,
106
+ brush: PaintRect,
109
107
  x: number,
110
108
  y: number,
111
109
  ): boolean
112
110
  paintRect(
113
- brushWidth: number,
114
- brushHeight: number,
111
+ brush: PaintRect,
115
112
  startX: number,
116
113
  startY: number,
117
114
  endX: number,
118
115
  endY: number,
119
116
  ): boolean
120
117
  paintRect(
121
- brushWidth: number,
122
- brushHeight: number,
118
+ brush: PaintRect,
123
119
  x0: number,
124
120
  y0: number,
125
121
  x1: number = x0,
@@ -133,8 +129,10 @@ export class BinaryMaskPaintBuffer {
133
129
  const tileMask = config.tileMask
134
130
  const target = config.target
135
131
 
136
- const centerOffsetX = _macro_paintRectCenterOffset(brushWidth)
137
- const centerOffsetY = _macro_paintRectCenterOffset(brushHeight)
132
+ const brushWidth = brush.w
133
+ const brushHeight = brush.h
134
+ const centerOffsetX = brush.centerOffsetX
135
+ const centerOffsetY = brush.centerOffsetY
138
136
 
139
137
  const trimRectBoundsFn = this.trimRectBoundsFn
140
138
  const eachTileInBoundsFn = this.eachTileInBoundsFn
@@ -1,12 +1,11 @@
1
1
  import type { Color32 } from '../_types'
2
2
  import { forEachLinePoint } from '../Algorithm/forEachLinePoint'
3
3
  import type { PixelEngineConfig } from '../History/PixelEngineConfig'
4
- import { _macro_paintRectCenterOffset } from '../Internal/macros'
5
4
  import type { Rect } from '../Rect/_rect-types'
6
5
  import { trimRectBounds } from '../Rect/trimRectBounds'
7
6
  import type { PixelTile } from '../Tile/_tile-types'
8
7
  import type { TilePool } from '../Tile/TilePool'
9
- import type { PaintAlphaMask, PaintBinaryMask } from './_paint-types'
8
+ import type { PaintAlphaMask, PaintBinaryMask, PaintRect } from './_paint-types'
10
9
  import { eachTileInBounds } from './eachTileInBounds'
11
10
 
12
11
  export class ColorPaintBuffer {
@@ -191,15 +190,13 @@ export class ColorPaintBuffer {
191
190
 
192
191
  paintRect(
193
192
  color: Color32,
194
- brushWidth: number,
195
- brushHeight: number,
193
+ brush: PaintRect,
196
194
  x: number,
197
195
  y: number,
198
196
  ): boolean
199
197
  paintRect(
200
198
  color: Color32,
201
- brushWidth: number,
202
- brushHeight: number,
199
+ brush: PaintRect,
203
200
  startX: number,
204
201
  startY: number,
205
202
  endX: number,
@@ -207,8 +204,7 @@ export class ColorPaintBuffer {
207
204
  ): boolean
208
205
  paintRect(
209
206
  color: Color32,
210
- brushWidth: number,
211
- brushHeight: number,
207
+ brush: PaintRect,
212
208
  x0: number,
213
209
  y0: number,
214
210
  x1: number = x0,
@@ -225,8 +221,10 @@ export class ColorPaintBuffer {
225
221
  const tileMask = config.tileMask
226
222
  const target = config.target
227
223
 
228
- const centerOffsetX = _macro_paintRectCenterOffset(brushWidth)
229
- const centerOffsetY = _macro_paintRectCenterOffset(brushHeight)
224
+ const brushWidth = brush.w
225
+ const brushHeight = brush.h
226
+ const centerOffsetX = brush.centerOffsetX
227
+ const centerOffsetY = brush.centerOffsetY
230
228
 
231
229
  let changed = false
232
230
 
@@ -0,0 +1,11 @@
1
+ import { _macro_paintRectCenterOffset } from '../Internal/macros'
2
+ import type { PaintRect } from './_paint-types'
3
+
4
+ export function makePaintRect(w: number, h: number): PaintRect {
5
+ return {
6
+ w,
7
+ h,
8
+ centerOffsetX: _macro_paintRectCenterOffset(w),
9
+ centerOffsetY: _macro_paintRectCenterOffset(h),
10
+ }
11
+ }
@@ -20,3 +20,9 @@ export interface PaintBinaryMask<T extends PaintMaskOutline = PaintMaskOutline>
20
20
 
21
21
  export type PaintMask = PaintAlphaMask<any> | PaintBinaryMask<any>
22
22
 
23
+ export interface PaintRect {
24
+ w: number,
25
+ h: number,
26
+ centerOffsetX: number,
27
+ centerOffsetY: number,
28
+ }
@@ -44,8 +44,7 @@ export function extractPixelDataBuffer(
44
44
  const srcH = source.h
45
45
  const srcData = source.data
46
46
 
47
- if (w <= 0) return new Uint32Array(0)
48
- if (h <= 0) return new Uint32Array(0)
47
+ if (w <= 0 || h <= 0) return new Uint32Array(0)
49
48
 
50
49
  const dstData = new Uint32Array(w * h)
51
50
 
@@ -72,8 +71,7 @@ export function extractPixelDataBuffer(
72
71
  copyW = Math.min(copyW, srcW - srcX)
73
72
  copyH = Math.min(copyH, srcH - srcY)
74
73
 
75
- if (copyW <= 0) return dstData
76
- if (copyH <= 0) return dstData
74
+ if (copyW <= 0 || copyH <= 0) return dstData
77
75
 
78
76
  for (let row = 0; row < copyH; row++) {
79
77
  const srcStart = (srcY + row) * srcW + srcX
@@ -83,8 +83,7 @@ export function fillPixelData(
83
83
  fillW = Math.min(fillW, dstW - dstX)
84
84
  fillH = Math.min(fillH, dstH - dstY)
85
85
 
86
- if (fillW <= 0) return false
87
- if (fillH <= 0) return false
86
+ if (fillW <= 0 || fillH <= 0) return false
88
87
 
89
88
  const dst32 = dst.data
90
89
  let hasChanged = false
@@ -85,8 +85,7 @@ export function fillPixelDataFast(
85
85
  fillW = Math.min(fillW, dstW - dstX)
86
86
  fillH = Math.min(fillH, dstH - dstY)
87
87
 
88
- if (fillW <= 0) return
89
- if (fillH <= 0) return
88
+ if (fillW <= 0 || fillH <= 0) return
90
89
 
91
90
  const dst32 = dst.data
92
91
  const dw = dst.w
@@ -0,0 +1,55 @@
1
+ import type { PixelData32 } from './_pixelData-types'
2
+
3
+ /**
4
+ * Writes PixelData from a source to a target.
5
+ * @param target - The destination to write to.
6
+ * @param source - The source to read from.
7
+ * @param x - The x-coordinate in the target where drawing starts.
8
+ * @param y - The y-coordinate in the target where drawing starts.
9
+ */
10
+ export function writePixelData(
11
+ target: PixelData32,
12
+ source: PixelData32,
13
+ x = 0,
14
+ y = 0,
15
+ ): void {
16
+ const dstW = target.w
17
+ const dstH = target.h
18
+ const dst = target.data
19
+
20
+ const srcW = source.w
21
+ const srcH = source.h
22
+ const src = source.data
23
+
24
+ let dstX = x
25
+ let dstY = y
26
+ let srcX = 0
27
+ let srcY = 0
28
+ let copyW = srcW
29
+ let copyH = srcH
30
+
31
+ if (dstX < 0) {
32
+ srcX = -dstX
33
+ copyW += dstX
34
+ dstX = 0
35
+ }
36
+
37
+ if (dstY < 0) {
38
+ srcY = -dstY
39
+ copyH += dstY
40
+ dstY = 0
41
+ }
42
+
43
+ copyW = Math.min(copyW, dstW - dstX)
44
+ copyH = Math.min(copyH, dstH - dstY)
45
+
46
+ if (copyW <= 0 || copyH <= 0) return
47
+
48
+ for (let row = 0; row < copyH; row++) {
49
+ const dstStart = (dstY + row) * dstW + dstX
50
+ const srcStart = (srcY + row) * srcW + srcX
51
+ const chunk = src.subarray(srcStart, srcStart + copyW)
52
+
53
+ dst.set(chunk, dstStart)
54
+ }
55
+ }
package/src/index.ts CHANGED
@@ -126,6 +126,7 @@ export * from './Paint/eachTileInBounds'
126
126
  export * from './Paint/makeCirclePaintMask'
127
127
  export * from './Paint/makePaintMask'
128
128
  export * from './Paint/makeRectFalloffPaintAlphaMask'
129
+ export * from './Paint/PaintRect'
129
130
 
130
131
  export * from './Paint/Render/AlphaMaskPaintBufferCanvasRenderer'
131
132
  export * from './Paint/Render/BinaryMaskPaintBufferCanvasRenderer'
@@ -166,6 +167,7 @@ export * from './PixelData/ReusablePixelData'
166
167
  export * from './PixelData/rotatePixelData'
167
168
  export * from './PixelData/uInt32ArrayToPixelData'
168
169
  export * from './PixelData/writePaintBufferToPixelData'
170
+ export * from './PixelData/writePixelData'
169
171
  export * from './PixelData/writePixelDataBuffer'
170
172
 
171
173
  export * from './Rect/_rect-types'