Skip to content

Commit

Permalink
feat(image): change extractColors to extractRGBAs (#42)
Browse files Browse the repository at this point in the history
## Summary

<!-- Please summarize your changes. -->

<!-- Please link to any applicable information (forum posts, bug
reports, etc.). -->

I changed extractColors to extractRGBAs

## Checks

<!-- For completed items, change [ ] to [x]. -->

<!-- If you leave this checklist empty, your PR will very likely be
closed. -->

Please check the following:

- [x] I have written documents and tests, if needed.
  • Loading branch information
manudeli authored Sep 24, 2023
1 parent d29136d commit fab95ee
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 120 deletions.
1 change: 1 addition & 0 deletions configs/eslint-config-js/noimport.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ module.exports = {
],
rules: {
"arrow-body-style": ["warn", "as-needed"],
"newline-before-return": "warn",
},
};
43 changes: 0 additions & 43 deletions packages/image/src/extractColors.spec.ts

This file was deleted.

76 changes: 0 additions & 76 deletions packages/image/src/extractColors.ts

This file was deleted.

28 changes: 28 additions & 0 deletions packages/image/src/extractRGBAs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, expect, it } from "vitest";
import { extractRGBAs } from ".";

const load = (src: HTMLImageElement["src"]) =>
new Promise<HTMLImageElement>((resolve, reject) => {
const image = new Image();
image.onload = () => resolve(image);
image.onerror = () => reject();
image.src = src;
});

describe("extractRGBAs", () => {
it("should return an array of colors", async () => {
const image = await load("src/images/test.png");
const result = extractRGBAs(image, { quality: 10 });
expect(result.length).toBeGreaterThan(0);
});

it("should throw an error if quality is out of range", async () => {
const image = await load("src/images/test.png");
expect(() => extractRGBAs(image, { quality: 101 })).toThrow(
"options.quality should be between 1 and 100",
);
expect(() => extractRGBAs(image, { quality: 0 })).toThrow(
"options.quality should be between 1 and 100",
);
});
});
61 changes: 61 additions & 0 deletions packages/image/src/extractRGBAs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
type RGBA = readonly [number, number, number, number];
type ExtractRGBAsOptions = { quality: number };
const initialOptions: ExtractRGBAsOptions = { quality: 100 };
/**
* Filters and extracts relevant pixels from image data based on quality setting.
*/
export const extractRGBAs = (
/**
* The image pixel data.
*/
image: HTMLImageElement,
/**
* Quality setting for filtering pixels. Higher values mean more pixels are processed. Range: [1, 100]
*/
options = initialOptions,
) => {
if (options.quality < 1 || options.quality > 100) {
throw new Error("options.quality should be between 1 and 100");
}
const uint8ClampedArray = extractUint8ClampedArray(image);
const step = Math.ceil(100 / options.quality);

return Array.from({
length: Math.ceil(uint8ClampedArray.length / (4 * step)),
}).map((_, index) => {
const rIndex = index * 4 * step;

return [
uint8ClampedArray[rIndex],
uint8ClampedArray[rIndex + 1],
uint8ClampedArray[rIndex + 2],
uint8ClampedArray[rIndex + 3],
] as RGBA;
});
};

/**
* Extracts pixel data from an image.
*/
const extractUint8ClampedArray = (
/**
* The image element
*/
image: HTMLImageElement,
) => {
const canvas = document.createElement("canvas");
const canvasRenderingContext2D = canvas.getContext("2d");
if (!canvasRenderingContext2D) {
throw new Error("canvasRenderingContext2D is not supported");
}
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
canvasRenderingContext2D.drawImage(image, 0, 0);

return canvasRenderingContext2D.getImageData(
0,
0,
canvas.width,
canvas.height,
).data;
};
2 changes: 1 addition & 1 deletion packages/image/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { checkWebPSupport } from "./checkWebPSupport";
export { detect } from "./detect";
export { extractColors } from "./extractColors";
export { extractRGBAs } from "./extractRGBAs";
export { load, type ImageSource } from "./load";

0 comments on commit fab95ee

Please sign in to comment.