@flighthq/image 0.3.0 → 0.3.1-next.209.43ef1bc
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/imageResourceFrom.d.ts.map +1 -1
- package/dist/imageResourceFrom.js +20 -1
- package/dist/imageResourceFrom.js.map +1 -1
- package/dist/imageResourceReference.d.ts +3 -3
- package/dist/imageResourceReference.d.ts.map +1 -1
- package/dist/imageResourceReference.js +34 -8
- package/dist/imageResourceReference.js.map +1 -1
- package/package.json +4 -4
- package/src/imageResourceFrom.test.ts +20 -0
- package/src/imageResourceReference.test.ts +37 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageResourceFrom.d.ts","sourceRoot":"","sources":["../src/imageResourceFrom.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAO9D,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK,CAQ7E;
|
|
1
|
+
{"version":3,"file":"imageResourceFrom.d.ts","sourceRoot":"","sources":["../src/imageResourceFrom.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAO9D,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK,CAQ7E;AAsBD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,iBAAiB,GAAG,KAAK,CAU9E;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAU7E;AAED,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,gBAAgB,GAAG,KAAK,CAUhF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,KAAK,CAAC,CAEhB;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAOhG;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,KAAK,CAAC,CAOhB;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,WAAW,GAAG,iBAAiB,EAC7C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,KAAK,CAAC,CA0BhB"}
|
|
@@ -10,10 +10,29 @@ export function createImageResourceFromBitmap(bitmap) {
|
|
|
10
10
|
canvas.width = bitmap.width;
|
|
11
11
|
canvas.height = bitmap.height;
|
|
12
12
|
const domImageData = new globalThis.ImageData(bitmap.width, bitmap.height);
|
|
13
|
-
domImageData.data.set(bitmap.data);
|
|
13
|
+
domImageData.data.set(bitmap.alphaType === 'premultiplied' ? unpremultiplyRgba8(bitmap.data) : bitmap.data);
|
|
14
14
|
canvas.getContext('2d').putImageData(domImageData, 0, 0);
|
|
15
15
|
return createImageResourceFromCanvas(canvas);
|
|
16
16
|
}
|
|
17
|
+
// ImageData is straight-alpha by contract. Preserve a Bitmap's declared representation at its own seam,
|
|
18
|
+
// then normalize only the scratch browser copy used to materialize a CanvasImageSource for Canvas/DOM.
|
|
19
|
+
function unpremultiplyRgba8(source) {
|
|
20
|
+
const data = new Uint8ClampedArray(source);
|
|
21
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
22
|
+
const alpha = data[i + 3];
|
|
23
|
+
if (alpha === 0) {
|
|
24
|
+
data[i] = 0;
|
|
25
|
+
data[i + 1] = 0;
|
|
26
|
+
data[i + 2] = 0;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const scale = 255 / alpha;
|
|
30
|
+
data[i] = Math.min(255, Math.round(data[i] * scale));
|
|
31
|
+
data[i + 1] = Math.min(255, Math.round(data[i + 1] * scale));
|
|
32
|
+
data[i + 2] = Math.min(255, Math.round(data[i + 2] * scale));
|
|
33
|
+
}
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
17
36
|
export function createImageResourceFromCanvas(canvas) {
|
|
18
37
|
return createEntity({
|
|
19
38
|
alphaType: DECODED_ALPHA_TYPE,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageResourceFrom.js","sourceRoot":"","sources":["../src/imageResourceFrom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,wFAAwF;AACxF,sGAAsG;AACtG,oGAAoG;AACpG,+FAA+F;AAC/F,MAAM,UAAU,6BAA6B,CAAC,MAAwB;IACpE,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3E,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"imageResourceFrom.js","sourceRoot":"","sources":["../src/imageResourceFrom.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { EmbeddedImageResourceReference, ExternalImageResourceReference,
|
|
2
|
-
export declare function createEmbeddedImageResourceReference(bytes: Uint8Array, mimeType?: string | null): EmbeddedImageResourceReference;
|
|
1
|
+
import type { AlphaType, EmbeddedImageResourceReference, ExternalImageResourceReference, ImageResourceFailure, ImageResourceFetch, ImageResourceReference, ImageResourceReferenceResolutionExplanation, TextureSource } from '@flighthq/types/contract';
|
|
2
|
+
export declare function createEmbeddedImageResourceReference(bytes: Uint8Array, mimeType?: string | null, alphaType?: AlphaType): EmbeddedImageResourceReference;
|
|
3
3
|
export declare function createExternalImageResourceReference(uri: string, basePath?: string | null): ExternalImageResourceReference;
|
|
4
4
|
export declare function createImageResourceFailure(cause: unknown): ImageResourceFailure;
|
|
5
5
|
export declare function explainImageResourceReferenceResolution(ref: Readonly<ImageResourceReference>): ImageResourceReferenceResolutionExplanation;
|
|
6
6
|
export declare function resetFailedImageResourceReference(ref: ImageResourceReference): boolean;
|
|
7
|
-
export declare function resolveImageResourceReference(ref: ImageResourceReference, fetch: ImageResourceFetch, signal: AbortSignal): Promise<
|
|
7
|
+
export declare function resolveImageResourceReference(ref: ImageResourceReference, fetch: ImageResourceFetch, signal: AbortSignal): Promise<TextureSource | null>;
|
|
8
8
|
//# sourceMappingURL=imageResourceReference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageResourceReference.d.ts","sourceRoot":"","sources":["../src/imageResourceReference.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"imageResourceReference.d.ts","sourceRoot":"","sources":["../src/imageResourceReference.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EAET,8BAA8B,EAE9B,8BAA8B,EAC9B,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,2CAA2C,EAC3C,aAAa,EACd,MAAM,0BAA0B,CAAC;AAWlC,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,MAAM,GAAG,IAAW,EAC9B,SAAS,GAAE,SAAsB,GAChC,8BAA8B,CAUhC;AA6BD,wBAAgB,oCAAoC,CAClD,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,8BAA8B,CAUhC;AAID,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAK/E;AAID,wBAAgB,uCAAuC,CACrD,GAAG,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GACpC,2CAA2C,CAO7C;AAID,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAKtF;AAUD,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,sBAAsB,EAC3B,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAwB/B"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createEntity } from '@flighthq/entity/contract';
|
|
2
|
+
import { decodeImage, decodeImagePremultiplied } from '@flighthq/image-codec/contract';
|
|
3
|
+
import { BitmapTextureSourceKind, ImageResourceFailureKind, ImageResourceReferenceKind, ResourceResolutionState, } from '@flighthq/types/contract';
|
|
3
4
|
// `bytes` is retained as the view the container handed over, not a copy: a parser carves an image payload
|
|
4
5
|
// out of its source and the reference borrows it, so a document that never resolves an image never pays for
|
|
5
6
|
// its pixels. `textures` starts empty and each waiting Texture subscribes itself.
|
|
6
|
-
export function createEmbeddedImageResourceReference(bytes, mimeType = null) {
|
|
7
|
+
export function createEmbeddedImageResourceReference(bytes, mimeType = null, alphaType = 'straight') {
|
|
7
8
|
return {
|
|
9
|
+
alphaType,
|
|
8
10
|
bytes,
|
|
9
11
|
failure: null,
|
|
10
12
|
kind: ImageResourceReferenceKind.Embedded,
|
|
@@ -13,6 +15,30 @@ export function createEmbeddedImageResourceReference(bytes, mimeType = null) {
|
|
|
13
15
|
textures: [],
|
|
14
16
|
};
|
|
15
17
|
}
|
|
18
|
+
// The one encoded-byte producer for image resource references. A registered decoder owns format
|
|
19
|
+
// knowledge; this async resource layer turns its RGBA result into the live Bitmap entity renderers
|
|
20
|
+
// dispatch by kind. The reference's alpha request is carried onto the source verbatim, so bytes that
|
|
21
|
+
// are already premultiplied never get multiplied a second time at renderer upload.
|
|
22
|
+
async function decodeEmbeddedImageResourceReference(ref, signal) {
|
|
23
|
+
signal.throwIfAborted();
|
|
24
|
+
const decoded = await (ref.alphaType === 'premultiplied'
|
|
25
|
+
? decodeImagePremultiplied(ref.bytes, ref.mimeType ?? undefined)
|
|
26
|
+
: decodeImage(ref.bytes, ref.mimeType ?? undefined));
|
|
27
|
+
signal.throwIfAborted();
|
|
28
|
+
if (decoded === null)
|
|
29
|
+
return null;
|
|
30
|
+
const bitmap = {
|
|
31
|
+
alphaType: ref.alphaType,
|
|
32
|
+
data: new Uint8ClampedArray(decoded.data),
|
|
33
|
+
format: 'rgba8unorm',
|
|
34
|
+
gamut: 'srgb',
|
|
35
|
+
height: decoded.height,
|
|
36
|
+
kind: BitmapTextureSourceKind,
|
|
37
|
+
version: 0,
|
|
38
|
+
width: decoded.width,
|
|
39
|
+
};
|
|
40
|
+
return createEntity(bitmap);
|
|
41
|
+
}
|
|
16
42
|
export function createExternalImageResourceReference(uri, basePath = null) {
|
|
17
43
|
return {
|
|
18
44
|
basePath,
|
|
@@ -51,7 +77,7 @@ export function resetFailedImageResourceReference(ref) {
|
|
|
51
77
|
ref.state = ResourceResolutionState.Unresolved;
|
|
52
78
|
return true;
|
|
53
79
|
}
|
|
54
|
-
// Advances one reference through its lifecycle and returns the decoded
|
|
80
|
+
// Advances one reference through its lifecycle and returns the decoded texture source, or null for an expected
|
|
55
81
|
// failure. Embedded bytes decode through @flighthq/image-codec; an External uri goes through the caller's
|
|
56
82
|
// fetch seam. An abort is a cancel rather than a failure, so the reference reverts to Unresolved and the
|
|
57
83
|
// rejection propagates — a caller racing several loads against one signal sees one cancellation, not a
|
|
@@ -63,16 +89,16 @@ export async function resolveImageResourceReference(ref, fetch, signal) {
|
|
|
63
89
|
ref.failure = null;
|
|
64
90
|
ref.state = ResourceResolutionState.Loading;
|
|
65
91
|
try {
|
|
66
|
-
const
|
|
67
|
-
? await
|
|
92
|
+
const source = ref.kind === ImageResourceReferenceKind.Embedded
|
|
93
|
+
? await decodeEmbeddedImageResourceReference(ref, signal)
|
|
68
94
|
: await fetch(ref, signal);
|
|
69
|
-
if (
|
|
95
|
+
if (source === null) {
|
|
70
96
|
ref.failure = { kind: ImageResourceFailureKind.Unavailable, message: 'Image resource unavailable', name: null };
|
|
71
97
|
ref.state = ResourceResolutionState.Failed;
|
|
72
98
|
return null;
|
|
73
99
|
}
|
|
74
100
|
ref.state = ResourceResolutionState.Resolved;
|
|
75
|
-
return
|
|
101
|
+
return source;
|
|
76
102
|
}
|
|
77
103
|
catch (cause) {
|
|
78
104
|
if (signal.aborted) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageResourceReference.js","sourceRoot":"","sources":["../src/imageResourceReference.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"imageResourceReference.js","sourceRoot":"","sources":["../src/imageResourceReference.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/image",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.209.43ef1bc",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/entity": "0.3.
|
|
42
|
-
"@flighthq/image-codec": "0.3.
|
|
43
|
-
"@flighthq/types": "0.3.
|
|
41
|
+
"@flighthq/entity": "0.3.1-next.209.43ef1bc",
|
|
42
|
+
"@flighthq/image-codec": "0.3.1-next.209.43ef1bc",
|
|
43
|
+
"@flighthq/types": "0.3.1-next.209.43ef1bc"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"typescript": "^5.3.0"
|
|
@@ -44,6 +44,26 @@ describe('createImageResourceFromBitmap', () => {
|
|
|
44
44
|
expect(resource.height).toBe(4);
|
|
45
45
|
expect(resource.source).not.toBeNull();
|
|
46
46
|
});
|
|
47
|
+
|
|
48
|
+
it('normalizes premultiplied Bitmap pixels for the straight-alpha ImageData bridge', () => {
|
|
49
|
+
const bitmap: Bitmap = createEntity({
|
|
50
|
+
alphaType: 'premultiplied',
|
|
51
|
+
gamut: 'srgb',
|
|
52
|
+
data: new Uint8ClampedArray([0x40, 0x20, 0x10, 0x80]),
|
|
53
|
+
format: 'rgba8unorm',
|
|
54
|
+
height: 1,
|
|
55
|
+
kind: BitmapTextureSourceKind,
|
|
56
|
+
version: 0,
|
|
57
|
+
width: 1,
|
|
58
|
+
});
|
|
59
|
+
const putImageData = vi.spyOn(CanvasRenderingContext2D.prototype, 'putImageData');
|
|
60
|
+
|
|
61
|
+
createImageResourceFromBitmap(bitmap);
|
|
62
|
+
|
|
63
|
+
const imageData = putImageData.mock.calls[0][0];
|
|
64
|
+
expect([...imageData.data]).toEqual([0x80, 0x40, 0x20, 0x80]);
|
|
65
|
+
expect([...bitmap.data]).toEqual([0x40, 0x20, 0x10, 0x80]);
|
|
66
|
+
});
|
|
47
67
|
});
|
|
48
68
|
|
|
49
69
|
describe('createImageResourceFromCanvas', () => {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { clearImageDecoders, registerImageDecoder } from '@flighthq/image-codec/contract';
|
|
2
|
+
import type { Image, ImageDecoder } from '@flighthq/types/contract';
|
|
3
|
+
import {
|
|
4
|
+
BitmapTextureSourceKind,
|
|
5
|
+
EntityRuntimeKey,
|
|
6
|
+
ImageResourceFailureKind,
|
|
7
|
+
ResourceResolutionState,
|
|
8
|
+
} from '@flighthq/types/contract';
|
|
3
9
|
|
|
4
10
|
import {
|
|
5
11
|
createEmbeddedImageResourceReference,
|
|
@@ -10,14 +16,19 @@ import {
|
|
|
10
16
|
resolveImageResourceReference,
|
|
11
17
|
} from './imageResourceReference';
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
let decoder: ReturnType<typeof vi.fn<ImageDecoder>>;
|
|
20
|
+
|
|
14
21
|
beforeEach(() => {
|
|
15
|
-
|
|
22
|
+
decoder = vi.fn<ImageDecoder>().mockResolvedValue({
|
|
23
|
+
data: new Uint8ClampedArray([0x11, 0x22, 0x33, 0x44]),
|
|
24
|
+
height: 1,
|
|
25
|
+
width: 1,
|
|
26
|
+
});
|
|
27
|
+
registerImageDecoder('image/png', decoder);
|
|
16
28
|
});
|
|
17
29
|
|
|
18
30
|
afterEach(() => {
|
|
19
|
-
|
|
20
|
-
delete (HTMLImageElement.prototype as Partial<HTMLImageElement>).decode;
|
|
31
|
+
clearImageDecoders();
|
|
21
32
|
});
|
|
22
33
|
|
|
23
34
|
const unusedFetch = () => Promise.resolve(null);
|
|
@@ -28,6 +39,7 @@ describe('createEmbeddedImageResourceReference', () => {
|
|
|
28
39
|
const ref = createEmbeddedImageResourceReference(bytes, 'image/png');
|
|
29
40
|
expect(ref.bytes).toBe(bytes);
|
|
30
41
|
expect(ref.mimeType).toBe('image/png');
|
|
42
|
+
expect(ref.alphaType).toBe('straight');
|
|
31
43
|
});
|
|
32
44
|
|
|
33
45
|
it('starts unresolved with no failure and no subscribers', () => {
|
|
@@ -106,12 +118,29 @@ describe('resetFailedImageResourceReference', () => {
|
|
|
106
118
|
describe('resolveImageResourceReference', () => {
|
|
107
119
|
it('decodes embedded bytes and marks the reference resolved', async () => {
|
|
108
120
|
const ref = createEmbeddedImageResourceReference(new Uint8Array([0x89, 0x50, 0x4e, 0x47]), 'image/png');
|
|
109
|
-
const
|
|
110
|
-
expect(
|
|
121
|
+
const source = await resolveImageResourceReference(ref, unusedFetch, new AbortController().signal);
|
|
122
|
+
expect(source).toMatchObject({
|
|
123
|
+
alphaType: 'straight',
|
|
124
|
+
data: new Uint8ClampedArray([0x11, 0x22, 0x33, 0x44]),
|
|
125
|
+
height: 1,
|
|
126
|
+
kind: BitmapTextureSourceKind,
|
|
127
|
+
width: 1,
|
|
128
|
+
});
|
|
129
|
+
expect(EntityRuntimeKey in source!).toBe(true);
|
|
130
|
+
expect(decoder).toHaveBeenCalledWith(ref.bytes);
|
|
111
131
|
expect(ref.state).toBe(ResourceResolutionState.Resolved);
|
|
112
132
|
expect(ref.failure).toBeNull();
|
|
113
133
|
});
|
|
114
134
|
|
|
135
|
+
it('requests and declares premultiplied output when the plain reference says its source retains it', async () => {
|
|
136
|
+
const ref = createEmbeddedImageResourceReference(new Uint8Array([1]), 'image/png', 'premultiplied');
|
|
137
|
+
|
|
138
|
+
const source = await resolveImageResourceReference(ref, unusedFetch, new AbortController().signal);
|
|
139
|
+
|
|
140
|
+
expect(decoder).toHaveBeenCalledWith(ref.bytes, { premultiplyAlpha: true });
|
|
141
|
+
expect(source?.alphaType).toBe('premultiplied');
|
|
142
|
+
});
|
|
143
|
+
|
|
115
144
|
it('routes an external reference through the fetch seam', async () => {
|
|
116
145
|
const ref = createExternalImageResourceReference('atlas.png', '/assets');
|
|
117
146
|
const fetched = { width: 2 } as Image;
|