add oversampler
This commit is contained in:
404
oversampling/WDL/lice/lice_jpg.cpp
Normal file
404
oversampling/WDL/lice/lice_jpg.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
Cockos WDL - LICE - Lightweight Image Compositing Engine
|
||||
Copyright (C) 2007 and later, Cockos Incorporated
|
||||
File: lice_jpg.cpp (JPG loading for LICE)
|
||||
See lice.h for license and other information
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lice.h"
|
||||
#include <setjmp.h>
|
||||
#include "../wdltypes.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../jpeglib/jpeglib.h"
|
||||
};
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
static void LICEJPEG_Error(j_common_ptr cinfo)
|
||||
{
|
||||
longjmp(((my_error_mgr*)cinfo->err)->setjmp_buffer,1);
|
||||
}
|
||||
static void LICEJPEG_EmitMsg(j_common_ptr cinfo, int msg_level) { }
|
||||
static void LICEJPEG_FmtMsg(j_common_ptr cinfo, char *) { }
|
||||
static void LICEJPEG_OutMsg(j_common_ptr cinfo) { }
|
||||
static void LICEJPEG_reset_error_mgr(j_common_ptr cinfo)
|
||||
{
|
||||
cinfo->err->num_warnings = 0;
|
||||
cinfo->err->msg_code = 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void LICEJPEG_init_source(j_decompress_ptr cinfo) {}
|
||||
static unsigned char EOI_data[2] = { 0xFF, 0xD9 };
|
||||
static boolean LICEJPEG_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
cinfo->src->next_input_byte = EOI_data;
|
||||
cinfo->src->bytes_in_buffer = 2;
|
||||
return TRUE;
|
||||
}
|
||||
static void LICEJPEG_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
if (num_bytes > 0)
|
||||
{
|
||||
if (num_bytes > (long) cinfo->src->bytes_in_buffer)
|
||||
{
|
||||
num_bytes = (long) cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
cinfo->src->next_input_byte += (size_t) num_bytes;
|
||||
cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
static void LICEJPEG_term_source(j_decompress_ptr cinfo) {}
|
||||
#endif
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPGFromResource(HINSTANCE hInst, const char *resid, LICE_IBitmap *bmp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HRSRC hResource = FindResource(hInst, resid, "JPG");
|
||||
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;
|
||||
|
||||
unsigned char *data = (unsigned char *)pResourceData;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={0,};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr));
|
||||
|
||||
cinfo.src->init_source = LICEJPEG_init_source;
|
||||
cinfo.src->fill_input_buffer = LICEJPEG_fill_input_buffer;
|
||||
cinfo.src->skip_input_data = LICEJPEG_skip_input_data;
|
||||
cinfo.src->resync_to_restart = jpeg_resync_to_restart;
|
||||
cinfo.src->term_source = LICEJPEG_term_source;
|
||||
|
||||
cinfo.src->next_input_byte = data;
|
||||
cinfo.src->bytes_in_buffer = imageSize;
|
||||
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height)
|
||||
{
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
}
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo); // we created cinfo.src with some special alloc so I think it gets collected
|
||||
|
||||
return bmp;
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={{0},};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
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;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_stdio_src(&cinfo, fp);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(fp);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
LICE_IBitmap *LICE_LoadJPGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp)
|
||||
{
|
||||
if (buflen < 8) return NULL;
|
||||
|
||||
unsigned char *data = (unsigned char *)(void *)data_in;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr={{0},};
|
||||
JSAMPARRAY buffer;
|
||||
int row_stride;
|
||||
|
||||
jerr.pub.error_exit = LICEJPEG_Error;
|
||||
jerr.pub.emit_message = LICEJPEG_EmitMsg;
|
||||
jerr.pub.output_message = LICEJPEG_OutMsg;
|
||||
jerr.pub.format_message = LICEJPEG_FmtMsg;
|
||||
jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr;
|
||||
|
||||
cinfo.err = &jerr.pub;
|
||||
|
||||
if (setjmp(jerr.setjmp_buffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_mem_src(&cinfo, data, buflen);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
|
||||
LICE_IBitmap *delbmp = NULL;
|
||||
if (bmp) bmp->resize(cinfo.output_width,cinfo.output_height);
|
||||
else delbmp = bmp = new WDL_NEW LICE_MemBitmap(cinfo.output_width,cinfo.output_height);
|
||||
|
||||
if (!bmp || bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height)
|
||||
{
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
delete delbmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LICE_pixel *bmpptr = bmp->getBits();
|
||||
int dbmpptr=bmp->getRowSpan();
|
||||
if (bmp->isFlipped())
|
||||
{
|
||||
bmpptr += dbmpptr*(bmp->getHeight()-1);
|
||||
dbmpptr=-dbmpptr;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
if (cinfo.output_components==3)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255);
|
||||
}
|
||||
}
|
||||
else if (cinfo.output_components==1)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < (int)cinfo.output_width; x++)
|
||||
{
|
||||
int v=buffer[0][x];
|
||||
bmpptr[x]=LICE_RGBA(v,v,v,255);
|
||||
}
|
||||
}
|
||||
else
|
||||
memset(bmpptr,0,4*cinfo.output_width);
|
||||
bmpptr+=dbmpptr;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
class LICE_JPGLoader
|
||||
{
|
||||
public:
|
||||
_LICE_ImageLoader_rec rec;
|
||||
LICE_JPGLoader()
|
||||
{
|
||||
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,".jpg")&&stricmp(p,".jpeg")&&stricmp(p,".jfif")) return 0;
|
||||
}
|
||||
return LICE_LoadJPG(filename,bmpbase);
|
||||
}
|
||||
static const char *get_extlist()
|
||||
{
|
||||
return "JPEG files (*.JPG;*.JPEG;*.JFIF)\0*.JPG;*.JPEG;*.JFIF\0";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LICE_JPGLoader LICE_jgpldr;
|
||||
Reference in New Issue
Block a user