📄 devimage.c
字号:
pii->id = id; pii->width = pimage->width; pii->height = pimage->height; pii->planes = pimage->planes; pii->bpp = pimage->bpp; pii->pitch = pimage->pitch; pii->bytesperpixel = pimage->bytesperpixel; pii->compression = pimage->compression; pii->palsize = pimage->palsize; if (pimage->palsize) { if (pimage->palette) { for (i=0; i<pimage->palsize; ++i) pii->palette[i] = pimage->palette[i]; } else { /* FIXME handle jpeg's without palette*/ GdGetPalette(pItem->psd, 0, pimage->palsize, pii->palette); } } return TRUE;}#define PIX2BYTES(n) (((n)+7)/8)/* * compute image line size and bytes per pixel * from bits per pixel and width */static voidComputePitch(int bpp, int width, int *pitch, int *bytesperpixel){ int linesize; int bytespp = 1; if(bpp == 1) linesize = PIX2BYTES(width); else if(bpp <= 4) linesize = PIX2BYTES(width<<2); else if(bpp <= 8) linesize = width; else if(bpp <= 16) { linesize = width * 2; bytespp = 2; } else if(bpp <= 24) { linesize = width * 3; bytespp = 3; } else { linesize = width * 4; bytespp = 4; } /* rows are DWORD right aligned*/ *pitch = (linesize + 3) & ~3; *bytesperpixel = bytespp;}/* * StretchImage - Resize an image * * Major portions from SDL Simple DirectMedia Layer by Sam Lantinga * Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga <slouken@devolution.com> * This a stretch blit implementation based on ideas given to me by * Tomasz Cejner - thanks! :) *//* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#define DEFINE_COPY_ROW(name, type) \static void name(type *src, int src_w, type *dst, int dst_w) \{ \ int i; \ int pos, inc; \ type pixel = 0; \ \ pos = 0x10000; \ inc = (src_w << 16) / dst_w; \ for ( i=dst_w; i>0; --i ) { \ while ( pos >= 0x10000L ) { \ pixel = *src++; \ pos -= 0x10000L; \ } \ *dst++ = pixel; \ pos += inc; \ } \}DEFINE_COPY_ROW(copy_row1, unsigned char)DEFINE_COPY_ROW(copy_row2, unsigned short)DEFINE_COPY_ROW(copy_row4, unsigned long)static void copy_row3(unsigned char *src, int src_w, unsigned char *dst, int dst_w){ int i; int pos, inc; unsigned char r = 0; unsigned char g = 0; unsigned char b = 0; pos = 0x10000; inc = (src_w << 16) / dst_w; for ( i=dst_w; i>0; --i ) { while ( pos >= 0x10000L ) { b = *src++; g = *src++; r = *src++; pos -= 0x10000L; } *dst++ = b; *dst++ = g; *dst++ = r; pos += inc; }}/** * Perform a stretch blit between two image structs of the same format. * * @param src Source image. * @param srcrect Source rectangle. * @param dst Destination image. * @param dstrect Destination rectangle. */voidGdStretchImage(PMWIMAGEHDR src, MWCLIPRECT *srcrect, PMWIMAGEHDR dst, MWCLIPRECT *dstrect){ int pos, inc; int bytesperpixel; int dst_maxrow; int src_row, dst_row; MWUCHAR *srcp = 0; MWUCHAR *dstp; MWCLIPRECT full_src; MWCLIPRECT full_dst; if ( src->bytesperpixel != dst->bytesperpixel ) { EPRINTF("GdStretchImage: bytesperpixel mismatch\n"); return; } /* Verify the blit rectangles */ if ( srcrect ) { if ( (srcrect->x < 0) || (srcrect->y < 0) || ((srcrect->x+srcrect->width) > src->width) || ((srcrect->y+srcrect->height) > src->height) ) { EPRINTF("GdStretchImage: invalid source rect\n"); return; } } else { full_src.x = 0; full_src.y = 0; full_src.width = src->width; full_src.height = src->height; srcrect = &full_src; } if ( dstrect ) { /* if stretching to nothing, return*/ if (!dstrect->width || !dstrect->height) 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_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 buffer_t *inptr;static voidinit_source(j_decompress_ptr cinfo){ cinfo->src->next_input_byte = inptr->start; cinfo->src->bytes_in_buffer = inptr->size;}static voidfill_input_buffer(j_decompress_ptr cinfo){ return;}static voidskip_input_data(j_decompress_ptr cinfo, long num_bytes){ if (num_bytes >= inptr->size) return; cinfo->src->next_input_byte += num_bytes; cinfo->src->bytes_in_buffer -= num_bytes;}static booleanresync_to_restart(j_decompress_ptr cinfo, int desired){ return jpeg_resync_to_restart(cinfo, desired);}static voidterm_source(j_decompress_ptr cinfo){ return;}static intLoadJPEG(buffer_t * src, PMWIMAGEHDR pimage, PSD psd, MWBOOL fast_grayscale){ int i; int ret = 2; /* image load error */ unsigned char magic[8]; struct jpeg_source_mgr smgr; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr;#if FASTJPEG extern MWPALENTRY mwstdpal8[256];#else MWPALENTRY palette[256];#endif /* 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, 8); if (strncmp(magic+4, "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 = (void *) init_source; smgr.fill_input_buffer = (void *) fill_input_buffer; smgr.skip_input_data = (void *) skip_input_data; smgr.resync_to_restart = (void *) resync_to_restart; smgr.term_source = (void *) term_source; cinfo.src = &smgr; inptr = src; /* 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 = 256; } 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(pimage->bpp <= 8) { pimage->palette = malloc(256*sizeof(MWPALENTRY)); if(!pimage->palette) goto err; if (fast_grayscale) { for (i=0; i<256; ++i) { MWPALENTRY pe; /* FIXME could use static palette here*/ pe.r = pe.g = pe.b = i; pimage->palette[i] = pe; } } else {#if FASTJPEG /* FASTJPEG case only, normal uses hw palette*/ 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_JPEG_SUPPORT)*/#if 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. *//* This is a quick user defined function to read from the buffer instead of from the file pointer */static voidpng_read_buffer(png_structp pstruct, png_bytep pointer, png_size_t size){ bread(pstruct->io_ptr, pointer, size);}static intLoadPNG(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, SEEK_SET); 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; } /* Set up the input function */ png_set_read_fn(state, src, png_read_buffer); /* png_init_io(state, src); */ 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -