msagent.js/core: Rewrite imageDrawToBuffer()
Now rows are not read and it doesn't use a BufferStream at all. Probably inconsequential for performance or memory usage but it's a cleaner way to implement it.
This commit is contained in:
parent
02a26109c0
commit
883ef7357c
1 changed files with 6 additions and 21 deletions
|
@ -1,4 +1,5 @@
|
||||||
import { AcsImageEntry } from './structs/image';
|
import { AcsImageEntry } from './structs/image';
|
||||||
|
import { RGBAColor } from './structs/core';
|
||||||
|
|
||||||
// probably should be in a utility module
|
// probably should be in a utility module
|
||||||
function dwAlign(off: number): number {
|
function dwAlign(off: number): number {
|
||||||
|
@ -10,9 +11,6 @@ function dwAlign(off: number): number {
|
||||||
return ul;
|
return ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { BufferStream, SeekDir } from './buffer';
|
|
||||||
import { RGBAColor } from './structs/core';
|
|
||||||
|
|
||||||
/// Draws an ACS image to a newly allocated buffer.
|
/// Draws an ACS image to a newly allocated buffer.
|
||||||
/// This function normalizes the agent 8bpp DIB format to a saner RGBA format,
|
/// This function normalizes the agent 8bpp DIB format to a saner RGBA format,
|
||||||
/// that can be directly converted to an ImageData for drawing to a web canvas.
|
/// that can be directly converted to an ImageData for drawing to a web canvas.
|
||||||
|
@ -20,30 +18,17 @@ import { RGBAColor } from './structs/core';
|
||||||
/// However, that should be done (and is done) by a higher level web layer.
|
/// However, that should be done (and is done) by a higher level web layer.
|
||||||
export function imageDrawToBuffer(imageEntry: AcsImageEntry, palette: RGBAColor[]) {
|
export function imageDrawToBuffer(imageEntry: AcsImageEntry, palette: RGBAColor[]) {
|
||||||
let rgbaBuffer = new Uint32Array(imageEntry.image.width * imageEntry.image.height);
|
let rgbaBuffer = new Uint32Array(imageEntry.image.width * imageEntry.image.height);
|
||||||
|
|
||||||
let buffer = imageEntry.image.data;
|
let buffer = imageEntry.image.data;
|
||||||
let bufStream = new BufferStream(buffer);
|
|
||||||
|
|
||||||
let rows = new Array<Uint8Array>(imageEntry.image.height - 1);
|
|
||||||
|
|
||||||
// Read all the rows bottom-up first. This idiosyncracy is due to the fact
|
|
||||||
// that the bitmap data is actually formatted to be used as a GDI DIB
|
|
||||||
// (device-independent bitmap), so it inherits all the strange baggage from that.
|
|
||||||
for (let y = imageEntry.image.height - 1; y >= 0; --y) {
|
|
||||||
let row = bufStream.subBuffer(imageEntry.image.width).raw();
|
|
||||||
rows[y] = row.slice(0, imageEntry.image.width);
|
|
||||||
|
|
||||||
// Seek to the next DWORD aligned spot to get to the next row.
|
|
||||||
// For most images this may mean not seeking at all.
|
|
||||||
bufStream.seek(dwAlign(bufStream.tell()), SeekDir.BEG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, draw the rows converted to RGBA, top down (so it's drawn correctly,
|
// Next, draw the rows converted to RGBA, top down (so it's drawn correctly,
|
||||||
// and in the RGBA format we want to return)
|
// and in the RGBA format we want to return)
|
||||||
for (let y = 0; y < imageEntry.image.height - 1; ++y) {
|
for (let y = 0; y < imageEntry.image.height - 1; ++y) {
|
||||||
let row = rows[y];
|
// flip y so it's all top down properly
|
||||||
|
let yy = imageEntry.image.height - 1 - y;
|
||||||
|
let rowStartOffset = yy * dwAlign(imageEntry.image.width);
|
||||||
|
|
||||||
for (let x = 0; x < imageEntry.image.width; ++x) {
|
for (let x = 0; x < imageEntry.image.width; ++x) {
|
||||||
rgbaBuffer[y * imageEntry.image.width + x] = palette[row[x]].to_rgba();
|
rgbaBuffer[y * imageEntry.image.width + x] = palette[buffer[rowStartOffset + x]].to_rgba();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rgbaBuffer;
|
return rgbaBuffer;
|
||||||
|
|
Loading…
Reference in a new issue