Welcome!
Final Burn Neo => FBN Development => Topic started by: dink 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
-
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
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;
}