melianmiko / zmake

Unofficial ZeppOS build system, for Smart Band 7
https://melianmiko.ru/en/zmake/
GNU General Public License v3.0
36 stars 5 forks source link

If i use TGA-RGB it gives error #7

Closed emircanerkul closed 1 year ago

emircanerkul commented 1 year ago

I tested with TGA-P and TGA-RLP which works great but to lower bundle size I wanted to use TGA-RGB but it gives an error which not quite related with.

/Users/xxx/Projects/miband/zmake/dist/zmake/zmake .
__main__.py:103: DeprecationWarning: 'exec_' will be removed in the future. Use 'exec' instead.
INFO:zmake:We think that you want... build this project
INFO:zmake:-- Stage: Prepare
INFO:zmake:-- Stage: Process app.json
INFO:zmake:-- Stage: Convert assets
INFO:zmake:-- Stage: Common files, app.js
INFO:zmake:-- Stage: Build app.js
INFO:zmake:Use our app.js template, because they don't exist in proj <<<<<< THIS IS THE NEW LIKE
INFO:zmake:-- Stage: Build page from src/lib
INFO:zmake:-- Stage: Process exiting pages
INFO:zmake:-- Stage: Post-processing JS files
INFO:zmake:-- Stage: Preview
INFO:zmake:Skip, disabled
INFO:zmake:-- Stage: Package BIN and ZIP
INFO:zmake:-- Stage: Make ZEUS package
INFO:zmake:-- Stage: ADB Install
INFO:zmake:Skip, disabled
INFO:zmake:Completed without error.

And are there any option to not use any compression? Because I already compressed my images which 1000% more efficient (I know might not compatible but want to see with my eyes who knows may works..)

melianmiko commented 1 year ago

Hi, There's no TGA-RGB option, there's only TGA-16 and TGA-32 variants only. It's a mistake in my docs =)

Also, you're using an outdated version of ZMake. In latest release there's an auto_rgba option which automatically selects target format between TGA-P and TGA-32, to store all color data without compression.

emircanerkul commented 1 year ago

Oh, okay, TGA-16 worked great, but my custom compression is well more than that. Basically, this enlarges my file sizes. Can't I disable it? To make use of my asset as is

melianmiko commented 1 year ago

What do you mean to disable?

ZeppOS uses their own TGA--based graphics format, so all assets should be converted to one of them. There's no way to use plain PNG's in their.

emircanerkul commented 1 year ago

Zmake should not preprocess/compress/resize etc my images.

With these tools, i resize my image into 5kb but zmake turns these into almost 100kb after extracting to bin zip

  convert -resize 192 "$file" "${path}/${filename}.png"
  zopflipng -y --lossy_transparent --lossy_8bit --splitting=2 --iterations=100 "$file" "$file"
melianmiko commented 1 year ago

preprocess/compress/resize

ZMake didn't do anything of that...

TGA is very simple format. When PNG/JPEG allows to use a good compression algorithms, like Deflate, TGA didn't support anything of that, except RLP which you already know.

TGA is more similar with BMP, only things that make sense in file size is color depth and image resolution. For example, image in TGA-P will be a file of 64 + (4 * count_of_colors) + (width * height) bytes. And there's no way to reduce that size, except of use TGA-RLP.

And similar TGA-32 means that each pixel was described with 4 bytes, and output file will be of 64 + (4 * width * height) bytes length. And there's no way to reduce that size.

emircanerkul commented 1 year ago

If so, why do I see my images like 100kb after extracting the bin zip? It should be 5kb because my image is 5kb as original file size. I assume the watch also has to extract the bin zip while installing the app. We have really limited memory like 30mb.

melianmiko commented 1 year ago

Read my previous message again. You applied a bucket of compressions to your PNG, but TGA didn't support any of them.

I don't want to waste my time in attempts to explain that.

emircanerkul commented 1 year ago

@melianmiko you're right. I disabled it manually in zmake source code yep sure watch does not show images :) I came up with this idea but I lack knowledge and couldn't find any code online to turn compressed images into tga in runtime. We have fs. In runtime I'll read my compressed image and save as tga then refresh the pages. Which saves around 170mb. I have to do such way because I have huge image set and wanted to include all.

emircanerkul commented 1 year ago

To put in history.

The idea works but the device CPU power is not enough to convert png to tga in watch 7


import { decode } from '@stevebel/png';
var Buffer = require('buffer/').Buffer

    const png = decode(new Uint8Array(FsUtils.read("/pages/p1.0.xpng")));
    const pixelCount = png.width * png.height;
    const tgaBuffer = Buffer.alloc(Math.ceil(pixelCount / 4) + 18);

    let tgaIndex = 18;
    let tgaByte = 0;
    let bitOffset = 6;

    for (let i = 0; i < pixelCount; i++) {
      const pngIndex = i << 2; // RGBA index in PNG data

      // Compress RGBA to 2-bit palette index
      const r = png.data[pngIndex];
      const g = png.data[pngIndex + 1];
      const b = png.data[pngIndex + 2];
      const paletteIndex = ((r & 0x80) >> 6) | ((g & 0x80) >> 7) | ((b & 0x80) >> 5);

      // Write palette index to TGA buffer
      tgaByte |= paletteIndex << bitOffset;

      // Move to the next byte or flush if all bits are filled
      if (bitOffset === 0) {
        tgaBuffer[tgaIndex++] = tgaByte;
        tgaByte = 0;
        bitOffset = 6;
      } else {
        bitOffset -= 2;
      }
    }

    // Flush any remaining bits
    if (bitOffset !== 6) {
      tgaBuffer[tgaIndex] = tgaByte;
    }

    tgaBuffer.writeUInt8(0, 0); // ID Length
    tgaBuffer.writeUInt8(0, 1); // Color Map Type
    tgaBuffer.writeUInt8(3, 2); // Image Type (Uncompressed Black-and-White Image)
    tgaBuffer.writeUInt16LE(0, 3); // Color Map Specification
    tgaBuffer.writeUInt16LE(0, 5); // Origin X
    tgaBuffer.writeUInt16LE(0, 7); // Origin Y
    tgaBuffer.writeUInt16LE(png.width, 12); // Image Width
    tgaBuffer.writeUInt16LE(png.height, 14); // Image Height
    tgaBuffer.writeUInt8(2, 16); // Pixel Depth
    tgaBuffer.writeUInt8(0x20, 17); // Image Descriptor (Top-left origin)

    const f = FsUtils.open("/temp.png", hmFS.O_WRONLY | hmFS.O_CREAT);
    result = hmFS.write(f, tgaBuffer, 0, tgaBuffer.byteLength);
    hmFS.close(f);

    this.view = hmUI.createWidget(hmUI.widget.IMG, {
      x: 10,
      y: 20,
      w: 172,
      h: 450,
      src: "temp.png",
    });