📄 image.cpp
字号:
rs->accum[i+0] += rs->lb[i+0]*rs->outh;
rs->accum[i+1] += rs->lb[i+1]*rs->outh;
rs->accum[i+2] += rs->lb[i+2]*rs->outh;
}
}
rs->inptr+=rs->outh;
}
struct my_src_mgr {
struct jpeg_source_mgr pub;
ImageLoader::BinReader *rdr;
JOCTET *buffer;
};
METHODDEF(void) jsrc_init_source (j_decompress_ptr cinfo) {
// do nothing
}
METHODDEF(boolean) jsrc_fill_input_buffer (j_decompress_ptr cinfo) {
my_src_mgr *mgr=(my_src_mgr*)cinfo->src;
int nr=mgr->rdr->Read(mgr->buffer,INBUF_SIZE);
if (nr<=0) { // eof
// fake EOI marker
mgr->buffer[0]=(JOCTET)0xff;
mgr->buffer[1]=(JOCTET)JPEG_EOI;
nr=2;
}
mgr->pub.bytes_in_buffer=nr;
mgr->pub.next_input_byte=mgr->buffer;
return TRUE;
}
METHODDEF(void) jsrc_skip_input_data (j_decompress_ptr cinfo, long bytes) {
my_src_mgr *mgr=(my_src_mgr*)cinfo->src;
if (bytes > 0) {
while (bytes > (long) mgr->pub.bytes_in_buffer) {
bytes -= (long) mgr->pub.bytes_in_buffer;
jsrc_fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
mgr->pub.next_input_byte += (size_t) bytes;
mgr->pub.bytes_in_buffer -= (size_t) bytes;
}
}
METHODDEF(void) jsrc_term_source(j_decompress_ptr cinfo) {
// do nothing
}
static void prepare_buffer(j_decompress_ptr cinfo,ImageLoader::BinReader *rdr) {
my_src_mgr *mgr;
if (cinfo->src==NULL) {
cinfo->src=(struct jpeg_source_mgr *)
(cinfo->mem->alloc_small((j_common_ptr)cinfo,JPOOL_PERMANENT,
sizeof(my_src_mgr)));
mgr=(my_src_mgr*)cinfo->src;
mgr->buffer=(JOCTET*)
(cinfo->mem->alloc_small((j_common_ptr)cinfo,JPOOL_PERMANENT,
INBUF_SIZE*sizeof(JOCTET)));
}
mgr=(my_src_mgr*)cinfo->src;
mgr->rdr=rdr;
mgr->pub.init_source=jsrc_init_source;
mgr->pub.fill_input_buffer=jsrc_fill_input_buffer;
mgr->pub.skip_input_data=jsrc_skip_input_data;
mgr->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
mgr->pub.term_source=jsrc_term_source;
mgr->pub.bytes_in_buffer=0;
mgr->pub.next_input_byte=NULL;
}
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf jb;
};
METHODDEF(void) je_error_exit(j_common_ptr cinfo) {
my_error_mgr *mgr=(my_error_mgr*)cinfo->err;
/* Always display the message */
(*cinfo->err->output_message) (cinfo);
jpeg_destroy(cinfo);
longjmp(mgr->jb,1);
}
METHODDEF(void) je_output_message(j_common_ptr cinfo) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
// do nothing at this time
#if 0
MessageBoxA(GetActiveWindow(),buffer,"JPEG Decompressor",MB_OK);
#endif
}
static void PNGAPI pngr_read_data(png_structp png_ptr,png_bytep data,png_size_t length) {
ImageLoader::BinReader *rdr=(ImageLoader::BinReader*)png_get_io_ptr(png_ptr);
if (!rdr || rdr->Read(data,length)!=(int)length)
png_error(png_ptr,"Read Error");
}
static int get_bitmap_format() {
static int format=BF_UNKNOWN;
#ifdef _WIN32_WCE
if (format!=BF_UNKNOWN)
return format;
HINSTANCE hLib;
if ((hLib=LoadLibrary(_T("gx.dll")))!=NULL) {
GXDisplayProperties (*gp)();
gp=(GXDisplayProperties (*)())GetProcAddress(hLib,
_T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ"));
if (gp) {
GXDisplayProperties props=gp();
if (props.ffFormat&kfDirect555)
format=BF_555;
else if (props.ffFormat&kfDirect565)
format=BF_565;
else
format=BF_888;
}
FreeLibrary(hLib);
}
#endif
if (format!=BF_UNKNOWN)
return format;
HDC hDC=GetDC(NULL);
if (GetDeviceCaps(hDC,BITSPIXEL)==16)
format=BF_565;
else
format=BF_888;
ReleaseDC(NULL,hDC);
return format;
}
static imagestore *bminit(HDC hDC,int w,int h,int maxw,int maxh,int rotate)
{
struct {
BITMAPINFOHEADER h;
DWORD masks[3];
} bi;
imagestore *im=(imagestore*)malloc(sizeof(imagestore));
if (!im)
return NULL;
void *data;
int bpp;
s32 rowstep;
im->bmformat=get_bitmap_format();
memset(&bi,0,sizeof(bi));
switch (im->bmformat) {
case BF_555:
bpp=2;
bi.masks[0]=0x7C00;
bi.masks[1]=0x03E0;
bi.masks[2]=0x001F;
bi.h.biCompression=BI_BITFIELDS;
im->packbits=packbits_24_to_15;
break;
case BF_565:
bpp=2;
bi.masks[0]=0xF800;
bi.masks[1]=0x07E0;
bi.masks[2]=0x001F;
bi.h.biCompression=BI_BITFIELDS;
im->packbits=packbits_24_to_16;
break;
case BF_888:
bpp=3;
#ifdef _WIN32_WCE
bi.masks[0]=0xFF0000;
bi.masks[1]=0x00FF00;
bi.masks[2]=0x0000FF;
bi.h.biCompression=BI_BITFIELDS;
#else
bi.h.biCompression=BI_RGB;
#endif
im->packbits=packbits_24_to_24;
break;
#ifndef STANDALONE
default:
ASSERT(0);
#endif
}
if (w<=maxw && h<=maxh) {
im->width=w;
im->height=h;
} else {
if (maxw*h<maxh*w) {
im->width=maxw;
im->height=(h*maxw)/w;
} else {
im->width=(w*maxh)/h;
im->height=maxh;
}
}
if (rotate==0 || rotate==1800) {
im->realheight=im->height;
im->realwidth=im->width;
} else {
im->realheight=im->width;
im->realwidth=im->height;
}
if (!hDC)
return im;
rowstep=(im->realwidth*bpp+3)&~3;
bi.h.biSize=sizeof(bi.h);
bi.h.biWidth=im->realwidth;
bi.h.biHeight=im->realheight;
bi.h.biPlanes=1;
bi.h.biBitCount=bpp==2 ? 16 : 24;
if (!(im->bmp=CreateDIBSection(hDC,(BITMAPINFO*)&bi,DIB_RGB_COLORS,&data,NULL,0))) {
DWORD err=GetLastError();
free(im);
return NULL;
}
switch (rotate) {
case 2700:
im->hstep=-rowstep;
im->vstep=-bpp;
im->bits=(u8*)data+bpp*(im->realwidth-1)+rowstep*(im->realheight-1);
break;
case 1800:
im->hstep=-bpp;
im->vstep=rowstep;
im->bits=(u8*)data+bpp*(im->realwidth-1);
break;
case 900:
im->hstep=rowstep;
im->vstep=bpp;
im->bits=(u8*)data;
break;
case 0:
im->hstep=bpp;
im->vstep=-rowstep;
im->bits=(u8*)data+rowstep*(im->realheight-1);
break;
#ifndef STANDALONE
default:
ASSERT(0);
#endif
}
return im;
}
bool ImageLoader::Load(HDC hDC,const wchar_t *type,ImageLoader::BinReader *rdr,
int maxwidth,int maxheight,int rotation,HBITMAP& bmp,
int& width,int& height)
{
imagestore *is=NULL;
resize_state *rs=NULL;
set_gamma(0.45455);
if (!wcscmp(type,L"image/jpeg")) { // only jpeg images are supported at the time
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
cinfo.err=jpeg_std_error(&jerr.pub);
jerr.pub.error_exit=je_error_exit;
jerr.pub.output_message=je_output_message;
if (setjmp(jerr.jb))
goto common_exit;
jpeg_create_decompress(&cinfo);
prepare_buffer(&cinfo,rdr);
jpeg_read_header(&cinfo,TRUE);
// do some scaling
int scale,iw;
for (scale=1,iw=cinfo.image_width;scale<8;scale<<=1,iw>>=1)
if ((iw>>1)<maxwidth)
break;
cinfo.scale_denom=scale;
cinfo.out_color_space=JCS_RGB;
jpeg_calc_output_dimensions(&cinfo);
is=bminit(hDC,cinfo.output_width,cinfo.output_height,maxwidth,maxheight,rotation);
if (is && hDC) {
if (is->width!=cinfo.output_width || is->height!=cinfo.output_height) {
rs=resize_state_create(cinfo.output_width,cinfo.output_height,is);
if (!rs)
goto outjpg;
}
jpeg_start_decompress(&cinfo);
JSAMPARRAY line=cinfo.mem->alloc_sarray((j_common_ptr)&cinfo,
JPOOL_IMAGE,cinfo.output_width*cinfo.output_components,
1);
if (rs) {
while (cinfo.output_scanline<cinfo.output_height) {
jpeg_read_scanlines(&cinfo,line,1);
resize_add_line(rs,line[0]);
}
} else {
while (cinfo.output_scanline<cinfo.output_height) {
jpeg_read_scanlines(&cinfo,line,1);
is->packbits(is,line[0]);
}
}
jpeg_finish_decompress(&cinfo);
}
outjpg:
jpeg_destroy_decompress(&cinfo);
} else if (!wcscmp(type,L"image/png")) {
// create png read structures
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if (!png_ptr) // out of memory?
return false;
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) { // out of memory?
png_destroy_read_struct(&png_ptr,NULL,NULL);
return false;
}
// setup i/o routine
png_set_read_fn(png_ptr,rdr,pngr_read_data);
// init jmpbuf
if (setjmp(png_jmpbuf(png_ptr))) { // error occurred
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
goto common_exit;
}
png_read_info(png_ptr,info_ptr);
png_uint_32 width,height;
int bit_depth,color_type,interlace_type;
png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,
&interlace_type,NULL,NULL);
if (interlace_type!=PNG_INTERLACE_NONE) {
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
return false;
}
// configure transformations, we always want RGB data in the end
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_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);
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);
// update info after applying transformations
png_read_update_info(png_ptr,info_ptr);
// reload info
png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,
&interlace_type,NULL,NULL);
// ok, now configure storer and resizer
is=bminit(hDC,width,height,maxwidth,maxheight,rotation);
if (is && hDC) {
if (is->width!=width || is->height!=height) {
rs=resize_state_create(width,height,is);
if (!rs)
goto outpng;
}
// handle transparency
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
// create a resizer, because we use it to apply
// transparency
if (!rs) {
rs=resize_state_create(width,height,is);
if (!rs)
goto outpng;
}
png_color_16p image_background;
if (png_get_bKGD(png_ptr, info_ptr, &image_background))
resize_set_alpha(rs,RGB(image_background->red>>8,
image_background->green>>8,
image_background->blue>>8));
else
resize_set_alpha(rs,::GetBkColor(hDC));
}
// now read the image line by line
int rowbytes=png_get_rowbytes(png_ptr,info_ptr);
unsigned char *row=(unsigned char *)malloc(rowbytes);
if (!row)
goto outpng;
if (rs) {
for (int i=0;i<(int)height;++i) {
png_read_row(png_ptr,row,NULL);
resize_add_line(rs,row);
}
} else {
for (int i=0;i<(int)height;++i) {
png_read_row(png_ptr,row,NULL);
is->packbits(is,row);
}
}
// destroy read struct
free(row);
png_read_end(png_ptr,NULL);
}
outpng:
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
} else
return false;
common_exit:
if (is) {
bmp=is->bmp;
width=is->width;
height=is->height;
}
resize_state_destroy(rs);
free(is);
return is!=NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -