Author Topic: Need awesome coder!  (Read 379 times)

Offline dink

  • Administrator
  • *****
  • Posts: 3139
  • Karma: +259/-0
  • side effects: new or worsening heart failure
Need awesome coder!
« on: July 17, 2019, 12:16:58 AM »
Hi guys,
Need help from someone that is awesome at code.  Even good at code will do :) 
What's needed:  Titles and Previews images are getting insanely plentiful.  It would be nice if they could reside in a .zip file instead of a directory of 12000 titles and directory of 12000 preview images (.png)

Problem is, by default Libpng only loads png files from a file handle.
We need to be able to load a png file from a memory buffer.  In FBN source, see src/burner/image.cpp.
Google: libpng load from memory
Warning: it's a bit complex :P

we need a memory analog of the following functions - replacing "FILE *fp" with "UINT8 *buffer, INT32 buffersize"
INT32 PNGLoad(IMAGE* img, FILE* fp, INT32 nPreset);
INT32 PNGGetInfo(IMAGE* img, FILE *fp);
and
bool PNGIsImage(FILE* fp);

example prototypes:
INT32 PNGLoad(IMAGE* img, UINT8 *buffer, INT32 buffersize, INT32 nPreset);
INT32 PNGGetInfo(IMAGE* img, UINT8 *buffer, INT32 buffersize);
bool PNGIsImage(UINT8 *buffer, INT32 buffersize);

buffer points to png data memory blob, buffersize is png data size.

With this, I'd be happy to hook up the rest - unless you'd like to also :)

p.s. temp file route is NOT an option :P
p.p.s: google: libpng load from memory

best regards,
- dink
« Last Edit: July 17, 2019, 09:55:22 AM by dink »

Offline Kev

  • FBA Dev
  • ******
  • Posts: 120
  • Karma: +1/-0
Re: Need awesome coder!
« Reply #1 on: July 17, 2019, 12:53:47 PM »
I've not tested it yet and might not be able to for a few days but according to https://klein-hu.github.io/tips/tools/libpng/png/2018/11/07/libpng.html this might do it. It does need to know the buffer size though but that can be worked around i'm sure.   Ignore that bit lol

Code: [Select]


static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
{
ImageSource* isource = (ImageSource*)png_get_io_ptr(png_ptr);

if (isource->offset + length <= isource->size)
{
memcpy(data, isource->data + isource->offset, length);
isource->offset += length;
}
else
png_error(png_ptr, "pngReaderCallback failed");
}


INT32 PNGLoadBuffer(IMAGE* img, unsigned char* buffer, int bufferLength, INT32 nPreset)
{
IMAGE temp_img;
png_uint_32 width = 0, height = 0;
INT32 bit_depth, color_type;

if (png_sig_cmp(buffer, 0, PNG_SIG_CHECK_BYTES)) {
return 1;
}

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
return 1;
}

png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return 1;
}

ImageSource imgsource;
imgsource.data = buffer;
imgsource.size = bufferLength;
imgsource.offset = 0;
png_set_read_fn(png_ptr, &imgsource, pngReadCallback);
   
memset(&temp_img, 0, sizeof(IMAGE));
png_set_sig_bytes(png_ptr, PNG_SIG_CHECK_BYTES);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
return 1;
}

// Instruct libpng to convert the image to 24-bit RGB format
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
png_set_gray_to_rgb(png_ptr);
}
if (bit_depth == 16) {
png_set_strip_16(png_ptr);
}
if (color_type & PNG_COLOR_MASK_ALPHA) {
png_set_strip_alpha(png_ptr);
}

temp_img.width = width;
temp_img.height = height;

// Initialize our img structure
if (img_alloc(&temp_img)) {
//longjmp(png_ptr->jmpbuf, 1);
png_jmpbuf(png_ptr);
}

// If bad things happen in libpng we need to do img_free(&temp_img) as well
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
img_free(&temp_img);
return 1;
}

// Read the .PNG image
png_set_bgr(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_read_image(png_ptr, temp_img.rowptr);
png_read_end(png_ptr, (png_infop)NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);


if (img_process(&temp_img, img->width ? img->width : temp_img.width, img->height ? img->height : temp_img.height, nPreset, false)) {
img_free(&temp_img);
return 1;
}

bPngImageOrientation = 0;
if (height && width && height > width) bPngImageOrientation = 1;

memcpy(img, &temp_img, sizeof(IMAGE));

return 0;
}




INT32 PNGGetInfoBuffer(IMAGE* img, unsigned char* buffer, int bufferLength)
{
IMAGE temp_img;
png_uint_32 width = 0, height = 0;
INT32 bit_depth, color_type;

if (png_sig_cmp(buffer, 0, PNG_SIG_CHECK_BYTES)) {
return 1;
}

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
return 1;
}

png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return 1;
}

ImageSource imgsource;
imgsource.data = buffer;
imgsource.size = bufferLength;
imgsource.offset = 0;
png_set_read_fn(png_ptr, &imgsource, pngReadCallback);

memset(&temp_img, 0, sizeof(IMAGE));

png_set_sig_bytes(png_ptr, PNG_SIG_CHECK_BYTES);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
return 1;
}

temp_img.width = width;
temp_img.height = height;

if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
return 1;
}

png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);


memcpy(img, &temp_img, sizeof(IMAGE));
img_free(&temp_img);

return 0;
}