UNPKG

pxt-common-packages

Version:
360 lines (310 loc) 11.8 kB
type color = number namespace image { export enum Dimension { //% block="width" Width, //% block="height" Height } export function repeatY(count: number, image: Image) { let arr = [image] while (--count > 0) arr.push(image) return concatY(arr) } export function concatY(images: Image[]) { let w = 0 let h = 0 for (let img of images) { w = Math.max(img.width, w) h += img.height } let r = image.create(w, h) let y = 0 for (let img of images) { let x = (w - img.width) >> 1 r.drawImage(img, x, y) y += img.height } return r } /** * Returns the width or height of a picture. * * @param picture The picture to get the width or height of * @param dimension The dimension to get * @returns */ //% blockId=image_get_dimension //% group="Create" //% blockNamespace="images" //% block="$picture $dimension" //% picture.shadow=variables_get //% picture.defl=picture export function getDimension(picture: Image, dimension: Dimension) { if (dimension === Dimension.Width) return picture.width; else return picture.height; } } //% snippet='img` `' //% pySnippet='img(""" """)' //% fixedInstances interface Image { /** * Draw an icon (monochromatic image) using given color */ //% helper=imageDrawIcon drawIcon(icon: Buffer, x: number, y: number, c: color): void; /** * Fill a rectangle */ //% helper=imageFillRect fillRect(x: number, y: number, w: number, h: number, c: color): void; /** * Draw a line */ //% helper=imageDrawLine drawLine(x0: number, y0: number, x1: number, y1: number, c: color): void; /** * Draw an empty rectangle */ //% helper=imageDrawRect drawRect(x: number, y: number, w: number, h: number, c: color): void; /** * Draw a circle */ //% helper=imageDrawCircle drawCircle(cx: number, cy: number, r: number, c: color): void; /** * Fills a circle */ //% helper=imageFillCircle fillCircle(cx: number, cy: number, r: number, c: color): void; /** * Fills a triangle */ //% helper=imageFillTriangle fillTriangle(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number): void; /** * Fills a 4-side-polygon */ //% helper=imageFillPolygon4 fillPolygon4(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number): void; /** * Returns an image rotated by -90, 90, -180, 180, -270, 270 deg clockwise */ //% helper=imageRotated rotated(deg: number): Image; /** * Scale and copy a row of pixels from a texture. */ //% helper=imageBlitRow blitRow(dstX: number, dstY: number, from: Image, fromX: number, fromH: number): void; /** * Copy an image from a source rectangle to a destination rectangle, stretching or * compressing to fit the dimensions of the destination rectangle, if necessary. */ //% helper=imageBlit blit(xDst: number, yDst: number, wDst: number, hDst: number, src: Image, xSrc: number, ySrc: number, wSrc: number, hSrc: number, transparent: boolean, check: boolean): boolean; } interface ScreenImage extends Image { /** * Sets the screen backlight brightness (10-100) */ //% helper=setScreenBrightness setBrightness(deg: number): Image; /** * Gets current screen backlight brightness (0-100) */ //% helper=screenBrightness brightness(): number; } // pxt compiler currently crashes on non-functions in helpers namespace; will fix namespace _helpers_workaround { export let brightness = 100 } namespace helpers { //% shim=ImageMethods::_drawLine function _drawLine(img: Image, xy: number, wh: number, c: color): void { } //% shim=ImageMethods::_fillRect function _fillRect(img: Image, xy: number, wh: number, c: color): void { } //% shim=ImageMethods::_mapRect function _mapRect(img: Image, xy: number, wh: number, m: Buffer): void { } //% shim=ImageMethods::_drawIcon function _drawIcon(img: Image, icon: Buffer, xy: number, c: color): void { } //% shim=ImageMethods::_fillCircle declare function _fillCircle(img: Image, cxy: number, r: number, c: color): void; //% shim=ImageMethods::_blitRow declare function _blitRow(img: Image, xy: number, from: Image, xh: number): void; //% shim=ImageMethods::_blit declare function _blit(img: Image, src: Image, args: number[]): boolean; //% shim=ImageMethods::_drawScaledRotatedImage declare function _drawScaledRotatedImage(img: Image, src: Image, args: number[]): void; //% shim=ImageMethods::_checkOverlapsScaledRotatedImage declare function _checkOverlapsScaledRotatedImage(img: Image, src: Image, args: number[]): boolean; //% shim=ImageMethods::_checkOverlapsTwoScaledRotatedImages declare function _checkOverlapsTwoScaledRotatedImages(img: Image, src: Image, args: number[]): boolean; //% shim=ImageMethods::_fillTriangle declare function _fillTriangle(img: Image, args: number[]): void; //% shim=ImageMethods::_fillPolygon4 declare function _fillPolygon4(img: Image, args: number[]): void; function pack(x: number, y: number) { return (Math.clamp(-30000, 30000, x | 0) & 0xffff) | (Math.clamp(-30000, 30000, y | 0) << 16) } let _blitArgs: number[]; export function imageBlit(img: Image, xDst: number, yDst: number, wDst: number, hDst: number, src: Image, xSrc: number, ySrc: number, wSrc: number, hSrc: number, transparent: boolean, check: boolean): boolean { _blitArgs = _blitArgs || []; _blitArgs[0] = xDst | 0; _blitArgs[1] = yDst | 0; _blitArgs[2] = wDst | 0; _blitArgs[3] = hDst | 0; _blitArgs[4] = xSrc | 0; _blitArgs[5] = ySrc | 0; _blitArgs[6] = wSrc | 0; _blitArgs[7] = hSrc | 0; _blitArgs[8] = transparent ? 1 : 0; _blitArgs[9] = check ? 1 : 0; return _blit(img, src, _blitArgs); } export function imageBlitRow(img: Image, dstX: number, dstY: number, from: Image, fromX: number, fromH: number): void { _blitRow(img, pack(dstX, dstY), from, pack(fromX, fromH)) } export function imageDrawIcon(img: Image, icon: Buffer, x: number, y: number, c: color): void { _drawIcon(img, icon, pack(x, y), c) } export function imageFillRect(img: Image, x: number, y: number, w: number, h: number, c: color): void { _fillRect(img, pack(x, y), pack(w, h), c) } export function imageMapRect(img: Image, x: number, y: number, w: number, h: number, m: Buffer): void { _mapRect(img, pack(x, y), pack(w, h), m) } export function imageDrawLine(img: Image, x: number, y: number, w: number, h: number, c: color): void { _drawLine(img, pack(x, y), pack(w, h), c) } export function imageDrawRect(img: Image, x: number, y: number, w: number, h: number, c: color): void { if (w == 0 || h == 0) return w-- h-- imageDrawLine(img, x, y, x + w, y, c) imageDrawLine(img, x, y, x, y + h, c) imageDrawLine(img, x + w, y + h, x + w, y, c) imageDrawLine(img, x + w, y + h, x, y + h, c) } export function imageDrawCircle(img: Image, cx: number, cy: number, r: number, col: number) { cx = cx | 0; cy = cy | 0; r = r | 0; // short cuts if (r < 0) return; // Bresenham's algorithm let x = 0 let y = r let d = 3 - 2 * r while (y >= x) { img.setPixel(cx + x, cy + y, col) img.setPixel(cx - x, cy + y, col) img.setPixel(cx + x, cy - y, col) img.setPixel(cx - x, cy - y, col) img.setPixel(cx + y, cy + x, col) img.setPixel(cx - y, cy + x, col) img.setPixel(cx + y, cy - x, col) img.setPixel(cx - y, cy - x, col) x++ if (d > 0) { y-- d += 4 * (x - y) + 10 } else { d += 4 * x + 6 } } } export function imageFillCircle(img: Image, cx: number, cy: number, r: number, col: number) { _fillCircle(img, pack(cx, cy), r, col); } export function imageFillTriangle(img: Image, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, col: number) { _blitArgs = _blitArgs || []; _blitArgs[0] = x0; _blitArgs[1] = y0; _blitArgs[2] = x1; _blitArgs[3] = y1; _blitArgs[4] = x2; _blitArgs[5] = y2; _blitArgs[6] = col; _fillTriangle(img, _blitArgs); } export function imageFillPolygon4(img: Image, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, col: number) { _blitArgs = _blitArgs || []; _blitArgs[0] = x0; _blitArgs[1] = y0; _blitArgs[2] = x1; _blitArgs[3] = y1; _blitArgs[4] = x2; _blitArgs[5] = y2; _blitArgs[6] = x3; _blitArgs[7] = y3; _blitArgs[8] = col; _fillPolygon4(img, _blitArgs); } export function imageDrawScaledRotated(dest: Image, destX: number, destY: number, src: Image, sx: number, sy: number, angle: number) { _blitArgs = _blitArgs || []; _blitArgs[0] = destX | 0; _blitArgs[1] = destY | 0; _blitArgs[2] = sx; _blitArgs[3] = sy; _blitArgs[4] = angle; _drawScaledRotatedImage(dest, src, _blitArgs); } export function checkOverlapsScaledRotatedImage(dest: Image, destX: number, destY: number, src: Image, sx: number, sy: number, angle: number) { _blitArgs = _blitArgs || []; _blitArgs[0] = destX | 0; _blitArgs[1] = destY | 0; _blitArgs[2] = sx; _blitArgs[3] = sy; _blitArgs[4] = angle; return _checkOverlapsScaledRotatedImage(dest, src, _blitArgs); } export function checkOverlapsTwoScaledRotatedImages(dest: Image, destX: number, destY: number, destSx: number, destSy: number, destAngle: number, src: Image, sx: number, sy: number, angle: number) { _blitArgs = _blitArgs || []; _blitArgs[0] = destX | 0; _blitArgs[1] = destY | 0; _blitArgs[2] = destSx; _blitArgs[3] = destSy; _blitArgs[4] = destAngle; _blitArgs[5] = sx; _blitArgs[6] = sy; _blitArgs[7] = angle; return _checkOverlapsTwoScaledRotatedImages(dest, src, _blitArgs); } /** * Returns an image rotated by 90, 180, 270 deg clockwise */ export function imageRotated(img: Image, deg: number) { if (deg == -90 || deg == 270) { let r = img.transposed(); r.flipY(); return r; } else if (deg == 180 || deg == -180) { let r = img.clone(); r.flipX(); r.flipY(); return r; } else if (deg == 90 || deg == -270) { let r = img.transposed(); r.flipX(); return r; } else { return null; } } //% shim=pxt::setScreenBrightness function _setScreenBrightness(brightness: number) { } export function setScreenBrightness(img: Image, b: number) { b = Math.clamp(10, 100, b | 0); _helpers_workaround.brightness = b _setScreenBrightness(_helpers_workaround.brightness) } export function screenBrightness(img: Image) { return _helpers_workaround.brightness } }