Attempt to reproduce the format of the original bitmap packet

This commit is contained in:
MultiMote 2024-10-20 17:27:19 +03:00
parent 8a62605876
commit a37f8a67de
2 changed files with 69 additions and 35 deletions

@ -153,9 +153,7 @@ export class PacketGenerator {
}
public static setPrintQuantity(quantity: number): NiimbotPacket {
return new NiimbotPacket(RequestCommandId.PrintQuantity, [
...Utils.u16ToBytes(quantity)
]);
return new NiimbotPacket(RequestCommandId.PrintQuantity, [...Utils.u16ToBytes(quantity)]);
}
public static printStatus(): NiimbotPacket {
@ -226,37 +224,51 @@ export class PacketGenerator {
return packet;
}
public static printBitmapRow(pos: number, repeats: number, data: Uint8Array): NiimbotPacket {
const blackPixelCount: number = Utils.countSetBits(data);
public static printBitmapRow(
pos: number,
repeats: number,
data: Uint8Array,
printheadPixels?: number
): NiimbotPacket {
const { total, a, b, c } = Utils.countPixelsForBitmapPacket(data, printheadPixels ?? 0);
// Black pixel count. Not sure what role it plays in printing.
// There is two formats of this part
// 1. <count> <count> <count> (sum must equals number of pixels, every number calculated by algorithm based on printhead resolution)
// 2. <0> <countH> <countL> (big endian)
let header: number[] = [0, ...Utils.u16ToBytes(total)];
if (printheadPixels !== undefined) {
header = [a, b, c];
}
const packet = new NiimbotPacket(RequestCommandId.PrintBitmapRow, [
...Utils.u16ToBytes(pos),
// Black pixel count. Not sure what role it plays in printing.
// There is two formats of this part
// 1. <count> <count> <count> (sum must equals number of pixels, every number calculated by algorithm based on printhead resolution)
// 2. <0> <countH> <countL> (big endian)
0,
...Utils.u16ToBytes(blackPixelCount),
...header,
repeats,
...data,
]);
packet.oneWay = true;
return packet;
}
/** Printer powers off if black pixel count > 6 */
public static printBitmapRowIndexed(pos: number, repeats: number, data: Uint8Array): NiimbotPacket {
const blackPixelCount: number = Utils.countSetBits(data);
// 5555 83 0e 007e 000400 01 0027 0028 0029 002a fa aaaa
public static printBitmapRowIndexed(pos: number, repeats: number, data: Uint8Array, printheadPixels?: number): NiimbotPacket {
const { total, a, b, c } = Utils.countPixelsForBitmapPacket(data, printheadPixels ?? 0);
const indexes: Uint8Array = ImageEncoder.indexPixels(data);
if (blackPixelCount > 6) {
throw new Error(`Black pixel count > 6 (${blackPixelCount})`);
if (total > 6) {
throw new Error(`Black pixel count > 6 (${total})`);
}
let header: number[] = [0, ...Utils.u16ToBytes(total)];
if (printheadPixels !== undefined) {
header = [a, b, c];
}
const packet = new NiimbotPacket(RequestCommandId.PrintBitmapRowIndexed, [
...Utils.u16ToBytes(pos),
0,
...Utils.u16ToBytes(blackPixelCount),
...header,
repeats,
...indexes,
]);
@ -273,13 +285,13 @@ export class PacketGenerator {
return new NiimbotPacket(RequestCommandId.WriteRFID, data);
}
public static writeImageData(image: EncodedImage): NiimbotPacket[] {
public static writeImageData(image: EncodedImage, printheadPixels?: number): NiimbotPacket[] {
return image.rowsData.map((p: ImageRow) => {
if (p.dataType === "pixels") {
if (p.blackPixelsCount > 6) {
return this.printBitmapRow(p.rowNumber, p.repeat, p.rowData!);
return this.printBitmapRow(p.rowNumber, p.repeat, p.rowData!, printheadPixels);
} else {
return this.printBitmapRowIndexed(p.rowNumber, p.repeat, p.rowData!);
return this.printBitmapRowIndexed(p.rowNumber, p.repeat, p.rowData!, printheadPixels);
}
} else {
return this.printEmptySpace(p.rowNumber, p.repeat);

@ -15,7 +15,7 @@ export class Utils {
if (!match) {
return new Uint8Array();
}
return new Uint8Array(
match.map((h) => {
return parseInt(h, 16);
@ -39,23 +39,45 @@ export class Utils {
return new TextDecoder().decode(arr);
}
/** Count non-zero bits in the byte array */
public static countSetBits(arr: Uint8Array): number {
// not so efficient, but readable
let count: number = 0;
/**
* Count non-zero bits in the byte array
*
* Not efficient, but readable.
*
* The algorithm is obtained by reverse engineering and I don't understand what's going on here.
*
* Sometimes these values match original packets, sometimes not.
**/
public static countPixelsForBitmapPacket(
arr: Uint8Array,
printheadSize: number
): { total: number; a: number; b: number; c: number } {
let total: number = 0;
let a: number = 0;
let b: number = 0;
let c: number = 0;
let xPos: number = 0;
arr.forEach((value) => {
// shift until value becomes zero
while (value > 0) {
// check last bit
if ((value & 1) === 1) {
count++;
const printheadSizeDiv3: number = printheadSize / 3;
arr.forEach((value: number) => {
//for (let bitN = 0; bitN < 8; bitN++) {
for (let bitN: number = 7; bitN >= 0; bitN--) {
const isBlack: boolean = (value & (1 << bitN)) !== 0;
if (isBlack) {
if (xPos < printheadSizeDiv3) {
a++;
} else if (xPos < printheadSizeDiv3 * 2) {
b++;
} else {
c++;
}
total++;
}
value >>= 1;
xPos++;
}
});
return count;
return { total, a, b, c };
}
/** Big endian */