📄 devimage.c
字号:
return;
if ( (dstrect->x < 0) || (dstrect->y < 0) ||
((dstrect->x+dstrect->width) > dst->width) ||
((dstrect->y+dstrect->height) > dst->height) ) {
EPRINTF("GdStretchImage: invalid dest rect\n");
return;
}
} else {
full_dst.x = 0;
full_dst.y = 0;
full_dst.width = dst->width;
full_dst.height = dst->height;
dstrect = &full_dst;
}
/* Set up the data... */
pos = 0x10000;
inc = (srcrect->height << 16) / dstrect->height;
src_row = srcrect->y;
dst_row = dstrect->y;
bytesperpixel = dst->bytesperpixel;
/* Perform the stretch blit */
for ( dst_maxrow = dst_row+dstrect->height; dst_row<dst_maxrow;
++dst_row ) {
dstp = (MWUCHAR *)dst->imagebits + (dst_row*dst->pitch)
+ (dstrect->x*bytesperpixel);
while ( pos >= 0x10000L ) {
srcp = (MWUCHAR *)src->imagebits + (src_row*src->pitch)
+ (srcrect->x*bytesperpixel);
++src_row;
pos -= 0x10000L;
}
switch (bytesperpixel) {
case 1:
copy_row1(srcp, srcrect->width, dstp, dstrect->width);
break;
case 2:
copy_row2((unsigned short *)srcp, srcrect->width,
(unsigned short *)dstp, dstrect->width);
break;
case 3:
copy_row3(srcp, srcrect->width, dstp, dstrect->width);
break;
case 4:
copy_row4((unsigned long *)srcp, srcrect->width,
(unsigned long *)dstp, dstrect->width);
break;
}
pos += inc;
}
}
#if defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)
#include "jpeglib.h"
/*
* JPEG decompression routine
*
* JPEG support must be enabled (see README.txt in contrib/jpeg)
*
* SOME FINE POINTS: (from libjpeg)
* In the below code, we ignored the return value of jpeg_read_scanlines,
* which is the number of scanlines actually read. We could get away with
* this because we asked for only one line at a time and we weren't using
* a suspending data source. See libjpeg.doc for more info.
*
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
* we should have done it beforehand to ensure that the space would be
* counted against the JPEG max_memory setting. In some systems the above
* code would risk an out-of-memory error. However, in general we don't
* know the output image dimensions before jpeg_start_decompress(), unless we
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
*
* Scanlines are returned in the same order as they appear in the JPEG file,
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
* you can use one of the virtual arrays provided by the JPEG memory manager
* to invert the data. See wrbmp.c for an example.
*
* As with compression, some operating modes may require temporary files.
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*/
static int
LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd, MWBOOL fast_grayscale)
{
int i;
int ret = 2; /* image load error*/
unsigned char magic[4];
#if FASTJPEG
extern MWPALENTRY mwstdpal8[256];
#else
MWPALENTRY palette[256];
#endif
struct jpeg_source_mgr smgr;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
static void init_source(j_compress_ptr dinfo) {
smgr.next_input_byte = src->start;
smgr.bytes_in_buffer = src->size;
}
static void fill_input_buffer(j_compress_ptr dinfo) {
return;
}
static void skip_input_data(j_compress_ptr dinfo, int num_bytes) {
if (num_bytes >= src->size) return;
smgr.next_input_byte += num_bytes;
smgr.bytes_in_buffer -= num_bytes;
}
static int resync_to_restart(j_compress_ptr dinfo, int desired ) {
return(jpeg_resync_to_restart(dinfo, desired));
}
static void term_source(j_compress_ptr dinfo) {
return;
}
/* first determine if JPEG file since decoder will error if not*/
bseek(src, 0, SEEK_SET);
if (!bread(src, magic, 2))
return(0);
if (magic[0] != 0xFF || magic[1] != 0xD8)
return(0); /* not JPEG image*/
bread(src, magic, 4);
bread(src, magic, 4);
if (strncmp(magic, "JFIF", 4) != 0)
return(0); /* not JPEG image*/
bread(src, 0, SEEK_SET);
pimage->imagebits = NULL;
pimage->palette = NULL;
/* Step 1: allocate and initialize JPEG decompression object */
/* We set up the normal JPEG error routines. */
cinfo.err = jpeg_std_error (&jerr);
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress (&cinfo);
/* Step 2: Setup the source manager */
smgr.init_source = init_source;
smgr.fill_input_buffer = fill_input_buffer;
smgr.skip_input_data = skip_input_data;
smgr.resync_to_restart = resync_to_restart;
smgr.term_source = term_source;
cinfo.src = &smgr;
/* Step 2: specify data source (eg, a file) */
/* jpeg_stdio_src (&cinfo, fp); */
/* Step 3: read file parameters with jpeg_read_header() */
jpeg_read_header (&cinfo, TRUE);
/* Step 4: set parameters for decompression */
cinfo.out_color_space = fast_grayscale? JCS_GRAYSCALE: JCS_RGB;
cinfo.quantize_colors = FALSE;
#if FASTJPEG
goto fastjpeg;
#endif
if (!fast_grayscale)
{
if (psd->pixtype == MWPF_PALETTE)
{
fastjpeg:
cinfo.quantize_colors = TRUE;
#if FASTJPEG
cinfo.actual_number_of_colors = 256;
#else
/* Get system palette */
cinfo.actual_number_of_colors =
GdGetPalette(psd, 0, psd->ncolors, palette);
#endif
/* Allocate jpeg colormap space */
cinfo.colormap = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE,
(JDIMENSION)cinfo.actual_number_of_colors,
(JDIMENSION)3);
/* Set colormap from system palette */
for(i = 0; i < cinfo.actual_number_of_colors; ++i)
{
#if FASTJPEG
cinfo.colormap[0][i] = mwstdpal8[i].r;
cinfo.colormap[1][i] = mwstdpal8[i].g;
cinfo.colormap[2][i] = mwstdpal8[i].b;
#else
cinfo.colormap[0][i] = palette[i].r;
cinfo.colormap[1][i] = palette[i].g;
cinfo.colormap[2][i] = palette[i].b;
#endif
}
}
}
else
{
/* Grayscale output asked */
cinfo.quantize_colors = TRUE;
cinfo.out_color_space = JCS_GRAYSCALE;
cinfo.desired_number_of_colors = psd->ncolors;
}
jpeg_calc_output_dimensions(&cinfo);
pimage->width = cinfo.output_width;
pimage->height = cinfo.output_height;
pimage->planes = 1;
#if FASTJPEG
pimage->bpp = 8;
#else
pimage->bpp = (fast_grayscale || psd->pixtype == MWPF_PALETTE)?
8: cinfo.output_components*8;
#endif
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
&pimage->bytesperpixel);
pimage->compression = MWIMAGE_RGB; /* RGB not BGR order*/
pimage->palsize = (pimage->bpp == 8)? 256: 0;
pimage->imagebits = malloc(pimage->pitch * pimage->height);
if(!pimage->imagebits)
goto err;
pimage->palette = NULL;
#if FASTJPEG
if(pimage->bpp == 8) {
pimage->palette = malloc(256*sizeof(MWPALENTRY));
if(!pimage->palette)
goto err;
for (i=0; i<256; ++i)
pimage->palette[i] = mwstdpal8[i];
}
#endif
/* Step 5: Start decompressor */
jpeg_start_decompress (&cinfo);
/* Step 6: while (scan lines remain to be read) */
while(cinfo.output_scanline < cinfo.output_height) {
JSAMPROW rowptr[1];
rowptr[0] = (JSAMPROW)(pimage->imagebits +
cinfo.output_scanline * pimage->pitch);
jpeg_read_scanlines (&cinfo, rowptr, 1);
}
ret = 1;
err:
/* Step 7: Finish decompression */
jpeg_finish_decompress (&cinfo);
/* Step 8: Release JPEG decompression object */
jpeg_destroy_decompress (&cinfo);
/* May want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
return ret;
}
#endif /* defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)*/
#if defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)
#include "png.h"
/* png_jmpbuf() macro is not defined prior to libpng-1.0.6*/
#ifndef png_jmpbuf
#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
#endif
/*
* Load a PNG file.
* Currently for simplicity we get the PNG library to convert the file to
* 24 bit RGB format with no alpha channel information even if we could
* potentially store the image more efficiently by taking note of the image
* type and depth and acting accordingly. Similarly, > 8 bits per channel,
* gamma correction, etc. are not supported.
*/
static int
LoadPNG(buffer_t * src, PMWIMAGEHDR pimage)
{
unsigned char hdr[8], **rows;
png_structp state;
png_infop pnginfo;
png_uint_32 width, height;
int bit_depth, colourtype, i;
bseek(src, 0L, 0);
if(bread(src, hdr, 8) != 8) return 0;
if(png_sig_cmp(hdr, 0, 8)) return 0;
if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL))) goto nomem;
if(!(pnginfo = png_create_info_struct(state))) {
png_destroy_read_struct(&state, NULL, NULL);
goto nomem;
}
if(setjmp(png_jmpbuf(state))) {
png_destroy_read_struct(&state, &pnginfo, NULL);
return 2;
}
png_init_io(state, fp);
png_set_sig_bytes(state, 8);
png_read_info(state, pnginfo);
png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &colourtype,
NULL, NULL, NULL);
pimage->width = width;
pimage->height = height;
pimage->bpp = 24;
pimage->planes = 1;
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
&pimage->bytesperpixel);
pimage->compression = MWIMAGE_RGB;
if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
png_destroy_read_struct(&state, &pnginfo, NULL);
goto nomem;
}
if(!(rows = malloc(pimage->height * sizeof(unsigned char *)))) {
png_destroy_read_struct(&state, &pnginfo, NULL);
goto nomem;
}
for(i = 0; i < pimage->height; i++)
rows[i] = pimage->imagebits + (i * pimage->pitch);
png_set_expand(state);
if(bit_depth == 16)
png_set_strip_16(state);
if(colourtype & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(state);
if(colourtype == PNG_COLOR_TYPE_GRAY ||
colourtype == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(state);
png_read_image(state, rows);
png_read_end(state, NULL);
free(rows);
png_destroy_read_struct(&state, &pnginfo, NULL);
return 1;
nomem:
EPRINTF("LoadPNG: Out of memory\n");
return 2;
}
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)*/
#if defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)
/* BMP stuff*/
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
#define BI_BITFIELDS 3L
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef struct {
/* BITMAPFILEHEADER*/
BYTE bfType[2];
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BMPFILEHEAD;
#define FILEHEADSIZE 14
/* windows style*/
typedef struct {
/* BITMAPINFOHEADER*/
DWORD BiSize;
DWORD BiWidth;
DWORD BiHeight;
WORD BiPlanes;
WORD BiBitCount;
DWORD BiCompression;
DWORD BiSizeImage;
DWORD BiXpelsPerMeter;
DWORD BiYpelsPerMeter;
DWORD BiClrUsed;
DWORD BiClrImportant;
} BMPINFOHEAD;
#define INFOHEADSIZE 40
/* os/2 style*/
typedef struct {
/* BITMAPCOREHEADER*/
DWORD bcSize;
WORD bcWidth;
WORD bcHeight;
WORD bcPlanes;
WORD bcBitCount;
} BMPCOREHEAD;
#define COREHEADSIZE 12
static int DecodeRLE8(MWUCHAR *buf, buffer_t *src);
static int DecodeRLE4(MWUCHAR *buf, buffer_t *src);
static void put4(int b);
/*
* BMP decoding routine
*/
/* Changed by JHC to allow a buffer instead of a filename */
static int
LoadBMP(buffer_t *src, PMWIMAGEHDR pimage)
{
int h, i, compression;
int headsize;
MWUCHAR *imagebits;
BMPFILEHEAD bmpf;
BMPINFOHEAD bmpi;
BMPCOREHEAD bmpc;
MWUCHAR headbuffer[INFOHEADSIZE];
bseek(src, 0, SEEK_SET);
pimage->imagebits = NULL;
pimage->palette = NULL;
/* read BMP file header*/
if (bread(src, &headbuffer, FILEHEADSIZE) != FILEHEADSIZE)
return(0);
bmpf.bfType[0] = headbuffer[0];
bmpf.bfType[1] = headbuffer[1];
/* Is it really a bmp file ? */
if (*(WORD*)&bmpf.bfType[0] != wswap(0x4D42)) /* 'BM' */
return 0; /* not bmp image*/
/*bmpf.bfSize = dwswap(dwread(&headbuffer[2]));*/
bmpf.bfOffBits = dwswap(dwread(&headbuffer[10]));
/* Read remaining header size */
if (bread(src,&headsize,sizeof(DWORD)) != sizeof(DWORD))
return 0; /* not bmp image*/
headsize = dwswap(headsize);
/* might be windows or os/2 header */
if(headsize == COREHEADSIZE) {
/* read os/2 header */
if(bread(src, &headbuffer, COREHEADSIZE-sizeof(DWORD)) !=
COREHEADSIZE-sizeof(DWORD))
return 0; /* not bmp image*/
/* Get data */
bmpc.bcWidth = wswap(*(WORD*)&headbuffer[0]);
bmpc.bcHeight = wswap(*(WORD*)&headbuffer[2]);
bmpc.bcPlanes = wswap(*(WORD*)&headbuffer[4]);
bmpc.bcBitCount = wswap(*(WORD*)&headbuffer[6]);
pimage->width = (int)bmpc.bcWidth;
pimage->height = (int)bmpc.bcHeight;
pimage->bpp = bmpc.bcBitCount;
if (pimage->bpp <= 8)
pimage->palsize = 1 << pimage->bpp;
else pimage->palsize = 0;
compression = BI_RGB;
} else {
/* read windows header */
if(bread(src, &headbuffer, INFOHEADSIZE-sizeof(DWORD)) !=
INFOHEADSIZE-sizeof(DWORD))
return 0; /* not bmp image*/
/* Get data */
bmpi.BiWidth = dwswap(*(DWORD*)&headbuffer[0]);
bmpi.BiHeight = dwswap(*(DWORD*)&headbuffer[4]);
bmpi.BiPlanes = wswap(*(WORD*)&headbuffer[8]);
bmpi.BiBitCount = wswap(*(WORD*)&headbuffer[10]);
bmpi.BiCompression = dwswap(*(DWORD*)&headbuffer[12]);
bmpi.BiSizeImage = dwswap(*(DWORD*)&headbuffer[16]);
bmpi.BiXpelsPerMeter = dwswap(*(DWORD*)&headbuffer[20]);
bmpi.BiYpelsPerMeter = dwswap(*(DWORD*)&headbuffer[24]);
bmpi.BiClrUsed = dwswap(*(DWORD*)&headbuffer[28]);
bmpi.BiClrImportant = dwswap(*(DWORD*)&headbuffer[32]);
pimage->width = (int)bmpi.BiWidth;
pimage->height = (int)bmpi.BiHeight;
pimage->bpp = bmpi.BiBitCount;
pimage->palsize = (int)bmpi.BiClrUsed;
if (pimage->palsize > 256)
pimage->palsize = 0;
else if(pimage->palsize == 0 && pimage->bpp <= 8)
pimage->palsize = 1 << pimage->bpp;
compression = bmpi.BiCompression;
}
pimage->compression = MWIMAGE_BGR; /* right side up, BGR order*/
pimage->planes = 1;
/* currently only 1, 4, 8 and 24 bpp bitmaps*/
if(pimage->bpp > 8 && pimage->bpp != 24) {
EPRINTF("LoadBMP: image bpp not 1, 4, 8 or 24\n");
return 2; /* image loading error*/
}
/* compute byte line size and bytes per pixel*/
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
&pimage->bytesperpixel);
/* Allocate image */
if( (pimage->imagebits = malloc(pimage->pitch*pimage->height)) == NULL)
goto err;
if( (pimage->palette = malloc(256*sizeof(MWPALENTRY))) == NULL)
goto err;
/* get colormap*/
if(pimage->bpp <= 8) {
for(i=0; i<pimage->palsize; i++) {
pimage->palette[i].b = bgetc(src);
pimage->palette[i].g = bgetc(src);
pimage->palette[i].r = bgetc(src);
if(headsize != COREHEADSIZE)
bgetc(src);
}
}
/* decode image data*/
bseek(src, bmpf.bfOffBits, SEEK_SET);
h = pimage->height;
/* For every row ... */
while (--h >= 0) {
/* turn image rightside up*/
imagebits = pimage->imagebits + h*pimage->pitch;
/* Get row data from file */
if(compression == BI_RLE8) {
if(!DecodeRLE8(imagebits, src))
break;
} else if(compression == BI_RLE4) {
if(!DecodeRLE4(imagebits, src))
break;
} else {
if(bread(src, imagebits, pimage->pitch) !=
pimage->pitch)
goto err;
}
}
return 1; /* bmp image ok*/
err:
EPRINTF("LoadBMP: image loading error\n");
if(pimage->imagebits)
free(pimage->imagebits);
if(pimage->palette)
free(pimage->palette);
return 2; /* bmp image error*/
}
/*
* Decode one line of RLE8, return 0 when done with all bitmap data
*/
static int
DecodeRLE8(MWUCHAR *buf, buffer_t *src)
{
int c, n;
MWUCHAR * p = buf;
for( ;;) {
switch( n = bgetc(src)) {
case EOF:
return( 0);
case 0: /* 0 = escape*/
switch( n = bgetc(src)) {
case 0: /* 0 0 = end of current scan line*/
return( 1);
case 1: /* 0 1 = end of data*/
return( 1);
case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/
(void)bgetc(src);
(void)bgetc(src);
continue;
default: /* 0 3..255 xx nn uncompressed data*/
for( c=0; c<n; c++)
*p++ = bgetc(src);
if( n & 1)
(void)bgetc(src);
continue;
}
default:
c = bgetc(src);
while( n--)
*p++ = c;
continue;
}
}
}
/*
* Decode one line of RLE4, return 0 when done with all bitmap data
*/
static MWUCHAR *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -