From 273b307b4408e8c3959dd110b9a4067fefc43fd0 Mon Sep 17 00:00:00 2001 From: Joe Lapp Date: Wed, 17 Jan 2018 19:32:00 -0600 Subject: [PATCH] redefined opaque as pixels of non-zero alpha --- README.md | 50 +++++++++++++++++++------------------------ src/bitmapimage.js | 12 +++++------ src/gifcodec.js | 8 +++---- templates/README.hbs | 2 +- test/lib/bitmaps.js | 20 +++++++++++------ test/lib/tools.js | 2 +- test/test_bitmap.js | 4 ++-- test/test_quantize.js | 6 +++--- 8 files changed, 52 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index e9c560f..a4c103c 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Images are represented within a GifFrame exactly as they are in a `Jimp` image. * `frame.bitmap.height` - Height of image in pixels * `frame.bitmap.data` - A Node.js Buffer that can be accessed like an array of bytes. Every 4 adjacent bytes represents the RGBA values of a single pixel. These 4 bytes correspond to red, green, blue, and alpha, in that order. Each pixel begins at an index that is a multiple of 4. -GIFs do not support partial transparency, so within `frame.bitmap.data`, the pixels having alpha value 0xFF are treated as opaque and pixels of all other alpha values are treated as transparent. The encoder ignores the RGB values of transparent pixels. +GIFs do not support partial transparency, so within `frame.bitmap.data`, pixels having alpha value 0x00 are treated as transparent and pixels of non-zero alpha value are treated as opaque. The encoder ignores the RGB values of transparent pixels. `gifwrap` also provides utilities for reading GIF files and for parsing raw encodings: @@ -214,6 +214,8 @@ The [Typescript typings](https://github.com/jtlapp/gifwrap/blob/master/index.d.t * [.fillRGBA(rgba)](#BitmapImage+fillRGBA) + * [.getPalette()](#BitmapImage+getPalette) + * [.getRGBA(x, y)](#BitmapImage+getRGBA) * [.greyscale()](#BitmapImage+greyscale) @@ -228,14 +230,6 @@ The [Typescript typings](https://github.com/jtlapp/gifwrap/blob/master/index.d.t -* [GifFrame](#GifFrame) - - * [new GifFrame()](#new_GifFrame_new) - - * [.getPalette()](#GifFrame+getPalette) - - - * [GifUtil](#GifUtil) * [.cloneFrames(frames)](#GifUtil.cloneFrames) @@ -304,7 +298,7 @@ Its constructor supports the following signatures: When a `BitmapImage` is provided, the constructed `BitmapImage` is a deep clone of the provided one, so that each image's pixel data can subsequently be modified without affecting each other. -`backgroundRGBA` is an optional parameter representing a pixel as a single number. In hex, the number is as follows: 0xRRGGBBAA, where RR is the red byte, GG the green byte, BB, the blue byte, and AA the alpha value. An AA of 0xFF is considered opaque, and all other AA values are treated as transparent. +`backgroundRGBA` is an optional parameter representing a pixel as a single number. In hex, the number is as follows: 0xRRGGBBAA, where RR is the red byte, GG the green byte, BB, the blue byte, and AA the alpha value. An AA of 0x00 is considered transparent, and all non-zero AA values are treated as opaque. @@ -327,11 +321,23 @@ Copy a square portion of this image into another image. | Param | Type | Description | | --- | --- | --- | -| rgba | number | Color with which to fill image, expressed as a singlenumber in the form 0xRRGGBBAA, where AA is 0xFF for opaque and any other value for transparent. | +| rgba | number | Color with which to fill image, expressed as a singlenumber in the form 0xRRGGBBAA, where AA is 0x00 for transparent and any other value for opaque. | Fills the image with a single color. **Returns**: [BitmapImage](#BitmapImage) - The present image to allow for chaining. + + +### *bitmapImage*.getPalette() +Get a summary of the colors found within the image. The return value is an object of the following form: + +Property | Description +--- | --- +colors | An array of all the opaque colors found within the image. Each color is given as an RGB number of the form 0xRRGGBB. The array is sorted by increasing number. Will be an empty array when the image is completely transparent. +usesTransparency | boolean indicating whether there are any transparent pixels within the image. A pixel is considered transparent if its alpha value is 0x00. +indexCount | The number of color indexes required to represent this palette of colors. It is equal to the number of opaque colors plus one if the image includes transparency. + +**Returns**: object - An object representing a color palette as described above. ### *bitmapImage*.getRGBA(x, y) @@ -341,7 +347,7 @@ Fills the image with a single color. | x | number | x-coord of pixel | | y | number | y-coord of pixel | -Gets the RGBA number of the pixel at the given coordinate in the form 0xRRGGBBAA, where AA is the alpha value, with 0xFF being opaque. +Gets the RGBA number of the pixel at the given coordinate in the form 0xRRGGBBAA, where AA is the alpha value, with 0x00 being transparent. **Returns**: number - RGBA of pixel in 0xRRGGBBAA form @@ -360,7 +366,7 @@ Converts the image to greyscale using inferred Adobe metrics. | yOffset | number | The y-coord offset of the upper-left pixel of the desired image relative to the present image. | | width | number | The width of the new image after reframing | | height | number | The height of the new image after reframing | -| fillRGBA | number | The color with which to fill space added to the image as a result of the reframing, in 0xRRGGBBAA format, where AA is 0xFF to indicate opaque and any other value to indicate transparent. This parameter is only required when the reframing exceeds the original boundaries (i.e. does not simply perform a crop). | +| fillRGBA | number | The color with which to fill space added to the image as a result of the reframing, in 0xRRGGBBAA format, where AA is 0x00 to indicate transparent and a non-zero value to indicate opaque. This parameter is only required when the reframing exceeds the original boundaries (i.e. does not simply perform a crop). | Reframes the image as if placing a frame around the original image and replacing the original image with the newly framed image. When the new frame is strictly within the boundaries of the original image, this method crops the image. When any of the new boundaries exceed those of the original image, the `fillRGBA` must be provided to indicate the color with which to fill the extra space added to the image. @@ -423,18 +429,6 @@ See the base class BitmapImage for a discussion of all parameters but `options` Provide a `frame` to the constructor to create a clone of the provided frame. The new frame includes a copy of the provided frame's pixel data so that each can subsequently be modified without affecting each other. - - -### *gifFrame*.getPalette() -Get a summary of the colors found within the frame. The return value is an object of the following form: - -Property | Description ---- | --- -colors | An array of all the opaque colors found within the frame. Each color is given as an RGB number of the form 0xRRGGBB. The array is sorted by increasing number. Will be an empty array when the frame is completely transparent. -usesTransparency | boolean indicating whether there are any transparent pixels within the frame. A pixel is considered transparent if its alpha value is not 0xFF. -indexCount | The number of color indexes required to represent this palette of colors. It is equal to the number of opaque colors plus one if the frame includes transparency. - -**Returns**: object - An object representing a color palette as described above. ### *GifUtil*.cloneFrames(frames) @@ -507,7 +501,7 @@ write() encodes a GIF and saves it as a file. | Param | Type | Description | | --- | --- | --- | -| options | object | Optionally takes an objection whose only possible property is `transparentRGB`. Images are internally represented in RGBA format, where A is the alpha value of a pixel. When `transparentRGB` is provided, this RGB value is assigned to transparent pixels, which have alpha value 0x00. All other pixels have alpha value 0xFF. The RGB color of transparent pixels shouldn't matter for most applications. Defaults to 0x000000. | +| options | object | Optionally takes an objection whose only possible property is `transparentRGB`. Images are internally represented in RGBA format, where A is the alpha value of a pixel. When `transparentRGB` is provided, this RGB value (excluding alpha) is assigned to transparent pixels, which are also given alpha value 0x00. (All opaque pixels are given alpha value 0xFF). The RGB color of transparent pixels shouldn't matter for most applications. Defaults to 0x000000. | GifCodec is a class that both encodes and decodes GIFs. It implements both the `encode()` method expected of an encoder and the `decode()` method expected of a decoder, and it wraps the `omggif` GIF encoder/decoder package. GifCodec serves as this library's default encoder and decoder, but it's possible to wrap other GIF encoders and decoders for use by `gifwrap` as well. GifCodec will not encode GIFs with interlacing. @@ -527,7 +521,7 @@ Its constructor takes one option argument: | --- | --- | --- | | buffer | Buffer | Bytes of an encoded GIF to decode. | -Decodes a GIF from a Buffer to yield an instance of Gif. Transparent pixels of the GIF are given alpha values of 0x00, and opaque pixels are given alpha values of 0xFF. +Decodes a GIF from a Buffer to yield an instance of Gif. Transparent pixels of the GIF are given alpha values of 0x00, and opaque pixels are given alpha values of 0xFF. The RGB values of transparent pixels default to 0x000000 but can be overridden by the constructor's `transparentRGB` option. **Returns**: Promise - A Promise that resolves to an instance of the Gif class, representing the encoded GIF. @@ -543,7 +537,7 @@ Decodes a GIF from a Buffer to yield an instance of Gif. Transparent pixels of t | frames | [Array.<GifFrame>](#GifFrame) | Array of frames to encode | | spec | object | An optional object that may provide values for `loops` and `colorScope`, as defined for the Gif class. However, `colorSpace` may also take the value Gif.GlobalColorsPreferred (== 0) to indicate that the encoder should attempt to create only a global color table. `loop` defaults to 0, looping indefinitely, and `colorScope` defaults to Gif.GlobalColorsPreferred. | -Encodes a GIF from provided frames. Any pixel not having an alpha value of 0xFF renders as transparent within the encoding, while all pixels of alpha value 0xFF are opaque. +Encodes a GIF from provided frames. Each pixel having an alpha value of 0x00 renders as transparent within the encoding, while all pixels of non-zero alpha value render as opaque. **Returns**: Promise - A Promise that resolves to an instance of the Gif class, representing the encoded GIF. diff --git a/src/bitmapimage.js b/src/bitmapimage.js index ba45390..3224a12 100644 --- a/src/bitmapimage.js +++ b/src/bitmapimage.js @@ -22,7 +22,7 @@ class BitmapImage { * * When a `BitmapImage` is provided, the constructed `BitmapImage` is a deep clone of the provided one, so that each image's pixel data can subsequently be modified without affecting each other. * - * `backgroundRGBA` is an optional parameter representing a pixel as a single number. In hex, the number is as follows: 0xRRGGBBAA, where RR is the red byte, GG the green byte, BB, the blue byte, and AA the alpha value. An AA of 0xFF is considered opaque, and all other AA values are treated as transparent. + * `backgroundRGBA` is an optional parameter representing a pixel as a single number. In hex, the number is as follows: 0xRRGGBBAA, where RR is the red byte, GG the green byte, BB, the blue byte, and AA the alpha value. An AA of 0x00 is considered transparent, and all non-zero AA values are treated as opaque. */ constructor(...args) { @@ -117,7 +117,7 @@ class BitmapImage { /** * Fills the image with a single color. * - * @param {number} rgba Color with which to fill image, expressed as a singlenumber in the form 0xRRGGBBAA, where AA is 0xFF for opaque and any other value for transparent. + * @param {number} rgba Color with which to fill image, expressed as a singlenumber in the form 0xRRGGBBAA, where AA is 0x00 for transparent and any other value for opaque. * @return {BitmapImage} The present image to allow for chaining. */ @@ -143,7 +143,7 @@ class BitmapImage { * Property | Description * --- | --- * colors | An array of all the opaque colors found within the image. Each color is given as an RGB number of the form 0xRRGGBB. The array is sorted by increasing number. Will be an empty array when the image is completely transparent. - * usesTransparency | boolean indicating whether there are any transparent pixels within the image. A pixel is considered transparent if its alpha value is not 0xFF. + * usesTransparency | boolean indicating whether there are any transparent pixels within the image. A pixel is considered transparent if its alpha value is 0x00. * indexCount | The number of color indexes required to represent this palette of colors. It is equal to the number of opaque colors plus one if the image includes transparency. * * @return {object} An object representing a color palette as described above. @@ -156,7 +156,7 @@ class BitmapImage { let i = 0; let usesTransparency = false; while (i < buf.length) { - if (buf[i + 3] < 255) { + if (buf[i + 3] === 0) { usesTransparency = true; } else { @@ -180,7 +180,7 @@ class BitmapImage { } /** - * Gets the RGBA number of the pixel at the given coordinate in the form 0xRRGGBBAA, where AA is the alpha value, with 0xFF being opaque. + * Gets the RGBA number of the pixel at the given coordinate in the form 0xRRGGBBAA, where AA is the alpha value, with 0x00 being transparent. * * @param {number} x x-coord of pixel * @param {number} y y-coord of pixel @@ -220,7 +220,7 @@ class BitmapImage { * @param {number} yOffset The y-coord offset of the upper-left pixel of the desired image relative to the present image. * @param {number} width The width of the new image after reframing * @param {number} height The height of the new image after reframing - * @param {number} fillRGBA The color with which to fill space added to the image as a result of the reframing, in 0xRRGGBBAA format, where AA is 0xFF to indicate opaque and any other value to indicate transparent. This parameter is only required when the reframing exceeds the original boundaries (i.e. does not simply perform a crop). + * @param {number} fillRGBA The color with which to fill space added to the image as a result of the reframing, in 0xRRGGBBAA format, where AA is 0x00 to indicate transparent and a non-zero value to indicate opaque. This parameter is only required when the reframing exceeds the original boundaries (i.e. does not simply perform a crop). * @return {BitmapImage} The present image to allow for chaining. */ diff --git a/src/gifcodec.js b/src/gifcodec.js index 800c0be..3226d7b 100644 --- a/src/gifcodec.js +++ b/src/gifcodec.js @@ -27,7 +27,7 @@ class GifCodec * * Its constructor takes one option argument: * - * @param {object} options Optionally takes an objection whose only possible property is `transparentRGB`. Images are internally represented in RGBA format, where A is the alpha value of a pixel. When `transparentRGB` is provided, this RGB value is assigned to transparent pixels, which have alpha value 0x00. All other pixels have alpha value 0xFF. The RGB color of transparent pixels shouldn't matter for most applications. Defaults to 0x000000. + * @param {object} options Optionally takes an objection whose only possible property is `transparentRGB`. Images are internally represented in RGBA format, where A is the alpha value of a pixel. When `transparentRGB` is provided, this RGB value (excluding alpha) is assigned to transparent pixels, which are also given alpha value 0x00. (All opaque pixels are given alpha value 0xFF). The RGB color of transparent pixels shouldn't matter for most applications. Defaults to 0x000000. */ constructor(options = {}) { @@ -41,7 +41,7 @@ class GifCodec } /** - * Decodes a GIF from a Buffer to yield an instance of Gif. Transparent pixels of the GIF are given alpha values of 0x00, and opaque pixels are given alpha values of 0xFF. + * Decodes a GIF from a Buffer to yield an instance of Gif. Transparent pixels of the GIF are given alpha values of 0x00, and opaque pixels are given alpha values of 0xFF. The RGB values of transparent pixels default to 0x000000 but can be overridden by the constructor's `transparentRGB` option. * * @param {Buffer} buffer Bytes of an encoded GIF to decode. * @return {Promise} A Promise that resolves to an instance of the Gif class, representing the encoded GIF. @@ -82,7 +82,7 @@ class GifCodec } /** - * Encodes a GIF from provided frames. Any pixel not having an alpha value of 0xFF renders as transparent within the encoding, while all pixels of alpha value 0xFF are opaque. + * Encodes a GIF from provided frames. Each pixel having an alpha value of 0x00 renders as transparent within the encoding, while all pixels of non-zero alpha value render as opaque. * * @param {GifFrame[]} frames Array of frames to encode * @param {object} spec An optional object that may provide values for `loops` and `colorScope`, as defined for the Gif class. However, `colorSpace` may also take the value Gif.GlobalColorsPreferred (== 0) to indicate that the encoder should attempt to create only a global color table. `loop` defaults to 0, looping indefinitely, and `colorScope` defaults to Gif.GlobalColorsPreferred. @@ -302,7 +302,7 @@ function _getIndexedImage(frameIndex, frame, palette) { let i = 0, j = 0; while (i < colorBuffer.length) { - if (colorBuffer[i + 3] === 255) { + if (colorBuffer[i + 3] !== 0) { const color = (colorBuffer.readUInt32BE(i, true) >> 8) & 0xFFFFFF; // caller guarantees that the color will be in the palette indexBuffer[j] = colorToIndexFunc(colors, color); diff --git a/templates/README.hbs b/templates/README.hbs index b1a7b2d..9dc8328 100644 --- a/templates/README.hbs +++ b/templates/README.hbs @@ -60,7 +60,7 @@ Images are represented within a GifFrame exactly as they are in a `Jimp` image. * `frame.bitmap.height` - Height of image in pixels * `frame.bitmap.data` - A Node.js Buffer that can be accessed like an array of bytes. Every 4 adjacent bytes represents the RGBA values of a single pixel. These 4 bytes correspond to red, green, blue, and alpha, in that order. Each pixel begins at an index that is a multiple of 4. -GIFs do not support partial transparency, so within `frame.bitmap.data`, the pixels having alpha value 0xFF are treated as opaque and pixels of all other alpha values are treated as transparent. The encoder ignores the RGB values of transparent pixels. +GIFs do not support partial transparency, so within `frame.bitmap.data`, pixels having alpha value 0x00 are treated as transparent and pixels of non-zero alpha value are treated as opaque. The encoder ignores the RGB values of transparent pixels. `gifwrap` also provides utilities for reading GIF files and for parsing raw encodings: diff --git a/test/lib/bitmaps.js b/test/lib/bitmaps.js index 5fdfceb..fd9f8f9 100644 --- a/test/lib/bitmaps.js +++ b/test/lib/bitmaps.js @@ -7,7 +7,7 @@ exports.COLORS = { 'B': 0x0000FFff, // blue 'b': 0x0000FF7f, // blue half-alpha '*': 0x000000ff, // black - ' ': 0x00000000, // black transparent + ' ': 0x00000000, // fully transparent 'W': 0xFFFFFFff, // white '_': 0xFFFFFF01, // white transparent '4': 0x404040ff, // dark grey @@ -34,15 +34,15 @@ exports.PREMADE = { ], singleFrameNoColorTrans: [ - 'rrr', - 'rrr', - 'rrr' + ' ', + ' ', + ' ' ], singleFrameMonoTrans: [ - 'bGb', + ' G ', 'GGG', - 'bGb' + ' G ' ], singleFrameBWOpaque: [ @@ -58,7 +58,13 @@ exports.PREMADE = { singleFrameMultiTrans: [ 'RGB ', - '_RGB', + ' RGB', + ' *' + ], + + singleFrameMultiPartialTrans: [ + '_G ', + '__G ', 'rgb*' ], diff --git a/test/lib/tools.js b/test/lib/tools.js index b4fc356..d93038b 100644 --- a/test/lib/tools.js +++ b/test/lib/tools.js @@ -147,7 +147,7 @@ function _stringsToBitmap(stringPic, transparentRGB) { if (Bitmaps.COLORS[row[x]] !== undefined) { const color = Bitmaps.COLORS[row[x]]; const alpha = color & 0xff; - if (alpha === 255 || trans === undefined) { + if (alpha !== 0 || trans === undefined) { data[offset] = (color >> 24) & 0xff; data[offset + 1] = (color >> 16) & 0xff; data[offset + 2] = (color >> 8) & 0xff; diff --git a/test/test_bitmap.js b/test/test_bitmap.js index 9b8e47c..c0073fb 100644 --- a/test/test_bitmap.js +++ b/test/test_bitmap.js @@ -147,11 +147,11 @@ describe("BitmapImage palette", () => { it("includes multiple colors with transparency", (done) => { - const bitmap = Tools.getBitmap('singleFrameMultiTrans'); + const bitmap = Tools.getBitmap('singleFrameMultiPartialTrans'); const f = new BitmapImage(bitmap); const p = f.getPalette(); assert.deepStrictEqual(p.colors, - [0x000000, 0x0000ff, 0x00ff00, 0xff0000]); + [0x000000, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff]); assert.strictEqual(p.usesTransparency, true); done(); }); diff --git a/test/test_quantize.js b/test/test_quantize.js index 525a94c..8da6d47 100644 --- a/test/test_quantize.js +++ b/test/test_quantize.js @@ -213,7 +213,7 @@ function _seriesTest(method, specialColor) { for (let x = 0; x < width; ++x) { buf[bi] = x * 8; buf[bi + 1] = y * 8; - buf[bi + 3] = 0xff; + buf[bi + 3] = 255; bi += 4; } } @@ -226,7 +226,7 @@ function _seriesTest(method, specialColor) { for (let x = 0; x < width; ++x) { buf[bi] = x * 8 + 4; buf[bi + 1] = y * 8 + 4; - buf[bi + 3] = 0xff; + buf[bi + 3] = 255; bi += 4; } } @@ -238,7 +238,7 @@ function _seriesTest(method, specialColor) { for (let y = 0; y < height; ++y) { for (let x = 0; x < width; ++x) { if (x < width / 2) { - buf.writeUInt32BE(0xff, bi); + buf.writeUInt32BE(255, bi); } else { buf.writeUInt32BE(specialColor, bi);