#include #include #include #include #include #include #include #include #include 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; }