Skip to content

Commit bd7bd84

Browse files
committed
feat: add blurhash package
1 parent cf95e2d commit bd7bd84

71 files changed

Lines changed: 3638 additions & 81 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bun.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/.harness/manifest.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
global.RN_HARNESS = {
2-
appRegistryComponentName: 'NitroImageExample',
3-
disableViewFlattening: false,
4-
}
1+
global.RN_HARNESS = {
2+
appRegistryComponentName: 'NitroImageExample',
3+
disableViewFlattening: false,
4+
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { describe, expect, it } from 'react-native-harness'
2+
import { Images } from 'react-native-nitro-image'
3+
import {
4+
BlurHash,
5+
getAverageColor,
6+
isBlurhashValid,
7+
} from 'react-native-nitro-image-blurhash'
8+
9+
const RED = { r: 1, g: 0, b: 0, a: 1 }
10+
const BLUE = { r: 0, g: 0, b: 1, a: 1 }
11+
12+
describe('BlurHash - round-trip', () => {
13+
it('encodes a small image to a BlurHash string', () => {
14+
const source = Images.createBlankImage(64, 64, true, BLUE).resize(32, 32)
15+
const hash = BlurHash.encode(source, 4, 3)
16+
expect(typeof hash).toBe('string')
17+
expect(hash.length).toBeGreaterThan(0)
18+
expect(isBlurhashValid(hash)).toEqual({ isValid: true })
19+
})
20+
21+
it('decode produces an Image of requested dimensions', () => {
22+
const source = Images.createBlankImage(64, 64, true, BLUE).resize(32, 32)
23+
const hash = BlurHash.encode(source, 4, 3)
24+
const decoded = BlurHash.decode(hash, 16, 24, 1)
25+
expect(decoded.width).toBe(16)
26+
expect(decoded.height).toBe(24)
27+
})
28+
29+
it('async variants round-trip encode + decode', async () => {
30+
const source = Images.createBlankImage(64, 64, true, RED).resize(32, 32)
31+
const hash = await BlurHash.encodeAsync(source, 4, 3)
32+
const decoded = await BlurHash.decodeAsync(hash, 32, 32, 1)
33+
expect(decoded.width).toBe(32)
34+
expect(decoded.height).toBe(32)
35+
})
36+
})
37+
38+
describe('isBlurhashValid', () => {
39+
it('returns isValid:true for a freshly produced hash', () => {
40+
const source = Images.createBlankImage(64, 64, true, BLUE).resize(32, 32)
41+
const hash = BlurHash.encode(source, 4, 3)
42+
expect(isBlurhashValid(hash)).toEqual({ isValid: true })
43+
})
44+
45+
it('rejects a malformed hash with an errorReason', () => {
46+
const result = isBlurhashValid('bad')
47+
expect(result.isValid).toBe(false)
48+
if (!result.isValid) {
49+
expect(result.errorReason.length).toBeGreaterThan(0)
50+
}
51+
})
52+
})
53+
54+
describe('getAverageColor', () => {
55+
it('returns r/g/b channels in [0, 1] for a valid hash', () => {
56+
const source = Images.createBlankImage(64, 64, true, BLUE).resize(32, 32)
57+
const hash = BlurHash.encode(source, 4, 3)
58+
const color = getAverageColor(hash)
59+
expect(color).toBeDefined()
60+
if (color != null) {
61+
for (const channel of [color.r, color.g, color.b]) {
62+
expect(channel).toBeGreaterThanOrEqual(0)
63+
expect(channel).toBeLessThanOrEqual(1)
64+
}
65+
}
66+
})
67+
68+
it('returns undefined for a too-short hash', () => {
69+
expect(getAverageColor('short')).toBeUndefined()
70+
})
71+
})
72+
73+
describe('BlurHash.clearCosineCache', () => {
74+
it('does not throw', () => {
75+
expect(() => BlurHash.clearCosineCache()).not.toThrow()
76+
})
77+
})

0 commit comments

Comments
 (0)