Skip to content

Commit 8d49a8c

Browse files
committed
feat(image): support Transformer from raw rgba pixels
1 parent 7cd00d4 commit 8d49a8c

File tree

10 files changed

+109
-21
lines changed

10 files changed

+109
-21
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@types/node": "^17.0.23",
1717
"@types/sharp": "^0.30.1",
1818
"ava": "^4.1.0",
19+
"blurhash": "^1.1.5",
1920
"lerna": "^4.0.0",
2021
"npm-run-all": "^4.1.5",
2122
"prettier": "^2.6.2",
768 Bytes
Loading

packages/binding/__test__/decoder.spec.mjs.md

Lines changed: 0 additions & 17 deletions
This file was deleted.
-309 Bytes
Binary file not shown.

packages/binding/__test__/decoder.spec.mjs renamed to packages/binding/__test__/transformer.spec.mjs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { join } from 'path'
33
import { fileURLToPath } from 'url'
44

55
import test from 'ava'
6+
import { decode } from 'blurhash'
67

78
import { Transformer } from '../index.js'
89

9-
const ROOT_DIR = join(fileURLToPath(import.meta.url), '..', '..', '..', '..')
10+
const __DIRNAME = join(fileURLToPath(import.meta.url), '..')
11+
const ROOT_DIR = join(__DIRNAME, '..', '..', '..')
1012

1113
const PNG = await fs.readFile(join(ROOT_DIR, 'un-optimized.png'))
1214
const JPEG = await fs.readFile(join(ROOT_DIR, 'un-optimized.jpg'))
@@ -38,3 +40,10 @@ test('should be able to encode into webp', async (t) => {
3840
const decoder = new Transformer(PNG)
3941
await t.notThrowsAsync(() => decoder.webp(75))
4042
})
43+
44+
test('should be able to create transformer from raw rgba pixels', async (t) => {
45+
const pixels = decode('LEHV6nWB2yk8pyo0adR*.7kCMdnj', 32, 32)
46+
const webp = await Transformer.fromRgbaPixels(pixels, 32, 32).webpLossless()
47+
const webpSnapshot = await fs.readFile(join(__DIRNAME, 'blurhash.webp'))
48+
t.deepEqual(webp, webpSnapshot)
49+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Snapshot report for `packages/binding/__test__/transformer.spec.mjs`
2+
3+
The actual snapshot is saved in `transformer.spec.mjs.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## should be able to get exif from jpg
8+
9+
> Snapshot 1
10+
11+
{
12+
Orientation: 'Unknown (5)',
13+
'Resolution Unit': 'in',
14+
'This image has an Exif SubIFD': '90',
15+
'X Resolution': '72 pixels per in',
16+
'Y Resolution': '72 pixels per in',
17+
}
18+
19+
## should be able to create transformer from raw rgba pixels
20+
21+
> Snapshot 1
22+
23+
Buffer @Uint8Array [
24+
52494646 f8020000 57454250 5650384c ec020000 2f1fc007 004d1069 dba0a1d7
25+
bfe28b88 e87f46f9 6141a46d 33ff2a0b 0f2f67e0 09b26de6 4f778422 1ca1ff31
26+
1152ce80 03c00000 421b4992 2467f387 b1382bf6 1e101222 497224c9 a3e7d4b3
27+
12fc593c 8cdfde74 104992d0 f43ce05f 573c1136 f2f3ef27 cbb2c71e eff1cef6
28+
e11d7bf6 8e9dad39 1366da7a ebead6ab 5eddfbea 9eeee99e eed5bb76 bc031980
29+
3081a106 b5d85436 016019e1 4f4d0c95 0095b229 6600888d 00408d0a 444a9991
30+
94819204 d4b6801a 40b300cd 82444808 7594a100 2115508d 39761462 34a0b94d
31+
8c44c188 d1094ac8 a94a880d 9d9c8961 c440abb0 4d299952 89e88449 15555509
32+
61468201 8419d46e a554a522 22d580a2 54e9a299 0e1fca36 02038866 b2754985
33+
aa52a953 15552ac7 952d0310 0c0304c6 593089a5 0d4b282c 982aae4e 283ec702
34+
ff068d6a 97989551 30d250aa aa529d82 21662136 9259dac8 944dabb6 756c6a86
35+
2390d2e9 389005c0 400cd6a2 0c76f21f 56a05942 50c5aaea ead2d97e d586dac8
36+
9618ca60 02160246 1a08562a 56c5fd86 4c6c28a3 3619c856 99663983 00088e0a
37+
5529557f 64b04930 8011b664 04ad00c8 268d8222 9d4aa7fe ce578ce5 c53fa660
38+
2de4cc2b b358655b 6404c394 2d694631 c3000831 1a009aa5 91010a26 304803c8
39+
68460c62 404c1930 3d8001b1 4c19886d a4910d00 65340b40 19812d41 00831623
40+
6d541a46 b377140c 10230620 a3b28ba1 01d5a634 6096960c c200c55a 6b2d606a
41+
5bd9d296 6c4b621a 80b46065 9b3f4062 162361b4 d8d4a87d 5c406c43 876dd0d2
42+
5a30c50a c32c2d01 9306196c 127b2dd9 0a690298 a1f6b97a a76d8455 620031d4
43+
6032830c 80cdc144 56abb1da 1ad50006 a1d810b3 c846e4e3 e6b31844 9443c678
44+
4bb386a2 11234680 0543f059 2c318403 32566a35 26990ca0 d8940162 4b2cb3b4
45+
b6114644 89c8f2e6 c98c5888 b6550032 9b624066 63398051 a2d41863 2cad4103
46+
65c44610 cc6400c2 1d005132 53430d6b 014000c4 c4080d86 c50c6898 c2466d3c
47+
a62d6104 60024b6c 0433a4c5 08c38420 0a6a400d 0b10d848 6c0acc12 d6e01f03
48+
]
1.2 KB
Binary file not shown.

packages/binding/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export interface Metadata {
129129
}
130130
export class Transformer {
131131
constructor(input: Buffer)
132+
static fromRgbaPixels(input: Buffer | Uint8ClampedArray, width: number, height: number): Transformer
132133
metadata(withExif?: boolean | undefined | null, signal?: AbortSignal | undefined | null): Promise<Metadata>
133134
/** Rotate with exif orientation */
134135
rotate(): this

packages/binding/src/transformer.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,50 @@ pub struct Transformer {
342342
#[napi]
343343
impl Transformer {
344344
#[napi(constructor)]
345-
pub fn new(input: Buffer) -> Result<Transformer> {
346-
Ok(Self {
345+
pub fn new(input: Buffer) -> Transformer {
346+
Self {
347347
dynamic_image: Arc::new(ThreadSafeDynamicImage::new(input)),
348348
rotate: false,
349349
resize: (None, None),
350-
})
350+
}
351+
}
352+
353+
#[napi]
354+
pub fn from_rgba_pixels(
355+
input: Either<Buffer, Uint8ClampedArray>,
356+
width: u32,
357+
height: u32,
358+
) -> Result<Transformer> {
359+
if let Some(image) = image::RgbaImage::from_vec(
360+
width,
361+
height,
362+
match input {
363+
Either::A(a) => a.to_vec(),
364+
Either::B(b) => b.to_vec(),
365+
},
366+
) {
367+
let image_meta = Box::new(Some(ImageMetaData {
368+
color_type: ColorType::Rgba8,
369+
orientation: None,
370+
image: DynamicImage::ImageRgba8(image),
371+
exif: HashMap::new(),
372+
format: ImageFormat::Png,
373+
has_parsed_exif: true,
374+
}));
375+
Ok(Self {
376+
dynamic_image: Arc::new(ThreadSafeDynamicImage {
377+
raw: vec![0].into(),
378+
image: Box::into_raw(image_meta),
379+
}),
380+
rotate: false,
381+
resize: (None, None),
382+
})
383+
} else {
384+
Err(Error::new(
385+
Status::InvalidArg,
386+
format!("Input buffer is not matched the width and height"),
387+
))
388+
}
351389
}
352390

353391
#[napi]

yarn.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,13 @@ __metadata:
16181618
languageName: node
16191619
linkType: hard
16201620

1621+
"blurhash@npm:^1.1.5":
1622+
version: 1.1.5
1623+
resolution: "blurhash@npm:1.1.5"
1624+
checksum: 8a647024948552e7250d4f123a0dc2a56941be476811c1c999b182cde01e6e15cc6938a8c523f1a2fea8c0dc12c1fffc1cf2001b86683e196bed03e88e176af2
1625+
languageName: node
1626+
linkType: hard
1627+
16211628
"brace-expansion@npm:^1.1.7":
16221629
version: 1.1.11
16231630
resolution: "brace-expansion@npm:1.1.11"
@@ -3417,6 +3424,7 @@ __metadata:
34173424
"@types/node": ^17.0.23
34183425
"@types/sharp": ^0.30.1
34193426
ava: ^4.1.0
3427+
blurhash: ^1.1.5
34203428
lerna: ^4.0.0
34213429
npm-run-all: ^4.1.5
34223430
prettier: ^2.6.2

0 commit comments

Comments
 (0)