Skip to content

Horizontal bar in all images after certain images persists #49

Description

@mockthebear

Aparently I cannot repoen the issue #42
So i'm creating another one addressing the same issue at #42

I just tried the changes at master.
Still got the line there.
And bringing new insight:

  delete []png;
  png = (PNG*)ps_malloc(sizeof(PNG));

Doing this every time I decode a PNG dont fix it. Aparently is a poisoning in some static allocated variable?
At first i tought might be something beeing written in any of those order[19], lbase, lext, dbase or dext. But even changing them to const and removing the static the behavior persists.

Honestly, I don't know whats going on :(

And yes, the change is present:

#if ((INTPTR_MAX == INT64_MAX) || defined(HAL_ESP32_HAL_H_) || defined(TEENSYDUINO) || defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7)) && !defined(ARDUINO_ARCH_RP2040)
//#define ALLOWS_UNALIGNED
#endif

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:

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 (40 * 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=nullptr;

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();


  png = new PNG;

  rcError = png->open(name, myOpen, myClose, myRead, mySeek, PNGDraw);
  if (rcError != PNG_SUCCESS) {
    delete png;
    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;
    delete png;
    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);
  delete png;
  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