diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b96f1ba..a372302 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -2,21 +2,20 @@ name: Run Tests on: push: branches: - - main + - "*" pull_request: - branches: - - main workflow_dispatch: jobs: test: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v4 - uses: denoland/setup-deno@v2 - - run: deno test -R='./' -W='./' --parallel --doc --trace-leaks + - run: deno test -R='.output/' -W='.output/' --parallel --doc --trace-leaks lint: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index 404abb2..6f0f8c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -coverage/ +.coverage/ +.output/ diff --git a/README.md b/README.md index 9a36b70..a22483a 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,26 @@ -# qoi +# Img -This is a TypeScript implementation of the QOI image format. The module offers -both sync and streaming versions to encode and decode to and from the QOI image -format. The raw pixel format/ the decoded format is a repeating sequence of -`[ r, g, b, a ]` in a `Uint8Array`, `Uint8ClampedArray`, or a -`ReadableStream`. +Img is a repo containing implemenetations, made from scratch, of various image +formats offering the ability to encode and decode between them, and integrate +smoothly with various Web APIs like the Canvas. Where possible, we offer both +sync and streaming encoders/decoders. -This implementationis based off the -[QOI Specification](https://qoiformat.org/qoi-specification.pdf). You can find -about more about QOI at their website: https://qoiformat.org/. +## Missing a format? -## Example +If this repo is missing a format you'd like to work with, simply create an issue +suggesting the format, along with a link to the standard, specifcation or some +document that is essentally the source of truth for that format. Do that and it +might get an implementation here. -```ts -import { encodeQOI } from "@img/qoi"; +## Formats -const rawData = await new Response(ReadableStream.from(async function* () { - for (let r = 0; r < 256; ++r) { - for (let c = 0; c < 256; ++c) { - yield Uint8Array.from([255 - r, c, r, 255]); - } - } -}())).bytes(); - -await Deno.writeFile( - "image.qoi", - encodeQOI(rawData, { - width: 256, - height: 256, - channels: "rgb", - colorspace: 0, - }), -); -``` +| Package | Latest Version | Spec | +| ------------------------------------- | -------------------------------------- | ------------------------------------------------------------ | +| [@img/apng](https://jsr.io/@img/apng) | Not Implemented Yet | https://wiki.mozilla.org/APNG_Specification | +| [@img/avif](https://jsr.io/@img/avif) | Not Implemented Yet | https://aomediacodec.github.io/av1-avif/v1.1.0.html | +| [@img/gif](https://jsr.io/@img/gif) | Not Implemented Yet | https://www.w3.org/Graphics/GIF/spec-gif89a.txt | +| [@img/jpeg](https://jsr.io/@img/jpeg) | Not Implemented Yet | https://www.w3.org/Graphics/JPEG/jfif3.pdf | +| [@img/png](https://jsr.io/@img/png) | Not Implemented Yet | https://www.w3.org/TR/2003/REC-PNG-20031110/ | +| [@img/qoi](https://jsr.io/@img/qoi) | ![JSR](https://jsr.io/badges/@img/qoi) | https://qoiformat.org/qoi-specification.pdf | +| [@img/avg](https://jsr.io/@img/svg) | Not Implemented Yet | https://www.w3.org/TR/SVG2/ | +| [@img/webp](https://jsr.io/@img/webp) | Not Implemented Yet | https://developers.google.com/speed/webp/docs/riff_container | diff --git a/deno.json b/deno.json index bda64b5..843d79b 100644 --- a/deno.json +++ b/deno.json @@ -1,34 +1,20 @@ { - "name": "@img/qoi", - "version": "0.1.3", - "publish": { - "exclude": ["**/.*"] - }, + "workspace": ["qoi"], "imports": { - "@std/assert": "jsr:@std/assert@^1.0.6", - "@std/bytes": "jsr:@std/bytes@^1.0.2", - "@std/streams": "jsr:@std/streams@^1.0.7" - }, - "exports": { - ".": "./src/mod.ts", - "./decode": "./src/decode.ts", - "./decoder-stream": "./src/decoder_stream.ts", - "./encode": "./src/encode.ts", - "./encoder-stream": "./src/encoder_stream.ts" + "@std/assert": "jsr:@std/assert@1", + "@std/bytes": "jsr:@std/bytes@1", + "@std/streams": "jsr:@std/streams@1" }, + "exclude": ["**/.*"], "tasks": { - "coverage": "deno coverage --html coverage/", - "coverage:mac": "deno task coverage && open coverage/html/index.html", - "coverage:lin": "deno task coverage && xdg-open coverage/html/index.html", - "coverage:win": "deno task coverage && start coverage/html/index.html", - "test": "deno test -R='./' -W='./' --parallel --doc --trace-leaks --coverage --clean && rm image.qoi", + "cov": "deno coverage --html .coverage/", + "cov:mac": "deno task cov && open .coverage/html/index.html", + "cov:lin": "deno task cov && xdg-open .coverage/html/index.html", + "cov:win": "deno task cov && start .coverage/html/index.html", + "test": "deno test -R='.output/' -W='.output/' --parallel --doc --trace-leaks --coverage='.coverage/' --clean", "ok": "deno fmt && deno lint && deno task test" }, - "fmt": { - "exclude": ["coverage/", "**/.*"] - }, "lint": { - "exclude": ["coverage/", "**/.*"], "rules": { "tags": ["recommended"], "include": [ @@ -47,8 +33,5 @@ "verbatim-module-syntax" ] } - }, - "test": { - "exclude": ["coverage/", "**/.*"] } } diff --git a/deno.lock b/deno.lock index 263fa7e..42a5a80 100644 --- a/deno.lock +++ b/deno.lock @@ -1,36 +1,33 @@ { "version": "4", "specifiers": { - "jsr:@std/assert@^1.0.6": "1.0.6", - "jsr:@std/bytes@^1.0.2": "1.0.2", - "jsr:@std/internal@^1.0.4": "1.0.4", - "jsr:@std/streams@^1.0.7": "1.0.7" + "jsr:@std/assert@1": "1.0.8", + "jsr:@std/bytes@1": "1.0.4", + "jsr:@std/internal@^1.0.5": "1.0.5", + "jsr:@std/streams@1": "1.0.8" }, "jsr": { - "@std/assert@1.0.6": { - "integrity": "1904c05806a25d94fe791d6d883b685c9e2dcd60e4f9fc30f4fc5cf010c72207", + "@std/assert@1.0.8": { + "integrity": "ebe0bd7eb488ee39686f77003992f389a06c3da1bbd8022184804852b2fa641b", "dependencies": [ "jsr:@std/internal" ] }, - "@std/bytes@1.0.2": { - "integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57" + "@std/bytes@1.0.4": { + "integrity": "11a0debe522707c95c7b7ef89b478c13fb1583a7cfb9a85674cd2cc2e3a28abc" }, - "@std/internal@1.0.4": { - "integrity": "62e8e4911527e5e4f307741a795c0b0a9e6958d0b3790716ae71ce085f755422" + "@std/internal@1.0.5": { + "integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba" }, - "@std/streams@1.0.7": { - "integrity": "1a93917ca0c58c01b2bfb93647189229b1702677f169b6fb61ad6241cd2e499b", - "dependencies": [ - "jsr:@std/bytes" - ] + "@std/streams@1.0.8": { + "integrity": "b41332d93d2cf6a82fe4ac2153b930adf1a859392931e2a19d9fabfb6f154fb3" } }, "workspace": { "dependencies": [ - "jsr:@std/assert@^1.0.6", - "jsr:@std/bytes@^1.0.2", - "jsr:@std/streams@^1.0.7" + "jsr:@std/assert@1", + "jsr:@std/bytes@1", + "jsr:@std/streams@1" ] } } diff --git a/src/_common.ts b/qoi/_common.ts similarity index 100% rename from src/_common.ts rename to qoi/_common.ts diff --git a/src/decode.ts b/qoi/decode.ts similarity index 100% rename from src/decode.ts rename to qoi/decode.ts diff --git a/src/decode_test.ts b/qoi/decode_test.ts similarity index 100% rename from src/decode_test.ts rename to qoi/decode_test.ts diff --git a/src/decoder_stream.ts b/qoi/decoder_stream.ts similarity index 100% rename from src/decoder_stream.ts rename to qoi/decoder_stream.ts diff --git a/src/decoder_stream_test.ts b/qoi/decoder_stream_test.ts similarity index 100% rename from src/decoder_stream_test.ts rename to qoi/decoder_stream_test.ts diff --git a/qoi/deno.json b/qoi/deno.json new file mode 100644 index 0000000..a0ea83c --- /dev/null +++ b/qoi/deno.json @@ -0,0 +1,11 @@ +{ + "name": "@img/qoi", + "version": "0.1.3", + "exports": { + ".": "./mod.ts", + "./decode": "./decode.ts", + "./decoder-stream": "./decoder_stream.ts", + "./encode": "./encode.ts", + "./encoder-stream": "./encoder_stream.ts" + } +} diff --git a/src/encode.ts b/qoi/encode.ts similarity index 95% rename from src/encode.ts rename to qoi/encode.ts index 56fca87..635d4b4 100644 --- a/src/encode.ts +++ b/qoi/encode.ts @@ -10,6 +10,8 @@ import type { QOIOptions } from "./types.ts"; * ```ts * import { encodeQOI } from "@img/qoi"; * + * await Deno.mkdir(".output/", { recursive: true }); + * * const rawData = await new Response(ReadableStream.from(async function* () { * for (let r = 0; r < 256; ++r) { * for (let c = 0; c < 256; ++c) { @@ -18,7 +20,7 @@ import type { QOIOptions } from "./types.ts"; * } * }())).bytes(); * - * await Deno.writeFile("image.qoi", encodeQOI(rawData, { + * await Deno.writeFile(".output/image.qoi", encodeQOI(rawData, { * width: 256, * height: 256, * channels: "rgb", diff --git a/src/encode_test.ts b/qoi/encode_test.ts similarity index 100% rename from src/encode_test.ts rename to qoi/encode_test.ts diff --git a/src/encoder_stream.ts b/qoi/encoder_stream.ts similarity index 96% rename from src/encoder_stream.ts rename to qoi/encoder_stream.ts index d2b8812..e210fdd 100644 --- a/src/encoder_stream.ts +++ b/qoi/encoder_stream.ts @@ -10,6 +10,8 @@ import type { QOIOptions } from "./types.ts"; * ```ts * import { QOIEncoderStream } from "@img/qoi"; * + * await Deno.mkdir(".output/", { recursive: true }); + * * await ReadableStream * .from(async function* () { * for (let r = 0; r < 256; ++r) { @@ -26,7 +28,7 @@ import type { QOIOptions } from "./types.ts"; * colorspace: 0, * }), * ) - * .pipeTo((await Deno.create("image.qoi")).writable); + * .pipeTo((await Deno.create(".output/image.qoi")).writable); * ``` * * @module diff --git a/src/encoder_stream_test.ts b/qoi/encoder_stream_test.ts similarity index 100% rename from src/encoder_stream_test.ts rename to qoi/encoder_stream_test.ts diff --git a/src/mod.ts b/qoi/mod.ts similarity index 90% rename from src/mod.ts rename to qoi/mod.ts index 8bf35c1..6e7a1af 100644 --- a/src/mod.ts +++ b/qoi/mod.ts @@ -13,6 +13,8 @@ * ```ts * import { encodeQOI } from "@img/qoi"; * + * await Deno.mkdir(".output/", { recursive: true }); + * * const rawData = await new Response(ReadableStream.from(async function* () { * for (let r = 0; r < 256; ++r) { * for (let c = 0; c < 256; ++c) { @@ -21,7 +23,7 @@ * } * }())).bytes(); * - * await Deno.writeFile("image.qoi", encodeQOI(rawData, { + * await Deno.writeFile(".output/image.qoi", encodeQOI(rawData, { * width: 256, * height: 256, * channels: "rgb", diff --git a/src/types.ts b/qoi/types.ts similarity index 100% rename from src/types.ts rename to qoi/types.ts