Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
fiahfy committed Nov 14, 2019
1 parent 0118666 commit 271e7f1
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 117 deletions.
67 changes: 42 additions & 25 deletions src/bitmap-info-header.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export class BitmapInfoHeader {
size: number
width: number
height: number
planes: number
bitCount: number
compression: number
sizeImage: number
xPelsPerMeter: number
yPelsPerMeter: number
clrUsed: number
clrImportant: number
readonly size: number
readonly width: number
readonly height: number
readonly planes: number
readonly bitCount: number
readonly compression: number
readonly sizeImage: number
readonly xPelsPerMeter: number
readonly yPelsPerMeter: number
readonly clrUsed: number
readonly clrImportant: number

constructor(
size = 40,
Expand Down Expand Up @@ -37,6 +37,37 @@ export class BitmapInfoHeader {
this.clrImportant = clrImportant
}

/**
* Create bitmap info header from the buffer.
* @param buffer The bitmap info header.
*/
static from(buffer: Buffer): BitmapInfoHeader {
const size = buffer.readUInt32LE(0)
const width = buffer.readInt32LE(4)
const height = buffer.readInt32LE(8)
const planes = buffer.readUInt16LE(12)
const bitCount = buffer.readUInt16LE(14)
const compression = buffer.readUInt32LE(16)
const sizeImage = buffer.readUInt32LE(20)
const xPelsPerMeter = buffer.readInt32LE(24)
const yPelsPerMeter = buffer.readInt32LE(28)
const clrUsed = buffer.readUInt32LE(32)
const clrImportant = buffer.readUInt32LE(36)
return new BitmapInfoHeader(
size,
width,
height,
planes,
bitCount,
compression,
sizeImage,
xPelsPerMeter,
yPelsPerMeter,
clrUsed,
clrImportant
)
}

get data(): Buffer {
const buffer = Buffer.alloc(40)
buffer.writeUInt32LE(this.size, 0)
Expand All @@ -52,18 +83,4 @@ export class BitmapInfoHeader {
buffer.writeUInt32LE(this.clrImportant, 36)
return buffer
}

set data(buffer) {
this.size = buffer.readUInt32LE(0)
this.width = buffer.readInt32LE(4)
this.height = buffer.readInt32LE(8)
this.planes = buffer.readUInt16LE(12)
this.bitCount = buffer.readUInt16LE(14)
this.compression = buffer.readUInt32LE(16)
this.sizeImage = buffer.readUInt32LE(20)
this.xPelsPerMeter = buffer.readInt32LE(24)
this.yPelsPerMeter = buffer.readInt32LE(28)
this.clrUsed = buffer.readUInt32LE(32)
this.clrImportant = buffer.readUInt32LE(36)
}
}
23 changes: 14 additions & 9 deletions src/ico-file-header.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
export class IcoFileHeader {
reserved: number
type: number
count: number
readonly reserved: number
readonly type: number
readonly count: number

constructor(reserved = 0, type = 1, count = 0) {
this.reserved = reserved
this.type = type
this.count = count
}

/**
* Create ICO file header from the buffer.
* @param buffer The ICO file header buffer.
*/
static from(buffer: Buffer): IcoFileHeader {
const reserved = buffer.readUInt16LE(0)
const type = buffer.readUInt16LE(2)
const count = buffer.readUInt16LE(4)
return new IcoFileHeader(reserved, type, count)
}

get data(): Buffer {
const buffer = Buffer.alloc(6)
buffer.writeUInt16LE(this.reserved, 0)
buffer.writeUInt16LE(this.type, 2)
buffer.writeUInt16LE(this.count, 4)
return buffer
}

set data(buffer) {
this.reserved = buffer.readUInt16LE(0)
this.type = buffer.readUInt16LE(2)
this.count = buffer.readUInt16LE(4)
}
}
44 changes: 25 additions & 19 deletions src/ico-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Bitmap } from 'jimp'
import { BitmapInfoHeader } from './bitmap-info-header'

export class IcoImage {
header: BitmapInfoHeader
xor: Buffer
and: Buffer
readonly header: BitmapInfoHeader
readonly xor: Buffer
readonly and: Buffer

constructor(
header = new BitmapInfoHeader(),
xor = Buffer.alloc(0),
Expand All @@ -14,32 +15,32 @@ export class IcoImage {
this.xor = xor
this.and = and
}
get data(): Buffer {
const list = [this.header.data, this.xor, this.and]
const totalLength = list.reduce((carry, buffer) => carry + buffer.length, 0)
return Buffer.concat(list, totalLength)
}
set data(buffer) {
this.header.data = buffer

/**
* Create ICO image from the buffer.
* @param buffer The ICO image buffer.
*/
static from(buffer: Buffer): IcoImage {
const header = BitmapInfoHeader.from(buffer)

// TODO: only 32 bpp supported
// no colors when bpp is 16 or more

let pos = this.header.data.length
const xorSize =
(((this.header.width * this.header.height) / 2) * this.header.bitCount) /
8
this.xor = buffer.slice(pos, pos + xorSize)
let pos = header.data.length
const xorSize = (((header.width * header.height) / 2) * header.bitCount) / 8
const xor = buffer.slice(pos, pos + xorSize)

pos += xorSize
const andSize =
((this.header.width +
(this.header.width % 32 ? 32 - (this.header.width % 32) : 0)) *
this.header.height) /
((header.width + (header.width % 32 ? 32 - (header.width % 32) : 0)) *
header.height) /
2 /
8
this.and = buffer.slice(pos, pos + andSize)
const and = buffer.slice(pos, pos + andSize)

return new IcoImage(header, xor, and)
}

static create(bitmap: Bitmap): IcoImage {
const width = bitmap.width
const height = bitmap.height * 2 // image + mask
Expand Down Expand Up @@ -99,4 +100,9 @@ export class IcoImage {

return new IcoImage(header, xor, and)
}

get data(): Buffer {
const buffers = [this.header.data, this.xor, this.and]
return Buffer.concat(buffers)
}
}
61 changes: 37 additions & 24 deletions src/ico-info-header.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export class IcoInfoHeader {
width: number
height: number
colorCount: number
reserved: number
planes: number
bitCount: number
bytesInRes: number
imageOffset: number
readonly width: number
readonly height: number
readonly colorCount: number
readonly reserved: number
readonly planes: number
readonly bitCount: number
readonly bytesInRes: number
readonly imageOffset: number

constructor(
width = 0,
Expand All @@ -28,6 +28,35 @@ export class IcoInfoHeader {
this.imageOffset = imageOffset
}

/**
* Create ICO info header from the buffer.
* @param buffer The ICO info header image buffer.
*/
static from(buffer: Buffer): IcoInfoHeader {
const width = buffer.readUInt8(0)
const height = buffer.readUInt8(1)
const colorCount = buffer.readUInt8(2)
const reserved = buffer.readUInt8(3)
const planes = buffer.readUInt16LE(4)
const bitCount = buffer.readUInt16LE(6)
const bytesInRes = buffer.readUInt32LE(8)
const imageOffset = buffer.readUInt32LE(12)
if (bitCount !== 32) {
// TODO: only 32 bpp supported
throw new Error('Only 32 bpp supported')
}
return new IcoInfoHeader(
width,
height,
colorCount,
reserved,
planes,
bitCount,
bytesInRes,
imageOffset
)
}

get data(): Buffer {
const buffer = Buffer.alloc(16)
buffer.writeUInt8(this.width, 0)
Expand All @@ -40,20 +69,4 @@ export class IcoInfoHeader {
buffer.writeUInt32LE(this.imageOffset, 12)
return buffer
}

set data(buffer) {
this.width = buffer.readUInt8(0)
this.height = buffer.readUInt8(1)
this.colorCount = buffer.readUInt8(2)
this.reserved = buffer.readUInt8(3)
this.planes = buffer.readUInt16LE(4)
this.bitCount = buffer.readUInt16LE(6)
this.bytesInRes = buffer.readUInt32LE(8)
this.imageOffset = buffer.readUInt32LE(12)

if (this.bitCount !== 32) {
// TODO: only 32 bpp supported
throw new Error('Only 32 bpp supported')
}
}
}
Loading

0 comments on commit 271e7f1

Please sign in to comment.