-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Downscale pasted PNG images based on metadata #29123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
34b4199
Downscale pasted images based on png metadata
silverwind bd88a3a
review and tweaks
silverwind e84c41a
add pngChunks function, remove dependency
silverwind dac316d
use filename and escape
silverwind f544683
check unit before using it
silverwind 132ea7e
typo
silverwind eeac408
fix lint
silverwind c4a1e6a
add test for pngInfo
silverwind 1fdf77f
swap
silverwind a417737
fix non-meter logic
silverwind 84325b8
make both functions accept blobs and add tests
silverwind c8683c5
rename function
silverwind d0ff9e3
enhance comment
silverwind c9cd1a2
move comment
silverwind 93468a0
fix comment
silverwind d5ce26f
handle empty png
silverwind 5880a2c
shorten code
silverwind 4bc121d
tweak comments
silverwind 86de298
create DataView only once
silverwind fcbdbfb
use DataView default offset
silverwind cd5d8d1
minimal valid png length is 12 bytes
silverwind 6f947b7
rename back to imageInfo
silverwind bd3accb
tweak comment
silverwind ccadc45
Merge branch 'main' into imgscale
silverwind cf2cdd3
Merge branch 'main' into imgscale
GiteaBot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
export async function pngChunks(blob) { | ||
const uint8arr = new Uint8Array(await blob.arrayBuffer()); | ||
const chunks = []; | ||
if (uint8arr.length < 12) return chunks; | ||
const view = new DataView(uint8arr.buffer); | ||
if (view.getBigUint64(0) !== 9894494448401390090n) return chunks; | ||
|
||
const decoder = new TextDecoder(); | ||
let index = 8; | ||
while (index < uint8arr.length) { | ||
const len = view.getUint32(index); | ||
chunks.push({ | ||
name: decoder.decode(uint8arr.slice(index + 4, index + 8)), | ||
data: uint8arr.slice(index + 8, index + 8 + len), | ||
}); | ||
index += len + 12; | ||
} | ||
|
||
return chunks; | ||
} | ||
|
||
// decode a image and try to obtain width and dppx. If will never throw but instead | ||
// return default values. | ||
export async function imageInfo(blob) { | ||
let width = 0; // 0 means no width could be determined | ||
let dppx = 1; // 1 dot per pixel for non-HiDPI screens | ||
|
||
if (blob.type === 'image/png') { // only png is supported currently | ||
try { | ||
for (const {name, data} of await pngChunks(blob)) { | ||
const view = new DataView(data.buffer); | ||
if (name === 'IHDR' && data?.length) { | ||
// extract width from mandatory IHDR chunk | ||
width = view.getUint32(0); | ||
} else if (name === 'pHYs' && data?.length) { | ||
// extract dppx from optional pHYs chunk, assuming pixels are square | ||
const unit = view.getUint8(8); | ||
if (unit === 1) { | ||
dppx = Math.round(view.getUint32(0) / 39.3701) / 72; // meter to inch to dppx | ||
} | ||
} | ||
} | ||
} catch {} | ||
} | ||
|
||
return {width, dppx}; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import {pngChunks, imageInfo} from './image.js'; | ||
|
||
const pngNoPhys = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAADUlEQVQIHQECAP3/AAAAAgABzePRKwAAAABJRU5ErkJggg=='; | ||
const pngPhys = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAEElEQVQI12OQNZcAIgYIBQAL8gGxdzzM0A=='; | ||
const pngEmpty = 'data:image/png;base64,'; | ||
|
||
async function dataUriToBlob(datauri) { | ||
return await (await globalThis.fetch(datauri)).blob(); | ||
} | ||
|
||
test('pngChunks', async () => { | ||
expect(await pngChunks(await dataUriToBlob(pngNoPhys))).toEqual([ | ||
{name: 'IHDR', data: new Uint8Array([0, 0, 0, 1, 0, 0, 0, 1, 8, 0, 0, 0, 0])}, | ||
{name: 'IDAT', data: new Uint8Array([8, 29, 1, 2, 0, 253, 255, 0, 0, 0, 2, 0, 1])}, | ||
{name: 'IEND', data: new Uint8Array([])}, | ||
]); | ||
expect(await pngChunks(await dataUriToBlob(pngPhys))).toEqual([ | ||
{name: 'IHDR', data: new Uint8Array([0, 0, 0, 2, 0, 0, 0, 2, 8, 2, 0, 0, 0])}, | ||
{name: 'pHYs', data: new Uint8Array([0, 0, 22, 37, 0, 0, 22, 37, 1])}, | ||
{name: 'IDAT', data: new Uint8Array([8, 215, 99, 144, 53, 151, 0, 34, 6, 8, 5, 0, 11, 242, 1, 177])}, | ||
]); | ||
expect(await pngChunks(await dataUriToBlob(pngEmpty))).toEqual([]); | ||
}); | ||
|
||
test('imageInfo', async () => { | ||
expect(await imageInfo(await dataUriToBlob(pngNoPhys))).toEqual({width: 1, dppx: 1}); | ||
expect(await imageInfo(await dataUriToBlob(pngPhys))).toEqual({width: 2, dppx: 2}); | ||
expect(await imageInfo(await dataUriToBlob(pngEmpty))).toEqual({width: 0, dppx: 1}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.