diff --git a/changes.md b/changes.md new file mode 100644 index 0000000..c0b3ae5 --- /dev/null +++ b/changes.md @@ -0,0 +1,7 @@ +## 2026-07-08 11:09 + +**Fix bug #224**: `Bitmap` constructor crash when float dimensions are passed to `make()`. + +In `src/bitmap.ts`, the constructor stored `Math.floor(w/h)` into `this.width/height` but then used the original float values for both the `Uint8Array` allocation and the fill loop. This caused `setPixelRGBA` to be called with `x = Math.floor(w)`, which equals `this.width`, triggering the `validate_coords` bounds check and throwing `Invalid Index: x N >= width N`. + +Fixed by using `this.width` and `this.height` consistently in place of the raw `w` and `h` floats after the floor assignment. Added `test/bugs/bug_224.test.ts` to cover this case. diff --git a/src/bitmap.ts b/src/bitmap.ts index 3e46018..7e09b38 100644 --- a/src/bitmap.ts +++ b/src/bitmap.ts @@ -22,11 +22,11 @@ export class Bitmap { constructor(w: number, h: number) { this.width = Math.floor(w); this.height = Math.floor(h); - this.data = new Uint8Array(w * h * 4); + this.data = new Uint8Array(this.width * this.height * 4); const fillval = OPAQUE_BLACK; - for (let j = 0; j < h; j++) { - for (let i = 0; i < w; i++) { + for (let j = 0; j < this.height; j++) { + for (let i = 0; i < this.width; i++) { this.setPixelRGBA(i, j, fillval); } } diff --git a/test/bugs/bug_224.test.ts b/test/bugs/bug_224.test.ts new file mode 100644 index 0000000..e2cea40 --- /dev/null +++ b/test/bugs/bug_224.test.ts @@ -0,0 +1,16 @@ +import { describe, it, expect } from "vitest"; +import * as PImage from "../../src/index.js"; + +describe("bug-224: make() with float dimensions should not crash", () => { + it("should construct without throwing when width and height are floats", () => { + expect(() => { + PImage.make(1100.000277777778, 849.9997222222221); + }).not.toThrow(); + }); + + it("constructed bitmap should have integer width and height", () => { + const image = PImage.make(1100.000277777778, 849.9997222222221); + expect(image.width).toBe(1100); + expect(image.height).toBe(849); + }); +});