Skip to content

Horizontal bar in all images after certain images #42

@mockthebear

Description

@mockthebear

Describe the bug
Having two images. Image A and image B.
Decode image A, it will be perfect. Decode image B, then B will have a red vertical bar all over its extension.
Invert the order, B then A, is all fine. Its seems to be some issue in image A that leaks trough the decompressor.

To Reproduce
Steps to reproduce the behavior:

  1. Get an esp32s3 with an SD card (Might be still happening between other esps).
    Use a code like this. Happens with any code, just providing the one i used)
#include <Arduino.h>
#include <SD.h>
#include <PNGdec.h>
#include "SPI.h"
#include <string>


#define SPI_CS 38
#define SPI_MOSI 14
#define SPI_MISO 47
#define SPI_SCK 21
#define SPI_MAX_CLOCK (80 * 1000 * 1000)

#define PANEL_WIDTH 64
#define PANEL_HEIGHT 32
#define FILE_PIXEL_COUNT PANEL_WIDTH * PANEL_HEIGHT
#define FILE_SIZE_BULK_SIZE ( FILE_PIXEL_COUNT * sizeof(uint16_t) )

File getFile(const char *name){
  File myFile = SD.open(name);
  return myFile;
}  

uint16_t* tmpBuffer;
File pngDecFile;
PNG png;

void * myOpen(const char *filename, int32_t *size) {
  pngDecFile = SD.open(filename);
  *size = pngDecFile.size();
  return &pngDecFile;
}
void myClose(void *handle) {
  if (pngDecFile) pngDecFile.close();
}
int32_t myRead(PNGFILE *handle, uint8_t *buffer, int32_t length) {
  if (!pngDecFile) return 0;
  return pngDecFile.read(buffer, length);
}
int32_t mySeek(PNGFILE *handle, int32_t position) {
  if (!pngDecFile) return 0;
  return pngDecFile.seek(position);
}

// Function to draw pixels to the display
int PNGDraw(PNGDRAW *pDraw) {
  static uint16_t raw[128];
  png.getLineAsRGB565(pDraw, raw, PNG_RGB565_LITTLE_ENDIAN, 0xffffffff);
  memcpy(tmpBuffer + (pDraw->y *pDraw->iWidth), raw, pDraw->iWidth * sizeof(uint16_t));
  return 1;
}


uint16_t *DecodePNGForBuffer(const char *name, int& rcError){
  auto fp = getFile(name);
  if (!fp){
    rcError = 998;
    return nullptr;
  }
  fp.close();

  rcError = png.open(name, myOpen, myClose, myRead, mySeek, PNGDraw);
  if (rcError != PNG_SUCCESS) {
    return nullptr;
  }
   Serial.printf("File is size %d %d\n", png.getWidth(), png.getHeight());
  if (png.getWidth() != PANEL_WIDTH && png.getHeight() != PANEL_HEIGHT){
    Serial.printf("Mismatched image size, expected %d %d but got %d %d", PANEL_WIDTH, PANEL_HEIGHT, png.getWidth(), png.getHeight());
    png.close();
    rcError = 999;
    return nullptr;
  }
 
  tmpBuffer = (uint16_t*)ps_malloc(FILE_SIZE_BULK_SIZE );
  png.decode(NULL, 0);
  png.close();
  int x = 0;
  int y = 0;
  Serial.printf("[00]=");
  for (int i=0;i<FILE_SIZE_BULK_SIZE;i++){
    uint16_t color = tmpBuffer[i];
    Serial.printf("%05d,", color);
    x++;
    if (x > PANEL_WIDTH){
      x = 0;
      y++;
      Serial.printf("\n[%02d]=", y);
    }
  }
  Serial.printf("\n\n\nFinished file: %s!\n", name);
  return tmpBuffer;
}

void setup() {
  
  Serial.begin(115200);
  SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI, SPI_CS);
  SPI.setFrequency(SPI_MAX_CLOCK);
  Serial.println("Initializing SD card...");
  if(!SD.begin(SPI_CS, SPI, SPI_MAX_CLOCK, "/sd", 10)){
      return;
  }   
  Serial.println("SD OK!");


  int error;
  uint16_t *buffA = DecodePNGForBuffer("/imagea.png", error);
  uint16_t *buffB = DecodePNGForBuffer("/imageb.png", error);


}


void loop() {}

Flash it, and load those two images in to the SD card:

Image Image

https://dogurai.com/imagea.png
https://dogurai.com/imageb.png
Or here as zip:

images.zip

Checking the console will output the image pixels, those are 64x32 pixel images.
You will see this o the first lines of the imageb

Finished file: /expressions/imagec.png!
File is size 64 32
[00]=00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,00000,63488,00000,

That 63488 was'nt supposed to be there, it happens on the same row of every single line. Sometimes taking 4 rows, sometimes taking one.

Image

Expected behavior

No red line visible

Image you're having trouble with
https://dogurai.com/imagea.png
https://dogurai.com/imageb.png

Additional context

I hosted the images in a site i own so you can download without any tool compressing it in any way. I know its a encoding related issue, because loading the image using mspaint, editing any pixel and saving again solve the issue.

The original image as edited using paintnet, but i saw this happening with some images done by phone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions