Sharp-equivalent API on the GPU - #1
Open
roprgm wants to merge 7 commits into
Open
Conversation
- Reuse a single framebuffer pair instead of allocating two per render - Dispose cached programs (WeakMap iteration was a no-op) - Decode inputs via createImageBitmap: img.decode() never resolves for detached images, and WebGL ignores UNPACK_FLIP_Y_WEBGL for ImageBitmap - Accept Blob/ImageData/ImageBitmap/canvas/img as input, not just URLs - Round derived resize dimensions and keep them >= 1 - Reject toBlob with an Error instead of undefined - Collapse the operation hierarchy into ShaderOperation + program consts - Drop unused GL abstractions (buffers, blending, attributes, elements) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add extract, extend, flip, flop and rotate, plus resize fit modes (cover/contain/fill/inside/outside) with gravity and background. Every geometry operation is a pure plan — a target size plus an affine map from target uv back to source uv — rendered by a single shader. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add convolve, sharpen, median, threshold, recomb, extractChannel, flatten, removeAlpha and normalize. grayscale now uses BT.709 luma to match sharp instead of zeroing HSL saturation. Uniforms are written according to the type declared in the shader, so a float[49] kernel is no longer mistaken for a matrix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add composite() with PDF blend modes and gravity/offset placement, metadata() for the loaded image, and toImageData() for pixel access. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Break gl.ts into texture/framebuffer/program/renderer so each file answers one question, and flatten resizePlan into named helpers. Rewrite the README around sharp parity, add the MIT license file and a CI workflow running format, typecheck, tests and build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The renderer now owns every texture it hands out, so destroy() frees them instead of leaking the ones held by operations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deploying sharp-gpu with
|
| Latest commit: |
aeeca9a
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://cac6c132.sharp-gpu.pages.dev |
| Branch Preview URL: | https://feat-sharp-api.sharp-gpu.pages.dev |
Fit, Gravity, BlendMode, ImageInput and the parameter types were only reachable through the class, so consumers could not import them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Brings the public API up to parity with the parts of sharp that make sense on a GPU, and fixes the bugs found along the way.
Fixes
render()allocated two framebuffers on every call and never freed them, so each slider drag in the example leaked GPU memory. The renderer now keeps one reusable ping-pong pair.dispose()iteratedObject.values()over aWeakMap, which is always empty.destroy(). The renderer now owns every texture it hands out.img.decode()hangs for images that are never attached to the document. Inputs are decoded withcreateImageBitmap, which also fixed the orientation flip WebGL introduces by ignoringUNPACK_FLIP_Y_WEBGLforImageBitmapuploads.toBlobrejected withundefinedinstead of anError.float[9]and amat3were indistinguishable. They are now dispatched by the type declared in the shader.New API
Geometry —
extract,extend,flip,flop,rotate(any angle, canvas grows to the bounding box), andresizewithfit(cover/contain/fill/inside/outside),positionandbackground.Effects —
convolve(up to 7x7),sharpen,median.Color —
threshold,recomb,normalize,extractChannel,removeAlpha,flatten.grayscalenow uses BT.709 luma to match sharp instead of zeroing HSL saturation.Composition —
compositewith PDF blend modes (over,multiply,screen,overlay,darken,lighten,difference,exclusion) placed by gravity or offset.I/O —
from()acceptsBlob,File,ImageData,ImageBitmap, canvas and<img>in addition to URLs; newmetadata()andtoImageData().Structure
Every geometry operation is now a pure plan — a target size plus an affine map from target uv back to source uv — rendered by one shader, so resize, crop, pad, mirror and rotate share a single code path and are unit-testable without a GPU.
gl.ts(497 lines, four concepts) is split intotexture/framebuffer/program/renderer. The unused buffer, blending, attribute and indexed-draw abstractions are gone, since every draw is a full-screen quad.Tests
bun test— 49 tests over the plan math: sizes, transforms, kernels, curves, luminance ranges, placement.test/browser— 49 tests rendering each operation on a real GPU and asserting on pixels, including a check thatdestroy()frees every allocated texture.Both suites pass, along with typecheck, build and the example app (verified interactively).
Also
MIT
LICENSEfile (the package claimed MIT with no license text), CI running format/typecheck/test/build, README rewritten around sharp parity, and.DS_Storeuntracked.