Files
Cluster/insDavi2.0/src/lib/InsPng.c
2026-04-17 18:22:45 +08:00

165 lines
3.6 KiB
C

#include <lib/InsPng.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <zlib.h>
#include <png.h>
#include <pngstruct.h>
#include <pnginfo.h>
typedef struct Struct_MemPng
{
UInt08 *data;
Int32 size;
Int32 offset;
} MemPng;
static void callback_ReadMemPng(png_structp ptrPng, png_bytep data, png_size_t length)
{
MemPng *mPngSrc = (MemPng*)ptrPng->io_ptr;
if(mPngSrc == NULL)
{
png_error(ptrPng, "not mem png source define");
}
else if(mPngSrc->offset + length <= mPngSrc->size)
{
memcpy(data, mPngSrc->data+mPngSrc->offset, length);
mPngSrc->offset += length;
}
else
{
png_error(ptrPng, "more mem png data is needed");
}
}
/*RGB888 only*/
Bool LoadPngFromMem(void *mem, UInt32 memSz, Int32 *width, Int32 *height, UInt32 *format, void **bmp, UInt32 bmpSize)
{
Int32 i, j, w, h, type;
UInt32 fmt;
MemPng mSrc =
{
.data = mem,
.size = memSz,
.offset = 0
};
UInt08 *buff;
#define GL_RGB 0x1907
#define GL_RGBA 0x1908
png_structp ptrPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if(ptrPng == 0)return INS_FALSE;
png_infop ptrInfo = png_create_info_struct(ptrPng);
if(ptrInfo == 0)
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
if(setjmp(png_jmpbuf(ptrPng)))
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
png_set_read_fn(ptrPng, &mSrc, callback_ReadMemPng);
png_read_png(ptrPng, ptrInfo, PNG_TRANSFORM_EXPAND, 0);
w = ptrInfo->width;
h = ptrInfo->height;
// depth = ptrInfo->pixel_depth;
png_bytep *PtrRow = png_get_rows(ptrPng, ptrInfo);
type = ptrInfo->color_type;
switch(type)
{
case PNG_COLOR_TYPE_RGB:
if(bmp[0] != NULL && bmpSize > 0)
{
if(w*h*3 > bmpSize)
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
}
else if(bmp[0] == NULL)
{
bmp[0] = malloc(w*h*3);
}
else
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
buff = bmp[0];
fmt = GL_RGB;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
buff[3*((h-1-i)*w+j)+0] = PtrRow[i][3*j+0];
buff[3*((h-1-i)*w+j)+1] = PtrRow[i][3*j+1];
buff[3*((h-1-i)*w+j)+2] = PtrRow[i][3*j+2];
}
}
break;
case PNG_COLOR_TYPE_RGBA:
if(bmp[0] != NULL && bmpSize > 0)
{
if(w*h*4 > bmpSize)
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
}
else if(bmp[0] == NULL)
{
bmp[0] = malloc(w*h*4);
}
else
{
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
buff = bmp[0];
fmt = GL_RGBA;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
buff[4*((h-1-i)*w+j)+0] = PtrRow[i][4*j+0];
buff[4*((h-1-i)*w+j)+1] = PtrRow[i][4*j+1];
buff[4*((h-1-i)*w+j)+2] = PtrRow[i][4*j+2];
buff[4*((h-1-i)*w+j)+3] = PtrRow[i][4*j+3];
}
}
break;
default:
png_destroy_read_struct(&ptrPng, 0, 0);
return INS_FALSE;
}
*width = w;
*height = h;
*format = fmt;
return INS_TRUE;
}