Skip to content

Commit

Permalink
feat(pixel): add invert, add/split interfaces, refactor blit fns
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jul 23, 2019
1 parent b3c79e3 commit 22a456a
Show file tree
Hide file tree
Showing 8 changed files with 410 additions and 86 deletions.
65 changes: 58 additions & 7 deletions packages/pixel/src/abgr-int.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { IObjectOf } from "@thi.ng/api";
import { lane8, Lane8, setLane8 } from "@thi.ng/binary";
import { Channel, IColorChannel, IPixelBuffer } from "./api";
import {
Channel,
IBlit,
IColorChannel,
IGrayscale,
IInvert,
IPixelBuffer
} from "./api";
import { imageCanvas } from "./canvas";
import { Uint8Buffer } from "./uint8";
import { abgrToGrayU8, blit1, ensureSize } from "./utils";
import {
abgrToGrayU8,
blit1,
clampRegion,
ensureSize
} from "./utils";

const LANES = <IObjectOf<Lane8>>{
[Channel.ALPHA]: 0,
Expand All @@ -17,7 +29,12 @@ const LANES = <IObjectOf<Lane8>>{
* by `ImageData`).
*/
export class ABGRBuffer
implements IPixelBuffer<Uint32Array, number>, IColorChannel<Uint8Array> {
implements
IPixelBuffer<Uint32Array, number>,
IBlit<Uint32Array, number>,
IColorChannel<Uint8Array>,
IGrayscale<Uint8Array, number>,
IInvert {
/**
* Takes a fully initialized image element and returns a
* `ABGRBuffer` instance of its contents. Optionally, a target size
Expand Down Expand Up @@ -68,16 +85,28 @@ export class ABGRBuffer
}
}

blit(buf: IPixelBuffer<Uint32Array, number>, x = 0, y = 0) {
blit(
buf: IPixelBuffer<Uint32Array, number>,
dx = 0,
dy = 0,
sx = 0,
sy = 0,
w = this.width,
h = this.height
) {
blit1(
this.pixels,
buf.pixels,
x,
y,
sx,
sy,
this.width,
this.height,
dx,
dy,
buf.width,
buf.height
buf.height,
w,
h
);
}

Expand All @@ -94,6 +123,20 @@ export class ABGRBuffer
ctx.putImageData(idata, x, y);
}

getRegion(x: number, y: number, width: number, height: number) {
[x, y, width, height] = clampRegion(
x,
y,
width,
height,
this.width,
this.height
);
const dest = new ABGRBuffer(width, height);
this.blit(dest, 0, 0, x, y, width, height);
return dest;
}

getAt(x: number, y: number) {
return x >= 0 && x < this.width && y >= 0 && y < this.height
? this.pixels[(x | 0) + (y | 0) * this.width]
Expand Down Expand Up @@ -136,4 +179,12 @@ export class ABGRBuffer
abgrToGrayU8(this.pixels)
);
}

invert() {
const pix = this.pixels;
for (let i = pix.length; --i >= 0; ) {
pix[i] ^= 0xffffff;
}
return this;
}
}
77 changes: 57 additions & 20 deletions packages/pixel/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,42 @@ export interface IPixelBuffer<T extends TypedArray, P> {
height: number;
pixels: T;

/**
* Returns pixel value at given position. If pos is outside the
* defined region, returns a suitable zero value.
*
* @param x
* @param y
*/
getAt(x: number, y: number): P;

/**
* Writes pixel value at given position. Has no effect if outside of
* the defined region.
*
* @param x
* @param y
* @param col
*/
setAt(x: number, y: number, col: P): this;

/**
* Extracts region as new pixel buffer in same format.
*
* @param x
* @param y
* @param width
* @param height
*/
getRegion(
x: number,
y: number,
width: number,
height: number
): IPixelBuffer<T, P>;
}

export interface IBlit<T extends TypedArray, P> {
/**
* Blits pixels into given `dest` pixel buffer at position `x`, `y`
* (0,0 by default). If `dest` buffer is smaller than source buffer,
Expand All @@ -19,36 +55,37 @@ export interface IPixelBuffer<T extends TypedArray, P> {
* performed.
*
* @param dest
* @param x
* @param y
* @param dx
* @param dy
* @param sx
* @param sy
* @param w
* @param h
*/
blit(dest: IPixelBuffer<T, P>, x?: number, y?: number): void;
blit(
dest: IPixelBuffer<T, P>,
dx?: number,
dy?: number,
sx?: number,
sy?: number,
w?: number,
h?: number
): void;

/**
* Converts and blits pixels into given canvas at position `x`, `y`
* (0,0 by default). If canvas is smaller than source buffer, only
* the top-left region will be written.
*/
blitCanvas(canvas: HTMLCanvasElement, x?: number, y?: number): void;
}

/**
* Returns pixel value at given position. If pos is outside the
* defined region, returns a suitable zero value.
*
* @param x
* @param y
*/
getAt(x: number, y: number): P;
export interface IInvert {
invert(): this;
}

/**
* Writes pixel value at given position. Has no effect if outside of
* the defined region.
*
* @param x
* @param y
* @param col
*/
setAt(x: number, y: number, col: P): this;
export interface IGrayscale<T extends TypedArray, P> {
grayscale(): IPixelBuffer<T, P>;
}

export interface IColorChannel<T extends TypedArray> {
Expand Down
60 changes: 54 additions & 6 deletions packages/pixel/src/argb-int.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { IObjectOf } from "@thi.ng/api";
import { Lane8, lane8, setLane8 } from "@thi.ng/binary";
import { Channel, IPixelBuffer } from "./api";
import {
Channel,
IBlit,
IColorChannel,
IGrayscale,
IInvert,
IPixelBuffer
} from "./api";
import { imageCanvas } from "./canvas";
import { Uint8Buffer } from "./uint8";
import {
argbToGrayU8,
blit1,
clampRegion,
ensureSize,
swapRB
} from "./utils";
Expand All @@ -20,7 +28,13 @@ const LANES = <IObjectOf<Lane8>>{
/**
* Buffer of 32bit packed ARGB values.
*/
export class ARGBBuffer implements IPixelBuffer<Uint32Array, number> {
export class ARGBBuffer
implements
IPixelBuffer<Uint32Array, number>,
IBlit<Uint32Array, number>,
IColorChannel<Uint8Array>,
IGrayscale<Uint8Array, number>,
IInvert {
/**
* Takes a fully initialized image element and returns a
* `ARGBBuffer` instance of its contents. Optionally, a target size
Expand Down Expand Up @@ -73,16 +87,28 @@ export class ARGBBuffer implements IPixelBuffer<Uint32Array, number> {
}
}

blit(buf: IPixelBuffer<Uint32Array, number>, x = 0, y = 0) {
blit(
buf: IPixelBuffer<Uint32Array, number>,
dx = 0,
dy = 0,
sx = 0,
sy = 0,
w = this.width,
h = this.height
) {
blit1(
this.pixels,
buf.pixels,
x,
y,
sx,
sy,
this.width,
this.height,
dx,
dy,
buf.width,
buf.height
buf.height,
w,
h
);
}

Expand All @@ -97,6 +123,20 @@ export class ARGBBuffer implements IPixelBuffer<Uint32Array, number> {
ctx.putImageData(idata, x, y);
}

getRegion(x: number, y: number, width: number, height: number) {
[x, y, width, height] = clampRegion(
x,
y,
width,
height,
this.width,
this.height
);
const dest = new ARGBBuffer(width, height);
this.blit(dest, 0, 0, x, y, width, height);
return dest;
}

getAt(x: number, y: number) {
return x >= 0 && x < this.width && y >= 0 && y < this.height
? this.pixels[(x | 0) + (y | 0) * this.width]
Expand Down Expand Up @@ -139,4 +179,12 @@ export class ARGBBuffer implements IPixelBuffer<Uint32Array, number> {
argbToGrayU8(this.pixels)
);
}

invert() {
const pix = this.pixels;
for (let i = pix.length; --i >= 0; ) {
pix[i] ^= 0xffffff;
}
return this;
}
}
Loading

0 comments on commit 22a456a

Please sign in to comment.