Reonarudo / pcb2photon

Image converter to .photon files used by the Anycubic's 3D UV Photon enabling it to produce UV PCB masks.
39 stars 4 forks source link

Some information about the UnknownArrayDef's #2

Closed Andoryuuta closed 6 years ago

Andoryuuta commented 6 years ago

Hi, I've been reverse-engineering this file format since yesterday and only found this repo today. Here is a bit of the information I have on the structure. In specific, the fstUnknownArrayDefStart and secUnknownArrayDefStart fields you have are offsets to structs describing the preview image data that gets displayed on the printer.

struct  PreviewHeader
{
  int width;
  int height;
  int dataOffset;
  int dataSize;
  __int64 unk_field_10; // Always set to 0 in caculateImageValidRange
  __int64 unk_field_18; // Always set to 0 in caculateImageValidRange

I haven't figured out the image format yet, but it seems like it might be something akin to ARGB1555. If you are using a dissassembler, you can look at caculateImageValidRange on the MacOS slicer binary (it has more debug symbols such as the aforementioned function name).

Snippet from caculateImageValidRange:

call    __ZNK6QImage5pixelEii ; QImage::pixel(int,int) // Get pixel from QT QImage
mov     ecx, eax
shr     ecx, 3
and     ecx, 1Fh
mov     edx, eax
shr     edx, 5
and     edx, 7C0h
or      edx, ecx
shr     eax, 8
and     eax, 0F800h
or      eax, edx
mov     [r15+r12*2], ax ; // r15=buffer, r12=index, *2 because its working on 16bit/2byte values
Rob2048 commented 6 years ago

Hi Andoryuuta, thanks to your disassembly there I was able to decode the image format.

The color of a pixel is 2 bytes (little endian) with each bit like this: RRRRR GGGGG X BBBBB If the X bit is set, then the next 2 bytes (little endian) masked with 0xFFF represents how many more times to repeat that pixel.

Reonarudo commented 6 years ago

Thank you! That is valuable information.

NardJ commented 6 years ago

Hi, good info! However I myself had no success decoding this info. Probably my fault. Am I correct that the vars called unknown8/9 in PhotonFileTemplate.bt contain the Width/Height of the first preview and unknown 14/15 the Width/Height from the second preview?

Rob2048 commented 6 years ago

@NardJ Yes, you are correct with the width/height. This is the javascript code I wrote to decode the images:

// Each image has header data near the top of the file.
let header = {
    width: d.getUint32(o + 0, true),
    height: d.getUint32(o + 4, true),
    data: d.getUint32(o + 8, true),
    size: d.getUint32(o + 12, true)
};

let img = new ArrayBuffer(header.width * header.height * 3);
let imgView = new Uint8Array(img);

o = header.data;
let j = 0;
let pixels = 0;

// Keep reading the image data until all data is consumed.
while (j < header.size) {
    let entry = d.getUint16(o + j, true);
    j += 2;

    let r = Math.floor(((entry >>> 11) & 0x1F) / 31 * 255);
    let g = Math.floor(((entry >>> 6) & 0x1F) / 31 * 255);
    let b = Math.floor(((entry >>> 0) & 0x1F) / 31 * 255);

    let repeat = 1;

    // Check for repeat bit.
    if (entry & 0x20) {
        let cmd = d.getUint16(o + j, true);
        j += 2;
        repeat += cmd & 0x0FFF;
    }

    // Assign pixel data to the image array.
    for (let i = 0; i < repeat; ++i) {
        imgView[pixels * 3 + 0] = r;
        imgView[pixels * 3 + 1] = g;
        imgView[pixels * 3 + 2] = b;
        ++pixels;
    }
}
X3msnake commented 6 years ago

@Rob2048 @Andoryuuta

Trying to get all hands working in one place, eventually integrating PCB2Photon in one multitool photon file edit swiss knife would be the best.

Check out https://github.com/NardJ/PhotonFileUtils

Already asked @NardJ to add @Reonarudo to the team there, drop a msg in the issues if you can help

NardJ commented 6 years ago

Thx, I followed this as template and it works perfect!

cheers, Nard

Op zo 17 jun. 2018 om 20:54 schreef Robert Gowans <notifications@github.com

:

@NardJ https://github.com/NardJ Yes, you are correct with the width/height. This is the javascript code I wrote to decode the images:

// Each image has header data near the top of the file.let header = { width: d.getUint32(o + 0, true), height: d.getUint32(o + 4, true), data: d.getUint32(o + 8, true), size: d.getUint32(o + 12, true) }; let img = new ArrayBuffer(header.width header.height 3);let imgView = new Uint8Array(img);

o = header.data;let j = 0;let pixels = 0; // Keep reading the image data until all data is consumed.while (j < header.size) { let entry = d.getUint16(o + j, true); j += 2;

let r = Math.floor(((entry >>> 11) & 0x1F) / 31 * 255);
let g = Math.floor(((entry >>> 6) & 0x1F) / 31 * 255);
let b = Math.floor(((entry >>> 0) & 0x1F) / 31 * 255);

let repeat = 1;

// Check for repeat bit.
if (entry & 0x20) {
    let cmd = d.getUint16(o + j, true);
    j += 2;
    repeat += cmd & 0x0FFF;
}

// Assign pixel data to the image array.
for (let i = 0; i < repeat; ++i) {
    imgView[pixels * 3 + 0] = r;
    imgView[pixels * 3 + 1] = g;
    imgView[pixels * 3 + 2] = b;
    ++pixels;
}

}

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Reonarudo/pcb2photon/issues/2#issuecomment-397898872, or mute the thread https://github.com/notifications/unsubscribe-auth/AK7bmKtL8ewgUWFmHN77-86tN_q51sbFks5t9qXugaJpZM4UZ56b .

Reonarudo commented 6 years ago

Also worked for me. I'm not sure if I should keep updating this repo if we are going to migrate to the PhotonFileUtils.