add oversampler
This commit is contained in:
375
oversampling/WDL/lice/lice_png.cpp
Normal file
375
oversampling/WDL/lice/lice_png.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_png.cpp (PNG loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include "lice.h"
|
||||
|
||||
#include "../wdltypes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../libpng/png.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h> // for loading images from embedded resource
|
||||
#endif
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadPNG(const char *filename, LICE_IBitmap *bmp)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
#if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
|
||||
#ifdef WDL_SUPPORT_WIN9X
|
||||
if (GetVersion()<0x80000000)
|
||||
#endif
|
||||
{
|
||||
WCHAR wf[2048];
|
||||
if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048))
|
||||
fp = _wfopen(wf,L"rb");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fp) fp = WDL_fopenA(filename,"rb");
|
||||
if (!fp) return 0;
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!png_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if(!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
unsigned int width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_method;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
//convert whatever it is to RGBA
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
{
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
color_type |= PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
else
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
|
||||
if (bmp) bmp->resize(width,height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height)
|
||||
{
|
||||
delete delbmp;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));;
|
||||
LICE_pixel *srcptr = bmp->getBits();
|
||||
int dsrcptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
srcptr += dsrcptr*(bmp->getHeight()-1);
|
||||
dsrcptr=-dsrcptr;
|
||||
}
|
||||
unsigned int i;
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
row_pointers[i]=(unsigned char *)srcptr;
|
||||
srcptr+=dsrcptr;
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
fclose(fp);
|
||||
|
||||
#if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3)
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
unsigned char *bp = row_pointers[i];
|
||||
int j=width;
|
||||
while (j-->0)
|
||||
{
|
||||
unsigned char a = bp[0];
|
||||
unsigned char r = bp[1];
|
||||
unsigned char g = bp[2];
|
||||
unsigned char b = bp[3];
|
||||
((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a);
|
||||
bp+=4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(row_pointers);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *data;
|
||||
int len;
|
||||
} pngReadStruct;
|
||||
|
||||
static void staticPngReadFunc(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
pngReadStruct *readStruct = (pngReadStruct *)png_get_io_ptr(png_ptr);
|
||||
memset(data, 0, length);
|
||||
|
||||
int l = (int)length;
|
||||
if (l > readStruct->len) l = readStruct->len;
|
||||
memcpy(data, readStruct->data, l);
|
||||
readStruct->data += l;
|
||||
readStruct->len -= l;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
LICE_IBitmap *LICE_LoadPNGFromNamedResource(const char *name, LICE_IBitmap *bmp) // returns a bitmap (bmp if nonzero) on success
|
||||
{
|
||||
char buf[2048];
|
||||
buf[0]=0;
|
||||
if (strlen(name)>400) return NULL; // max name for this is 400 chars
|
||||
|
||||
#ifdef __APPLE__
|
||||
CFBundleRef bund = CFBundleGetMainBundle();
|
||||
if (bund)
|
||||
{
|
||||
CFURLRef url=CFBundleCopyBundleURL(bund);
|
||||
if (url)
|
||||
{
|
||||
CFURLGetFileSystemRepresentation(url,true,(UInt8*)buf,sizeof(buf)-512);
|
||||
CFRelease(url);
|
||||
}
|
||||
}
|
||||
if (!buf[0]) return 0;
|
||||
strcat(buf,"/Contents/Resources/");
|
||||
#else
|
||||
int sz = readlink("/proc/self/exe", buf, sizeof(buf)-512);
|
||||
if (sz < 1)
|
||||
{
|
||||
static char tmp;
|
||||
// this will likely not work if the program was launched with a relative path
|
||||
// and the cwd has changed, but give it a try anyway
|
||||
Dl_info inf={0,};
|
||||
if (dladdr(&tmp,&inf) && inf.dli_fname)
|
||||
sz = (int) strlen(inf.dli_fname);
|
||||
else
|
||||
sz = 0;
|
||||
}
|
||||
|
||||
if ((unsigned int)sz >= sizeof(buf)-512) sz = sizeof(buf)-512-1;
|
||||
buf[sz]=0;
|
||||
char *p = buf;
|
||||
while (*p) p++;
|
||||
while (p > buf && *p != '/') p--;
|
||||
*p=0;
|
||||
strcat(buf,"/Resources/");
|
||||
#endif // !__APPLE__
|
||||
|
||||
strcat(buf,name);
|
||||
return LICE_LoadPNG(buf,bmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
LICE_IBitmap *LICE_LoadPNGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp)
|
||||
{
|
||||
if (buflen<8) return NULL;
|
||||
unsigned char *data = (unsigned char *)(void*)data_in;
|
||||
if(png_sig_cmp(data, 0, 8)) return NULL;
|
||||
|
||||
pngReadStruct readStruct = {data, buflen};
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!png_ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if(!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_set_read_fn(png_ptr, &readStruct, staticPngReadFunc);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
unsigned int width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_method;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
//convert whatever it is to RGBA
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
{
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
color_type |= PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
if (bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_swap_alpha(png_ptr);
|
||||
else
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
|
||||
if (bmp) bmp->resize(width,height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height);
|
||||
if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height)
|
||||
{
|
||||
delete delbmp;
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));;
|
||||
LICE_pixel *srcptr = bmp->getBits();
|
||||
int dsrcptr=bmp->getRowSpan();
|
||||
unsigned int i;
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
row_pointers[i]=(unsigned char *)srcptr;
|
||||
srcptr+=dsrcptr;
|
||||
}
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
|
||||
//put shit in correct order
|
||||
#if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3)
|
||||
for(i=0;i<height;i++)
|
||||
{
|
||||
unsigned char *bp = row_pointers[i];
|
||||
int j=width;
|
||||
while (j-->0)
|
||||
{
|
||||
unsigned char a = bp[0];
|
||||
unsigned char r = bp[1];
|
||||
unsigned char g = bp[2];
|
||||
unsigned char b = bp[3];
|
||||
((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a);
|
||||
bp+=4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free(row_pointers);
|
||||
return bmp;
|
||||
}
|
||||
LICE_IBitmap *LICE_LoadPNGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HRSRC hResource = FindResource(hInst, resid, "PNG");
|
||||
if(!hResource) return NULL;
|
||||
|
||||
DWORD imageSize = SizeofResource(hInst, hResource);
|
||||
if(imageSize < 8) return NULL;
|
||||
|
||||
HGLOBAL res = LoadResource(hInst, hResource);
|
||||
const void* pResourceData = LockResource(res);
|
||||
if(!pResourceData) return NULL;
|
||||
|
||||
LICE_IBitmap * ret = LICE_LoadPNGFromMemory(pResourceData,imageSize,bmp);
|
||||
|
||||
// todo : cleanup res??
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
class LICE_PNGLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_PNGLoader()
|
||||
{
|
||||
rec.loadfunc = loadfunc;
|
||||
rec.get_extlist = get_extlist;
|
||||
rec._next = LICE_ImageLoader_list;
|
||||
LICE_ImageLoader_list = &rec;
|
||||
}
|
||||
|
||||
static LICE_IBitmap *loadfunc(const char *filename, bool checkFileName, LICE_IBitmap *bmpbase)
|
||||
{
|
||||
if (checkFileName)
|
||||
{
|
||||
const char *p=filename;
|
||||
while (*p)p++;
|
||||
while (p>filename && *p != '\\' && *p != '/' && *p != '.') p--;
|
||||
if (stricmp(p,".png")) return 0;
|
||||
}
|
||||
return LICE_LoadPNG(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "PNG files (*.PNG)\0*.PNG\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_PNGLoader LICE_pngldr;
|
||||
Reference in New Issue
Block a user