static LICE_IBitmap *hbmToBit(HBITMAP hbm, LICE_IBitmap *bmp) { BITMAP bm; GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm); LICE_SysBitmap sysbitmap(bm.bmWidth,bm.bmHeight); #ifdef _WIN32 HDC hdc=CreateCompatibleDC(NULL); HGDIOBJ oldBM=SelectObject(hdc,hbm); BitBlt(sysbitmap.getDC(),0,0,bm.bmWidth,bm.bmHeight,hdc,0,0,SRCCOPY); GdiFlush(); if (!bmp) bmp=new WDL_NEW LICE_MemBitmap(bm.bmWidth,bm.bmHeight); LICE_Copy(bmp,&sysbitmap); SelectObject(hdc,oldBM); DeleteDC(hdc); #else LICE_Clear(&sysbitmap,0); RECT r={0,0,bm.bmWidth,bm.bmHeight}; DrawImageInRect(sysbitmap.getDC(),hbm,&r); if (!bmp) bmp=new WDL_NEW LICE_MemBitmap(bm.bmWidth,bm.bmHeight); LICE_Copy(bmp,&sysbitmap); #endif if (bmp) LICE_FillRect(bmp,0,0,bmp->getWidth(),bmp->getHeight(),LICE_RGBA(0,0,0,255),1.0f,LICE_BLIT_MODE_ADD); return bmp; }
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_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 = fopen(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; }
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 = fopen(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; }