/* Copyright (c) 2004-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkfigpi.c PDF image information module. */ /** Inside the dkfigpi module. */ #define DKFIGPI_C 1 #include "dkfig.h" $(trace-include) /** Abbreviation for dkfig_pdf_output_instruction. */ typedef dkfig_pdf_output_instruction OI; /** Image type: unknown. */ #define WHAT_NONE (-1) /** Image type: PNG */ #define WHAT_PNG 0 /** Image type: JPEG. */ #define WHAT_JPG 1 /** Image type: NetPBM. */ #define WHAT_PBM 2 /** Image information. */ typedef struct { int what; /**< Image type. */ union { int dummy ; /**< Dummy if no library available at all. */ #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H struct { png_structp pp; /**< Read struct. */ png_infop pi; /**< Information struct. */ png_byte **array; /**< Pixel data. */ } p; /**< PNG image information. */ #endif #endif #if DK_HAVE_JPEGLIB_H struct { JSAMPLE **array; /**< Pixel data. */ JSAMPROW color_map0; /**< Color map 0. */ JSAMPROW color_map1; /**< Color map 1. */ JSAMPROW color_map2; /**< Color map 2. */ struct jpeg_decompress_struct cinfo; /**< Decompression struct. */ struct jpeg_error_mgr jerr; /**< Error handling. */ int state; /**< State of reader. */ int what_to_do; } j; /**< JPEG image information. */ #endif #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H struct { int format; /**< NetPBM sub format. */ xel **array; /**< Pixel data array. */ xelval maxxelval; /**< Maximum pixel value. */ } n; /**< NetPBM image information. */ #endif } d; /**< Image information data. */ } image_data; /** Abbreviation. */ typedef image_data IDATA; /** File type suffixes we can handle. */ static char *file_suffixes[] = { "png", "jpg", "jpeg", "pbm", "pgm", "ppm", "pnm", NULL }; /** File open mode: read binary. */ static char str_mode_read_binary[] = { "rb" }; /** File open mode: write binary. */ static char str_mode_write_binary[] = { "wb" }; /** Get file type for name by inspecting the suffix. @param n File name. @return File type WHAT_xxx. */ static int get_file_type DK_P1(char *,n) { int back = -1, cs, x; if(n) { char *ptr; cs = 0; ptr = dksf_get_file_type_dot(n); if(ptr) { ptr++; x = dkstr_array_index(file_suffixes, ptr, cs); switch(x) { case 0: { back = WHAT_PNG; } break; case 1: case 2: { back = WHAT_JPG; } break; case 3: case 4: case 5: case 6: { back = WHAT_PBM; } break; } } } return back; } /** Initialize new image information structure. @param i Structure to initialize. */ static void null_image DK_P1(IDATA *,i) { DK_MEMRES((void *)i, sizeof(IDATA)); i->what = -1; } #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H /** Release memory allocated for PNG pixel data. @param array Array to release. @param he Image height (number of rows in array). */ static void release_png_memory DK_P2(png_byte **,array, png_uint_32,he) { png_byte *xptr, **ptr; png_uint_32 y; if(array) { ptr = array; for(y = 0; y < he; y++) { xptr = *ptr; if(xptr) { dkmem_free(xptr); } *(ptr++) = NULL; } dkmem_free(array); } } /** Allocate memory for PNG pixel data. @param h Number of rows in image. @param rowbytes Number of bytes needed for each row. @return Pointer to new array on success, NULL on error. */ static png_byte ** allocate_png_memory DK_P2(png_uint_32,h, png_uint_32,rowbytes) { png_byte **back = NULL, **ptr; png_uint_32 y; int ok; $? "+ allocate_png_memory" back = (png_byte **)dkmem_alloc(sizeof(png_bytep),h); if(back) { ptr = back; for(y = 0; y < h; y++) { *(ptr++) = NULL; } ptr = back; ok = 1; for(y = 0; y < h; y++) { *ptr = (png_bytep)dkmem_alloc(sizeof(png_byte),rowbytes); if(!(*ptr)) { ok = 0; } ptr++; } if(!ok) { release_png_memory(back, h); back = NULL; } } $? "- allocate_png_memory %s", TR_PTR(back) return back; } /** Read image to memory. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int read_png_image DK_P2(OI *,oi, IDATA *,idata) { int back = 0; FILE *inputfile; unsigned long w; /* width */ unsigned long h; /* height */ int b; /* bit depth (bits per pixel) */ int c; /* color type */ int i; /* interlace */ int z; /* compression type */ int f; /* filter type */ int ch; /* channels */ int ne, ns, np; unsigned long rowbytes; $? "+ read_png_image" (idata->d).p.array = NULL; (idata->d).p.pp = NULL; (idata->d).p.pi = NULL; ne = ns = np = 0; inputfile = dkapp_fopen( (oi->c)->app, (oi->ci)->inputfilename, str_mode_read_binary ); if(inputfile) { $? ". inputfile \"%s\"ok", (oi->ci)->inputfilename (idata->d).p.pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if((idata->d).p.pp) { $? ". pp ok" (idata->d).p.pi = png_create_info_struct((idata->d).p.pp); if((idata->d).p.pi) { $? ". pi ok" #if DK_HAVE_SETJMP_H if(setjmp(((idata->d).p.pp)->jmpbuf) == 0) { #endif png_init_io((idata->d).p.pp, inputfile); png_read_info((idata->d).p.pp, (idata->d).p.pi); png_get_IHDR( (idata->d).p.pp, (idata->d).p.pi, &w, &h, &b, &c, &i, &z, &f ); ch = png_get_channels((idata->d).p.pp, (idata->d).p.pi); $? ". width = %lu", w $? ". height = %lu", h $? ". bitdepth = %d", b $? ". colortype = %d", c $? ". interlace = %d", i $? ". compressiontype = %d", z $? ". filtertype = %d", f $? ". channels = %d", ch if((c == PNG_COLOR_TYPE_PALETTE) && (b <= 8)) { ne = 1; $? ". ne=1" } if((c == PNG_COLOR_TYPE_GRAY) && (b < 8)) { ne = 1; $? ". ne=1" } if(png_get_valid((idata->d).p.pp, (idata->d).p.pi, PNG_INFO_tRNS)) { ne = 1; $? ". ne=1" } if(b > 8) { ns = 1; $? ". ns=1" } else { if(b < 8) { np = 1; $? ". np=1" } } if(ne) { png_set_expand((idata->d).p.pp); } if(ns) { png_set_strip_16((idata->d).p.pp); } if(np) { png_set_packing((idata->d).p.pp); } /* if(png_get_bKGD()) { } else { } */ png_read_update_info((idata->d).p.pp, (idata->d).p.pi); ch = png_get_channels((idata->d).p.pp, (idata->d).p.pi); c = png_get_color_type((idata->d).p.pp, (idata->d).p.pi); $? ". colortype = %d", c $? ". channels = %d", ch rowbytes = png_get_rowbytes((idata->d).p.pp, (idata->d).p.pi); (idata->d).p.array = allocate_png_memory(h, rowbytes); if((idata->d).p.array) { png_read_image((idata->d).p.pp, (idata->d).p.array); back = 1; (oi->ci)->w = w; (oi->ci)->h = h; (oi->ci)->bpp = b; (oi->ci)->ch = ch; } else { dkfig_tool2_simple_error_message(oi->c, 82); } #if DK_HAVE_SETJMP_H } else { dkfig_tool2_combined_error_message(oi->c, 96, 97, (oi->ci)->inputfilename); } #endif } else { dkfig_tool2_simple_error_message(oi->c, 83); } } else { dkfig_tool2_simple_error_message(oi->c, 82); } fclose(inputfile); inputfile = NULL; } else { if((oi->c)->app) { dkapp_err_fopenr((oi->c)->app, (oi->ci)->inputfilename); } } $? "- read_png_image %d", back return back; } #endif #endif #if DK_HAVE_JPEGLIB_H /** Flag: Error encountered while reading JPEG file (0=no error). */ static int had_error = 0; /** Error handling function (do not exit, set error code instead). @param cinfo JPEG reader structure. */ static void error_exit_replacement DK_P1(j_common_ptr,cinfo) { had_error = 1; } /** Pointer definition. */ typedef JSAMPLE *jsptr; /** Release memory used for JPEG pixels. @param p Array pointer. @param h Number of rows in image (elements in array). */ static void release_jpeg_memory DK_P2(JSAMPLE **,p, JDIMENSION,h) { JSAMPLE *xptr, **ptr; JDIMENSION y; $? "+ release_jpeg_memory" ptr = p; y = h; while(y--) { $? ". release row %lu", (unsigned long)y if(*ptr) { xptr = *ptr; dkmem_free(xptr); *ptr = NULL; ptr++; } } dkmem_free(p); $? "- release_jpeg_memory" } /** Allocate memory to read JPEG image. @param rl Row length in bytes. @param h Number of rows in image. @return Pointer to memory on success, NULL on error. */ static JSAMPLE ** allocate_jpeg_memory DK_P2(size_t,rl, size_t,h) { int ok = 1; JSAMPLE **back = NULL, **ptr = NULL; JDIMENSION y; $? "+ allocate_jpeg_memory" back = (JSAMPLE **)dkmem_alloc(sizeof(jsptr),h); if(back) { ptr = back; y = h; while(y--) { *ptr = (JSAMPLE *)dkmem_alloc(1,rl); if(!(*ptr)) { ok = 0; } ptr++; } if(!ok) { release_jpeg_memory(back,h); back = NULL; } } $? "- allocate_jpeg_memory %s", TR_PTR(back) return back; } /** Read JPEG image into memory. @param oi OI structure. @param idata Image information structure. @return Pointer to pixel data on success, NULL on error. */ static JSAMPLE **read_jpeg_file DK_P2(OI *,oi, IDATA *,idata) { JSAMPLE **back = NULL, **ptr; JDIMENSION w, h, y; size_t sz; int ok; $? "+ read_jpeg_file" sz = (idata->d).j.cinfo.output_width; sz = sz * (idata->d).j.cinfo.output_components * sizeof(JSAMPLE); back = allocate_jpeg_memory(sz, (idata->d).j.cinfo.output_height); if(back) { w = (idata->d).j.cinfo.output_width; h = (idata->d).j.cinfo.output_height; ptr = back; ok = 1; while(h && ok) { y = jpeg_read_scanlines(&((idata->d).j.cinfo), ptr, h); if(!had_error) { if(y > 0) { ptr = &(ptr[y]); h = h - y; } else { ok = 0; } } else { ok = 0; } } if(ok) { $? ". success" (oi->ci)->w = (unsigned long)((idata->d).j.cinfo.output_width); (oi->ci)->h = (unsigned long)((idata->d).j.cinfo.output_height); (oi->ci)->bpp = 8; if((idata->d).j.cinfo.quantize_colors) { /* quantized colors */ (idata->d).j.what_to_do = 1; (idata->d).j.color_map0 = ((idata->d).j.cinfo.colormap)[0]; if((idata->d).j.cinfo.out_color_space == JCS_GRAYSCALE) { (oi->ci)->ch = 1; (idata->d).j.what_to_do = 2; } else { (oi->ci)->ch = 3; (idata->d).j.color_map1 = ((idata->d).j.cinfo.colormap)[1]; (idata->d).j.color_map2 = ((idata->d).j.cinfo.colormap)[2]; } } else { /* colors not quantized */ if((idata->d).j.cinfo.out_color_space == JCS_GRAYSCALE) { (oi->ci)->ch = 1; } else { (oi->ci)->ch = 3; } } } else { release_jpeg_memory(back, (idata->d).j.cinfo.output_height); back = NULL; dkfig_tool2_simple_error_message(oi->c, 80); $? "! Error while reading JPEG" } } else { dkfig_tool2_simple_error_message(oi->c, 81); } $? "- read_jpeg_file %s", TR_PTR(back) return back; } /** Read JPEG image into image information structure. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int read_jpg_image DK_P2(OI *,oi, IDATA *,idata) { int back = 0; FILE *inputfile; $? "+ read_jpg_image %s", TR_STR((oi->ci)->inputfilename) had_error = 0; (idata->d).j.state = 0; (idata->d).j.color_map0 = NULL; (idata->d).j.color_map1 = NULL; (idata->d).j.color_map2 = NULL; (idata->d).j.what_to_do = 0; (idata->d).j.cinfo.err = jpeg_std_error(&((idata->d).j.jerr)); (idata->d).j.jerr.error_exit = error_exit_replacement; jpeg_create_decompress(&((idata->d).j.cinfo)); if(!had_error) { (idata->d).j.state = 1; inputfile = dkapp_fopen((oi->c)->app,(oi->ci)->inputfilename, str_mode_read_binary ); if(inputfile) { (idata->d).j.array = NULL; jpeg_stdio_src(&((idata->d).j.cinfo), inputfile); if(!had_error) { (idata->d).j.state = 2; jpeg_read_header(&((idata->d).j.cinfo), TRUE); if(!had_error) { (idata->d).j.state = 3; jpeg_start_decompress(&((idata->d).j.cinfo)); if(!had_error) { (idata->d).j.state = 4; (oi->ci)->w = (unsigned long)((idata->d).j.cinfo.output_width); (oi->ci)->h = (unsigned long)((idata->d).j.cinfo.output_height); (idata->d).j.array = read_jpeg_file(oi,idata); if((idata->d).j.array) { $? ". success" back = 1; jpeg_finish_decompress(&((idata->d).j.cinfo)); } else { $? "! failed to read file" jpeg_abort((j_common_ptr)(&((idata->d).j.cinfo))); dkfig_tool2_simple_error_message(oi->c, 80); } } else { jpeg_abort((j_common_ptr)(&((idata->d).j.cinfo))); dkfig_tool2_simple_error_message(oi->c, 79); } } else { jpeg_abort((j_common_ptr)(&((idata->d).j.cinfo))); dkfig_tool2_simple_error_message(oi->c, 78); } } else { jpeg_abort((j_common_ptr)(&((idata->d).j.cinfo))); dkfig_tool2_simple_error_message(oi->c, 77); } fclose(inputfile); inputfile = NULL; } else { if((oi->c)->app) { dkapp_err_fopenr((oi->c)->app, (oi->ci)->inputfilename); } } } else { dkfig_tool2_simple_error_message(oi->c, 76); } $? "- read_jpeg_image %d",back return back; } #endif #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H /** Read NetPBM image into image information structure. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int read_pbm_image DK_P2(OI *,oi, IDATA *,idata) { int back = 0, cols = 0, rows = 0; FILE *inf; dkfig_tool_init_netpbm(oi->c); (idata->d).n.format = 0; (idata->d).n.array = NULL; (idata->d).n.maxxelval = 0; inf = dkapp_fopen( (oi->c)->app, (oi->ci)->inputfilename, str_mode_read_binary ); if(inf) { (idata->d).n.array = pnm_readpnm( inf, &cols, &rows, &((idata->d).n.maxxelval), &((idata->d).n.format) ); if((idata->d).n.array) { back = 1; (oi->ci)->w = cols; (oi->ci)->h = rows; (oi->ci)->bpp = 8; if(PNM_FORMAT_TYPE((idata->d).n.format) == PPM_TYPE) { (oi->ci)->ch = 3; } else { (oi->ci)->ch = 1; } } else { dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_ERROR, 71, 61, (oi->ci)->inputfilename); } fclose(inf); inf = NULL; } else { if((oi->c)->app) { dkapp_err_fopenr((oi->c)->app, (oi->ci)->inputfilename); } } return back; } #endif /** Release image information structure. @param oi OI structure. @param idata Image information structure to release. */ static void release_image DK_P2(OI *,oi, IDATA *,idata) { $? "+ release_image" $? ". flip style = %d", (oi->ci)->flipped switch(idata->what) { case WHAT_PNG: { $? ". release PNG" #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H if((idata->d).p.array) { $? ". release memory" release_png_memory((idata->d).p.array, (oi->ci)->h); (idata->d).p.array = NULL; } if((idata->d).p.pp) { if((idata->d).p.pi) { $? ". release info struct" png_destroy_info_struct((idata->d).p.pp, &((idata->d).p.pi)); (idata->d).p.pi = NULL; } $? ". release read struct" png_destroy_read_struct(&((idata->d).p.pp), NULL, NULL); (idata->d).p.pp = NULL; } #endif #endif } break; case WHAT_JPG: { $? ". release JPG" #if DK_HAVE_JPEGLIB_H if((idata->d).j.state >= 1) { $? ". release decompressor" jpeg_destroy_decompress(&((idata->d).j.cinfo)); } if((idata->d).j.array) { $? ". release memory" release_jpeg_memory((idata->d).j.array, (oi->ci)->h); } else { $? "! Something is wrong" } (idata->d).j.array = NULL; #endif } break; case WHAT_PBM: { #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H if((idata->d).n.array) { pnm_freearray((idata->d).n.array, (oi->ci)->h); } (idata->d).n.array = NULL; #endif } break; } $? "- release_image" } /** Read image into image information structure. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int read_image DK_P2(OI *,oi, IDATA *,idata) { int back = 0; $? "+ read_image %s", TR_STR((oi->ci)->inputfilename) idata->what = get_file_type((oi->ci)->inputfilename); switch(idata->what) { case WHAT_PNG: { $? ". PNG" #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H back = read_png_image(oi, idata); #endif #endif } break; case WHAT_JPG: { $? ". JPG" #if DK_HAVE_JPEGLIB_H back = read_jpg_image(oi, idata); #endif } break; case WHAT_PBM: { $? ". PBM" #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H back = read_pbm_image(oi, idata); #endif } break; default: { dkfig_tool2_simple_error_message(oi->c, 111); } break; } $? "- read_image %d", back return back; } /** Attach a temporary file name for alpha channel. @param oi OI structure. @return 1 on success (no file name needed or file name ok), 0 on error. */ static int attach_filenames DK_P1(OI *,oi) { int back = 0; long mpl; char *buffer; $? "+ attach_filenames" mpl = dksf_get_maxpathlen(); buffer = dk_new(char,mpl); if(buffer) { if(dkapp_tmpnam((oi->c)->app, buffer, mpl)) { (oi->ci)->ofn = dkstr_dup(buffer); if((oi->ci)->ofn) { switch((oi->ci)->ch) { case 2: case 4: { if(dkapp_tmpnam((oi->c)->app, buffer, mpl)) { (oi->ci)->afn = dkstr_dup(buffer); if((oi->ci)->afn) { back = 1; } } if(oi->d) { (oi->d)->opt2 |= DKFIG_OPT_HAVE_ALPHA_CHANNEL; } } break; default: { (oi->ci)->afn = NULL; back = 1; } break; } } } dk_delete(buffer); buffer = NULL; } $? "- attach_filenames %d", back return back; } #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H /** Normalize a pixel value. @param v Original pixel value. @param mx Original maximum value. @param max New maximum value. @return Converted value. */ static int normalize_pnm DK_P3(int,v, xelval,mx, int,max) { int back; long l1, l2, l3, l4; $? "+ normalize_pnm %d %ld %d", v, (long)mx, max back = v; if((int)mx != max) { l1 = v; l2 = max; l3 = (long)mx; l4 = (l1 * l2) / l3; back = (int)l4; } $? "- normalize_pnm %d", back return back; } #endif /** Get one byte from image. @param idata Image information structure. @param x X position of pixel. @param y Y position of pixel. @param ch Number of channels in image. @param ind Channel to get value for. @return The byte. */ static unsigned char get_byte DK_P5(IDATA *,idata, unsigned long,x, unsigned long,y, int,ch, int,ind) { unsigned char back = 0x00; switch(idata->what) { case WHAT_PNG: { #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H png_byte *rptr, **array; array = (idata->d).p.array; rptr = array[y]; back = rptr[(x * ch) + ind]; #endif #endif } break; case WHAT_JPG: { #if DK_HAVE_JPEGLIB_H JSAMPLE *rptr; int r; rptr = ((idata->d).j.array)[y]; switch((idata->d).j.what_to_do) { case 2: { /* grayscaled mapped */ r = rptr[(x * ch) + ind]; back = ((idata->d).j.color_map0)[r & 0xFF]; } break; case 1: { /* color mapped */ r = rptr[(x * ch) + ind]; switch(ind) { case 2: { back = ((idata->d).j.color_map2)[r & 0xFF]; } break; case 1: { back = ((idata->d).j.color_map1)[r & 0xFF]; } break; default: { back = ((idata->d).j.color_map0)[r & 0xFF]; } break; } } break; default: { back = rptr[(x * ch) + ind]; } break; } #endif } break; case WHAT_PBM: { #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H xel xe; int r; xe = (((idata->d).n.array)[y])[x]; if(PNM_FORMAT_TYPE((idata->d).n.format) == PPM_TYPE) { switch(ind) { case 2: { r = (int)(PPM_GETB(xe)); } break; case 1: { r = (int)(PPM_GETG(xe)); } break; default: { r = (int)(PPM_GETR(xe)); } break; } r = normalize_pnm(r, (idata->d).n.maxxelval, 255); back = r & 0xFF; } else { r = (int)(PNM_GET1(xe)); r = normalize_pnm(r, (idata->d).n.maxxelval, 255); back = r & 0xFF; } #endif } break; } return back; } /** Write information for one pixel to compressed stream. @param oi OI structure. @param idata Image information structure. @param strm Output stream (compressing and encoding). @param x X position of pixel. @param y Y position of pixel. @param isalpha Ignored. */ static void handle_position DK_P6(OI *,oi, IDATA *,idata, dk_stream_t *,strm, unsigned long,x, unsigned long,y, int,isalpha) { unsigned char uc[5]; switch((oi->ci)->ch) { case 1: case 2: { uc[0] = get_byte(idata,x,y,(oi->ci)->ch, 0); uc[1] = '\0'; dkstream_write(strm,(char *)uc,1); } break; case 3: case 4: { uc[0] = get_byte(idata,x,y,(oi->ci)->ch, 0); uc[1] = get_byte(idata,x,y,(oi->ci)->ch, 1); uc[2] = get_byte(idata,x,y,(oi->ci)->ch, 2); uc[3] = '\0'; dkstream_write(strm,(char *)uc,3); } break; } } /** Create compressed an encoded data stream for image. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int write_data_stream DK_P2(OI *,oi, IDATA *,idata) { int back = 0; unsigned long x, y; $? "+ write_data_stream" dk_stream_t *pstr, *cstr; pstr = dkapp_stream_openfile( (oi->c)->app, (oi->ci)->ofn, str_mode_write_binary ); if(pstr) { cstr = dkof_open(pstr, 3); if(cstr) { back = 1; dkof_set_crnl(cstr,1); if(!dkof_set(cstr,0,DK_OF_TYPE_BUFFERED)) { back = 0; } if(!dkof_set(cstr,1,DK_OF_TYPE_ASCII85)) { back = 0; } if(!dkof_set(cstr,2,DK_OF_TYPE_FLATE)) { back = 0; } if(back) { back = 0; if(dkof_start_chunk(cstr)) { switch((oi->ci)->flipped) { case 1: { /* horiz */ for(y = 0; y < (oi->ci)->h; y++) { for(x = (oi->ci)->w; x > 0; x--) { handle_position(oi,idata,cstr,(x-1),y,0); } } } break; case 2: { /* diag */ for(x = 0; x < (oi->ci)->w; x++) { for(y = 0; y < (oi->ci)->h; y++) { handle_position(oi,idata,cstr,x,y,0); } } } break; default: { /* not flipped */ for(y = 0; y < (oi->ci)->h; y++) { for(x = 0; x < (oi->ci)->w; x++) { handle_position(oi,idata,cstr,x,y,0); } } } break; } if(dkof_end_chunk(cstr)) { back = 1; } } } dkof_close(cstr); cstr = NULL; } else { dkfig_tool2_simple_error_message(oi->c, 72); } (oi->ci)->ol = dkstream_get_bytes_written(pstr); dkstream_close(pstr); pstr = NULL; } else { dkfig_tool2_simple_error_message(oi->c, 72); } $? "- write_data_stream %d", back return back; } /** Write alpha data to stream. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int write_alpha_stream DK_P2(OI *,oi, IDATA *,idata) { int back = 0; unsigned long x, y; unsigned char uc; $? "+ write_alpha_stream" dk_stream_t *pstr, *cstr; pstr = dkapp_stream_openfile( (oi->c)->app, (oi->ci)->afn, str_mode_write_binary ); if(pstr) { cstr = dkof_open(pstr, 3); if(cstr) { back = 1; dkof_set_crnl(cstr,1); if(!dkof_set(cstr,0,DK_OF_TYPE_BUFFERED)) { back = 0; } if(!dkof_set(cstr,1,DK_OF_TYPE_ASCII85)) { back = 0; } if(!dkof_set(cstr,2,DK_OF_TYPE_FLATE)) { back = 0; } if(back) { back = 0; if(dkof_start_chunk(cstr)) { switch((oi->ci)->flipped) { case 1: { /* horiz */ for(y = 0; y < (oi->ci)->h; y++) { for(x = (oi->ci)->w; x > 0; x--) { uc = get_byte(idata,(x - 1),y,(oi->ci)->ch,((oi->ci)->ch - 1)); dkstream_write(cstr,(char *)(&uc),1); } } } break; case 2: { /* diag */ for(x = 0; x < (oi->ci)->w; x++) { for(y = 0; y < (oi->ci)->h; y++) { uc = get_byte(idata,x,y,(oi->ci)->ch,((oi->ci)->ch - 1)); dkstream_write(cstr,(char *)(&uc),1); } } } break; default: { /* not flipped */ for(y = 0; y < (oi->ci)->h; y++) { for(x = 0; x < (oi->ci)->w; x++) { uc = get_byte(idata,x,y,(oi->ci)->ch,((oi->ci)->ch - 1)); dkstream_write(cstr,(char *)(&uc),1); } } } break; } if(dkof_end_chunk(cstr)) { back = 1; } } } dkof_close(cstr); cstr = NULL; } else { dkfig_tool2_simple_error_message(oi->c, 72); } (oi->ci)->al = dkstream_get_bytes_written(pstr); dkstream_close(pstr); pstr = NULL; } else { dkfig_tool2_simple_error_message(oi->c, 72); } $? "- write_alpha_stream %d", back return back; } /** Write image data. @param oi OI structure. @param idata Image information structure. @return 1 on success, 0 on error. */ static int write_image DK_P2(OI *,oi, IDATA *,idata) { int back = 0; $? "+ write_image %s", TR_STR((oi->ci)->inputfilename) if(attach_filenames(oi)) { if(write_data_stream(oi, idata)) { switch((oi->ci)->ch) { case 2: case 4: { if(write_alpha_stream(oi, idata)) { back = 1; } } break; default: { back = 1; } break; } } } $? "- write_image %d", back return back; } /** Prepare image for writing to PDF output. @param oi OI structure. @return 1 on success, 0 on error. */ static int prepare_image DK_P1(OI *,oi) { int back = 0; image_data idata; $? "+ prepare_image %s", TR_STR((oi->ci)->inputfilename) null_image(&idata); if(read_image(oi, &idata)) { if(write_image(oi, &idata)) { back = 1; } } release_image(oi, &idata); $? "- prepare_image %d", back return back; } /** Prepare to show image. @param oi PDF output instruction structure. @return 1 on success, 0 on error. */ int dkfigpi_prepare_image DK_P1(OI *,oi) { int back = 0; unsigned long oldlineno; if(oi) { if(oi->c) { if((oi->c)->app) { oldlineno = dkapp_get_source_lineno((oi->c)->app); dkapp_set_source_lineno((oi->c)->app, (oi->ci)->lineno); back = prepare_image(oi); if(!back) { dkfig_tool2_msg3( oi->c, DK_LOG_LEVEL_ERROR, 112, 61, (oi->ci)->inputfilename ); } dkapp_set_source_lineno((oi->c)->app, oldlineno); } } } return back; }