%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% header #include "dk3conf.h" #include "dk3types.h" #ifdef __cplusplus extern "C" { #endif /** Check whether a bitmap image file type is supported. @param tp File type to check. @return 1 for supported types, 0 otherwise. */ int dk3bif_type_supported(int tp); /** Check file name suffix (dkChar). @param sn File name suffix without the dot. @return Bitmap image file type. */ int dk3bif_check_suffix_without_dot(dkChar const *sn); /** Check file name suffix (char). @param sn File name suffix without the dot. @return Bitmap image file type. */ int dk3bif_check_c8_suffix_without_dot(char const *sn); /** Check file name suffix (dkChar). @param fn File name to check. @return Bitmap image file type. */ int dk3bif_check_file_name(dkChar const *fn); /** Check file name suffix (char). @param fn File name to check. @return Bitmap image file type. */ int dk3bif_check_c8_file_name(char const *fn); /** Open bitmap image file (dkChar). @param fn File name. @param tp Bitmap type. @param app Application structure for diagnostics, may not be NULL. @return Pointer to BIF on success, NULL on error. */ dk3_bif_t * dk3bif_open_filename_app(dkChar const *fn, int tp, dk3_app_t *app); /** Open bitmap image file (char). @param fn File name. @param tp Bitmap type. @param app Application structure for diagnostics, may not be NULL. @return Pointer to BIF on success, NULL on error. */ dk3_bif_t * dk3bif_open_c8_filename_app(char const *fn, int tp, dk3_app_t *app); /** Open bitmap image file. @param fipo File, opened for binary reading. @param tp Bitmap type. @param app Application structure for diagnostics, may not be NULL. @return Pointer to BIF on success, NULL on error. */ dk3_bif_t * dk3bif_open_file_app(FILE *fipo, int tp, dk3_app_t *app); /** Retrieve image type. @param bp Bitmap image file. @return Image type, DK3_BIF_IMAGE_TYPE_xxx, see @ref bifimagetypes. */ int dk3bif_get_type(dk3_bif_t *bp); /** Get width of current frame. @param bp Bitmap image file. @return Image width. */ dk3_bif_coord_t dk3bif_get_width(dk3_bif_t *bp); /** Get height of current frame. @param bp Bitmap image file. @return Image height. */ dk3_bif_coord_t dk3bif_get_height(dk3_bif_t *bp); /** Get width of widest frame. @param bp Bitmap image file. @return Image width. */ dk3_bif_coord_t dk3bif_get_largest_width(dk3_bif_t *bp); /** Get height of highest frame. @param bp Bitmap image file. @return Image height. */ dk3_bif_coord_t dk3bif_get_largest_height(dk3_bif_t *bp); /** Set background color on per-file base. Use this function after opening the bitmap image file but before dk3bif_read_data(). @param bp Bitmap image file. @param r Red. @param g Green. @param b Blue. @param f Force flag: 0=use background color chunk from file if available, 1=always use the color specified here. */ void dk3bif_set_background( dk3_bif_t *bp, dk3_bif_pixel_t r, dk3_bif_pixel_t g, dk3_bif_pixel_t b, int f ); /** Read image data. @param bp Bitmap image file. @return 1 on success, 0 on error. */ int dk3bif_read_data(dk3_bif_t *bp); /** Find number of frames in image file. @param bp Bitmap image file. @return Number of frames in the file. */ size_t dk3bif_number_of_frames(dk3_bif_t *bp); /** Set current frame number. @param bp Bitmap image file. @param fn Number of frame to process. @return 1 on success, 0 on error. */ int dk3bif_set_frame(dk3_bif_t *bp, size_t fn); /** Reset internal current frame pointer, so the next dk3bif_next_frame() call returns the first frame. @param bp Bitmap image file. */ void dk3bif_reset_frames(dk3_bif_t *bp); /** Switch to the next frame. @param bp Bitmap image file. @return 1 on success, 0 on error (no more frames). */ int dk3bif_next_frame(dk3_bif_t *bp); /** Check whether a bitmap image is really colored. @param bp Bitmap image file. @return 1 for colored image, 0 for grey. */ int dk3bif_is_colored(dk3_bif_t *bp); /** Retrieve number of bits per pixel for current frame. @param bp Bitmap image file. @return Number of bits per pixel used in the file. */ size_t dk3bif_get_bits_per_pixel(dk3_bif_t *bp); /** Retrieve number of bits per pixel for current frame really containing information. This function returns a useful result only if dk3bif_analyze() was run with DK3_ANALYSIS_BITS before. @param bp Bitmap image file. @return Number of non-redundant bits per pixel. */ size_t dk3bif_real_bits_per_pixel(dk3_bif_t *bp); /** Retrieve information whether colors are really used. This function returns a useful result only if dk3bif_analyze() was run with DK3_BIF_ANALYSIS_COLOR before. @param bp Bitmap image file. @return 1 for colors, 0 for gray. */ int dk3bif_real_color(dk3_bif_t *bp); /** Retrieve information whether alpha channel is really used. This function returns a useful result only if dk3bif_analyze() was run with DK3_BIF_ANALYSIS_ALPHA before. @param bp Bitmap image file. @return 1 for alpha channel used, 0 for unused. */ int dk3bif_real_alpha(dk3_bif_t *bp); /** Set number of bits per pixel when retrieving data. @param bp Bitmap image file. @param sz Number of bits per pixel. @return 1 on success, 0 on error. */ int dk3bif_set_bits_per_pixel(dk3_bif_t *bp, size_t sz); /** Get color space. @param bp Bitmap image file. @return The color space used by the image. */ int dk3bif_get_color_space(dk3_bif_t *bp); /** Get red component of pixel. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_red(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get green component of pixel. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_green(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get blue component of pixel. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_blue(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get gray component of pixel. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_gray(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get alpha component of pixel. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_alpha(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get red component of pixel mixed against background. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_mixed_red(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get green component of pixel mixed against background. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_mixed_green(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get blue component of pixel mixed against background. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_mixed_blue(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get gray component of pixel mixed against background. @param bp Bitmap image file. @param x X coordinate. @param y Y coordinate. @return Value corrected to requested bits per component. */ dk3_bif_pixel_t dk3bif_get_mixed_gray(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y); /** Get file to access raw data. This function is primary intended to access JPEG data. @param bp Bitmap image file. @return FILE pointer if available, NULL otherwise. */ FILE * dk3bif_get_file(dk3_bif_t *bp); /** Retrieve X resolution. @param bp Bitmap image file. @return X resolution in dpi. */ double dk3bif_get_xres(dk3_bif_t *bp); /** Retrieve Y resolution. @param bp Bitmap image file. @return Y resolution in dpi. */ double dk3bif_get_yres(dk3_bif_t *bp); /** Close bitmap image file, release memory. @param bp Bitmap image file to close. */ void dk3bif_close(dk3_bif_t *bp); /** Get original number of components for JPEG file. @param bif Bitmap image file. @return Number of components found in file on success, 0 on error. */ int dk3bif_jpeg_get_num_components(dk3_bif_t *bif); /** Check whether Adobe marker was found in JPEG input file. @param bif Bitmap image file. @return 1 if marker was found, 0 otherwise. */ int dk3bif_jpeg_get_found_adobe_marker(dk3_bif_t *bif); /** Calculate average predictor value from left and upper value. @param left Value left to the pixel. @param upper Value upper to the pixel. @return Predictor value. */ dk3_bif_pixel_t dk3bif_average(dk3_bif_pixel_t left, dk3_bif_pixel_t upper); /** Paeth prediction function. @param v1 Left value. @param v2 Upper value. @param v3 Upper left value. @return Predicted value. */ dk3_bif_pixel_t dk3bif_paeth( dk3_bif_pixel_t v1, dk3_bif_pixel_t v2, dk3_bif_pixel_t v3 ); /** Retrieve one pixel component not yet resampled. @param bp Bitmap image. @param x X coordinate. @param y Y coordinate. @param c Choose component: 0=red/gray, 1=green, 2=blue, 3=alpha. @return Pixel component. */ dk3_bif_pixel_t dk3bif_get_pixel_component_not_resampled( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ); #ifdef __cplusplus } #endif %% module #include "dk3conf.h" #include #if DK3_HAVE_PNG_H #include #else #if DK3_HAVE_SETJMP_H #include #endif #endif #if DK3_HAVE_SYS_TYPES_H #include #endif #if DK3_HAVE_STDLIB_H #include #endif #if DK3_HAVE_UNISTD_H #include #endif #if DK3_HAVE_PROCESS_H #include #endif #if DK3_HAVE_JPEGLIB_H #include #endif #if DK3_HAVE_TIFF_H #include #include #endif #if DK3_HAVE_STRING_H #include #endif #if DK3_HAVE_STRINGS_H #include #endif #if 0 #include "dk3all.h" #endif #include "dk3const.h" #include "dk3mem.h" #include "dk3str.h" #include "dk3sf.h" #include "dk3sto.h" #include "dk3bif.h" #include "dk3bifa.h" #include "dk3pixre.h" #include "dk3ma.h" #include "dk3numco.h" #include "dk3bits.h" #include "dk3app.h" $!trace-include $!trace-off /** File suffixes for images. */ static dkChar const * const dk3bif_dk_type_names[] = { $!text macro=dkT png jpeg jpg tiff tif $!end }; /** File suffixes for images. Note: Order must correpsond to the order of dk3bif_dk_type_names. */ static char const * const dk3bif_c8_type_names[] = { $!text png jpeg jpg tiff tif $!end }; /** Keywords used by the module (dkChar). */ static dkChar const * const dk3bif_kw_dk[] = { /* 0 */ dkT("rb"), NULL }; /** Keywords and texts used by the module (8-bit). */ static char const * const dk3bif_kw_c8[] = { /* 0 */ "dk3bif-%lu-%lu.tmp", /* PID, index */ /* 1 */ "dk3bif-%d-%lu.tmp", /* PID, index */ NULL }; /** Number of current temporary file within this process. */ static unsigned long dk3bif_temp_number = 0UL; static dk3_bif_frame_t * dk3bif_frame_new(dk3_bif_t *bp); #if DK3_HAVE_PNG_H /** Per frame data, PNG-specific. */ typedef struct { png_bytep *rows; png_colorp palp; png_size_t rowbytes; dk3_bif_coord_t h; dk3_bif_pixel_t bgred; dk3_bif_pixel_t bggreen; dk3_bif_pixel_t bgblue; int paln; } dk3_bif_frame_png_t; /** Per file data, PNG-specific. */ typedef struct { png_structp pp; /* Read structure. */ png_infop pi; /* PNG information. */ int ct; /* Color type. */ int im; /* Interlace method. */ int cm; /* Compression method. */ int fm; /* Filter method. */ int ch; /* Number of channels. */ int np; /* Number of interlace passes. */ } dk3_bif_png_t; /** Release type-specific information for PNG file. @param is Bitmap-type specific data. */ static void dk3bif_frame_release_implspec_png(void *is) { dk3_bif_frame_png_t *fdis; dk3_bif_coord_t i; $? "+ dk3bif_frame_release_implspec_png" fdis = (dk3_bif_frame_png_t *)is; if(fdis->rows) { $? ". delete rows" for(i = 0L; i < fdis->h; i++) { $? ". delete row %ld", i dk3_delete((fdis->rows)[i]); } dk3_delete(fdis->rows); } dk3_release(fdis); $? "- dk3bif_frame_release_implspec_png" } /** Release type specific information for PNG file (image). @param is Bitmap-type specific data. */ static void dk3bif_release_implspec_png(void *is) { dk3_bif_png_t *dis; $? "+ dk3bif_release_implspec_png" dis = (dk3_bif_png_t *)is; if(dis->pp) { if(dis->pi) { $? ". destroy info struct" png_destroy_info_struct(dis->pp, &(dis->pi)); } $? ". destroy read struct" png_destroy_read_struct(&(dis->pp), (png_infopp)NULL, (png_infopp)NULL); } dis->pp = NULL; dis->pi = NULL; dk3_release(dis); $? "- dk3bif_release_implspec_png" } /** Read header for PNG image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_png_header(dk3_bif_t *bp) { unsigned char header[9]; /* Test for PNG file header. */ dk3_bif_png_t *dis; dk3_bif_frame_png_t *fdis; #if 0 double gamma; /* Gamma value. */ #endif double dbldpi; double dblxdpi; double dblydpi; png_uint_32 w; /* Image width. */ png_uint_32 h; /* Image height. */ png_uint_32 xdpi; /* X resolution. */ png_uint_32 ydpi; /* Y resolution. */ png_uint_32 dpi; /* Resolution. */ int bd; /* Bit depth. */ int ct; /* Color type. */ int im; /* Interlace method. */ int cm; /* Compression method. */ int fm; /* Filter method. */ int ch; /* Number of channels. */ int np = 1; /* Number of interlace passes. */ size_t szh; /* Number of header bytes read. */ int back = 0; $? "+ dk3bif_read_png_header" szh = fread(header, 1, 8, bp->tmpfipo); if(szh > 0) { $? ". szh ok" if(png_sig_cmp(header, 0, szh) == 0) { dis = dk3_new_app(dk3_bif_png_t,1,bp->app); if(dis) { $? ". dis ok" bp->implspec = (void *)dis; dis->pp = NULL; dis->pi = NULL; dis->ct = 0; dis->pp = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, /* user error data */ NULL, /* user error function */ NULL /* user warning function */ ); if(dis->pp) { $? ". pp ok" #if DK3_HAVE_SETJMP_H if(setjmp(png_jmpbuf(dis->pp)) == 0) { #endif dis->pi = png_create_info_struct(dis->pp); if(dis->pi) { $? ". piok" bp->cf = dk3bif_frame_new(bp); if(bp->cf) { $? ". cf ok" fdis = dk3_new_app(dk3_bif_frame_png_t,1,bp->app); if(fdis) { $? ". fdis ok" fdis->rows = NULL; fdis->rowbytes = 0; fdis->palp = NULL; fdis->paln = 0; fdis->bgred = 255; fdis->bggreen = 255; fdis->bgblue = 255; fdis->h = 0L; (bp->cf)->implspec = (void *)fdis; /* Prepare reading. */ png_init_io(dis->pp, bp->tmpfipo); png_set_sig_bytes(dis->pp, (int)szh); /* Read file information. */ png_read_info(dis->pp, dis->pi); /* Read information about the image. */ png_get_IHDR(dis->pp,dis->pi,&w,&h,&bd,&ct,&im,&cm,&fm); ch = png_get_channels(dis->pp, dis->pi); $? ". w=%lu h=%lu ct=%d ch=%d bd=%d im=%d",w,h,ct,ch,bd,im if(png_get_valid(dis->pp, dis->pi, PNG_INFO_pHYs)) { dbldpi = dblxdpi = dblydpi = 0.0; #if DK3_HAVE_PNG_GET_PIXELS_PER_INCH dpi = png_get_pixels_per_inch(dis->pp, dis->pi); xdpi = png_get_x_pixels_per_inch(dis->pp, dis->pi); ydpi = png_get_y_pixels_per_inch(dis->pp, dis->pi); dbldpi = (double)dpi; dblxdpi = (double)xdpi; dblydpi = (double)ydpi; #else /* 0.0254 = 254 / 10000 */ dpi = png_get_pixels_per_meter(dis->pp, dis->pi); xdpi = png_get_x_pixels_per_meter(dis->pp, dis->pi); ydpi = png_get_y_pixels_per_meter(dis->pp, dis->pi); dbldpi = 0.0254 * (double)dpi; dblxdpi = 0.0254 * (double)xdpi; dblydpi = 0.0254 * (double)ydpi; dpi = (png_uint_32)dbldpi; xdpi = (png_uint_32)dblxdpi; ydpi = (png_uint_32)dblydpi; #endif if(!(xdpi)) { if(dpi) { xdpi = dpi; dblxdpi = dbldpi; } else { if(ydpi) { xdpi = ydpi; dblxdpi = dblydpi; } } } if(!(ydpi)) { if(dpi) { ydpi = dpi; dblydpi = dbldpi; } else { if(xdpi) { ydpi = xdpi; dblydpi = dblxdpi; } } } if((xdpi) && (ydpi)) { (bp->cf)->xres = dblxdpi; (bp->cf)->yres = dblydpi; if((xdpi == 72UL) && (ydpi == 72UL)) { (bp->cf)->xres = (bp->cf)->yres = -1.0; } } $? ". resolution %lg %lg", (bp->cf)->xres, (bp->cf)->yres } /* Establish transformations. */ if(ct == PNG_COLOR_TYPE_PALETTE) { /* Convert palette image to RGB */ png_set_palette_to_rgb(dis->pp); } if(png_get_valid(dis->pp, dis->pi, PNG_INFO_tRNS)) { /* Get alpha values if available */ png_set_tRNS_to_alpha(dis->pp); } #if !DK3_WORDS_BIGENDIAN if(bd == 16) { /* Change network byte order to host byte order on x86. */ png_set_swap(dis->pp); } #endif #if 0 /* I need to find out some more about gamma correction. */ if(png_get_gAMA(dis->pp, dis->pi, &gamma)) { png_set_gamma(dis->pp, scg, gamma); } else { png_set_gamma(dis->pp, scg, 0.45455); } #endif switch(im) { case PNG_INTERLACE_ADAM7: { np = png_set_interlace_handling(dis->pp); } break; } /* Re-read information. */ png_read_update_info(dis->pp, dis->pi); png_get_IHDR(dis->pp,dis->pi,&w,&h,&bd,&ct,&im,&cm,&fm); ch = png_get_channels(dis->pp, dis->pi); $? ". w=%lu h=%lu ct=%d ch=%d bd=%d im=%d",w,h,ct,ch,bd,im (bp->cf)->w = (dk3_bif_coord_t)w; (bp->cf)->h = (dk3_bif_coord_t)h; (bp->cf)->realbits = (bp->cf)->bits = (size_t)bd; dis->ct = ct; dis->im = im; dis->cm = cm; dis->fm = fm; dis->ch = ch; dis->np = np; fdis->h = h; switch(ct) { case PNG_COLOR_TYPE_GRAY: { /* 1,2,4,8,16 */ (bp->cf)->cs = DK3_COLOR_SPACE_GRAY; back = 1; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: { /* 8,16 */ (bp->cf)->cs = DK3_COLOR_SPACE_GRAY_ALPHA; back = 1; } break; case PNG_COLOR_TYPE_PALETTE: { /* 1,2,4,8 */ (bp->cf)->cs = DK3_COLOR_SPACE_RGB; back = 1; } break; case PNG_COLOR_TYPE_RGB: { /* 8,16 */ (bp->cf)->cs = DK3_COLOR_SPACE_RGB; back = 1; } break; case PNG_COLOR_TYPE_RGB_ALPHA: { /* 8,16 */ (bp->cf)->cs = DK3_COLOR_SPACE_RGBA; back = 1; } break; } } else { $? "! memory" } } else { $? "! memory" } } else { $? "! memory" } #if DK3_HAVE_SETJMP_H } else { back = 0; } #endif } else { $? "! memory" } } else { $? "! memory" } } else { $? "! not a png file" } } else { $? "! failed to read any header data" } $? "- dk3bif_read_png_header %d", back return back; } /** Read data for PNG image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_png_data(dk3_bif_t *bp) { #if 0 png_color_16 bg; #endif png_color_16p bgp = NULL; dk3_bif_png_t *dis; dk3_bif_frame_png_t *fdis; png_bytep *rp; dk3_bif_coord_t i; int back = 0; dis = (dk3_bif_png_t *)(bp->implspec); fdis = (dk3_bif_frame_png_t *)((bp->cf)->implspec); #if DK3_HAVE_SETJMP_H if(setjmp(png_jmpbuf(dis->pp)) == 0) { #endif fdis->rowbytes = png_get_rowbytes(dis->pp, dis->pi); fdis->rows = dk3_new_app(png_bytep,(size_t)((bp->cf)->h),bp->app); if(fdis->rows) { rp = fdis->rows; for(i = 0L; i < (bp->cf)->h; i++) { *(rp++) = NULL; } back = 1; rp = fdis->rows; for(i = 0L; (i < (bp->cf)->h) && (back == 1); i++) { *rp = dk3_new_app(png_byte, fdis->rowbytes, bp->app); if(!(*rp)) { back = 0; } rp++; } if(back) { png_read_image(dis->pp, fdis->rows); if(png_get_bKGD(dis->pp, dis->pi, &bgp)) { fdis->bgred = bgp->red; fdis->bggreen = bgp->green; fdis->bgblue = bgp->blue; $? ". bg chunk %lu %lu %lu", (unsigned long)(bgp->red), (unsigned long)(bgp->green), (unsigned long)(bgp->blue) } if(dis->ct == PNG_COLOR_TYPE_PALETTE) { back = 0; png_get_PLTE(dis->pp, dis->pi, &(fdis->palp), &(fdis->paln)); if((fdis->palp) && (fdis->paln)) { back = 1; } } } } else { $? "! memory" } #if DK3_HAVE_SETJMP_H } else { back = 0; } #endif return back; } /** Retrieve one pixel component from PNG. @param bp Bitmap image. @param x X coordinate. @param y Y coordinate. @param c Choose component: 0=red/gray, 1=green, 2=blue, 3=alpha. @return Pixel component. */ static dk3_bif_pixel_t dk3bif_get_png_pixel_component( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ) { png_bytep row; dk3_bif_png_t *dis; dk3_bif_frame_png_t *fdis; dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; dk3_bif_coord_t vi; if(bp) { if(bp->cf) { if(bp->implspec) { if((bp->cf)->implspec) { dis = (dk3_bif_png_t *)(bp->implspec); fdis = (dk3_bif_frame_png_t *)((bp->cf)->implspec); if(fdis->rows) { row = (fdis->rows)[y]; vi = 0L; switch(dis->ct) { case PNG_COLOR_TYPE_GRAY: { vi = x; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: { vi = 2L * x; if(c == 3) { vi = vi + 1; } } break; case PNG_COLOR_TYPE_RGB: { vi = 3L * x; if((c >= 0) && (c < 3)) { vi = vi + (dk3_bif_coord_t)c; } } break; case PNG_COLOR_TYPE_RGB_ALPHA: { vi = 4L * x; if((c >= 0) && (c < 4)) { vi = vi + (dk3_bif_coord_t)c; } } break; default: { /* Must not happen, we requested conversion from palette to RGB. */ } break; } back = dk3pixre_get_value_from_packed_bytes( (unsigned char const *)row, vi, (bp->cf)->bits ); } } } } } return back; } #endif /* if DK3_HAVE_PNG_H */ #if DK3_HAVE_JPEGLIB_H /* JPEGLIB error management. */ /** JPEGLIB error manager. */ typedef struct { struct jpeg_error_mgr pub; /**< Default error manager. */ #if DK3_HAVE_SETJMP_H jmp_buf setjmp_buffer; /**< Buffer for setjmp. */ #endif } dk3_bif_jpg_error_mgr; /** Per frame data, JPEG-specific. */ typedef struct { JSAMPLE **rows; /**< Sample buffer. */ JDIMENSION w; /**< Image width. */ JDIMENSION h; /**< Image height. */ int is_adobe; /**< Flag: Adobe marker found. */ int num_comp; /**< Number of components found. */ } dk3_bif_frame_jpeg_t; /** Per file data, JPEG-specific. */ typedef struct { int st; struct jpeg_decompress_struct cinfo; /**< Decompression struct. */ dk3_bif_jpg_error_mgr errmgr; /**< Error manager. */ } dk3_bif_jpeg_t; /** Error exit replacement function. @param cinfo JPEG decompression structure. */ static void dk3bif_jpeg_error_exit(j_common_ptr cinfo) { dk3_bif_jpg_error_mgr *myerr = (dk3_bif_jpg_error_mgr *)(cinfo->err); if(myerr) { longjmp(myerr->setjmp_buffer, 1); } } /** Release type-specific information for JPEG file (frame). @param is Bitmap-type specific data. */ static void dk3bif_frame_release_implspec_jpeg(void *is) { dk3_bif_frame_jpeg_t *fdis; JSAMPLE **ptr; JDIMENSION i; fdis = (dk3_bif_frame_jpeg_t *)is; if(fdis->rows) { ptr = fdis->rows; for(i = 0; i < fdis->h; i++) { dk3_release(*ptr); ptr++; } dk3_delete(fdis->rows); } dk3_delete(is); } /** Release type specific information for JPEG file (image). @param is Bitmap-type specific data. */ static void dk3bif_release_implspec_jpeg(void *is) { dk3_bif_jpeg_t *dis; dis = (dk3_bif_jpeg_t *)is; if(dis->st >= 1) { #if DK3_HAVE_SETJMP_H if(setjmp((dis->errmgr).setjmp_buffer) == 0) { #endif jpeg_destroy_decompress(&(dis->cinfo)); #if DK3_HAVE_SETJMP_H } #endif } dk3_delete(dis); } /** Read header for JPEG image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_jpeg_header(dk3_bif_t *bp) { dk3_bif_jpeg_t *dis = NULL; dk3_bif_frame_jpeg_t *fdis = NULL; int back = 0; $? "+ dk3bif_read_jpeg_header" bp->cf = dk3bif_frame_new(bp); if(bp->cf) { dis = dk3_new_app(dk3_bif_jpeg_t,1,bp->app); if(dis) { bp->implspec = (void *)dis; dis->st = 0; /* Initial state. */ (dis->errmgr).pub.error_exit = dk3bif_jpeg_error_exit; (dis->cinfo).err = jpeg_std_error(&((dis->errmgr).pub)); (dis->errmgr).pub.error_exit = dk3bif_jpeg_error_exit; #if DK3_HAVE_SETJMP_H if(setjmp((dis->errmgr).setjmp_buffer) == 0) { #endif jpeg_create_decompress(&(dis->cinfo)); dis->st = 1; /* Decompress created. */ if(bp->tmpfipo) { jpeg_stdio_src(&(dis->cinfo), bp->tmpfipo); dis->st = 2; jpeg_read_header(&(dis->cinfo), TRUE); dis->st = 3; fdis = dk3_new_app(dk3_bif_frame_jpeg_t,1,bp->app); if(fdis) { (bp->cf)->implspec = (void *)fdis; fdis->is_adobe = 0; fdis->num_comp = (dis->cinfo).num_components; $? ". fdis->num_comp = %d", (int)(fdis->num_comp) fdis->rows = NULL; fdis->w = (dis->cinfo).image_width; fdis->h = (dis->cinfo).image_height; (bp->cf)->w = (dk3_bif_coord_t)(fdis->w); (bp->cf)->h = (dk3_bif_coord_t)(fdis->h); (bp->cf)->realbits = (bp->cf)->bits = 8; switch((dis->cinfo).jpeg_color_space) { case JCS_GRAYSCALE: { $? ". gray" (bp->cf)->cs = DK3_COLOR_SPACE_GRAY; } break; case JCS_RGB: { $? ". rgb" (bp->cf)->cs = DK3_COLOR_SPACE_RGB; } break; case JCS_CMYK: { $? ". cmyk" (bp->cf)->cs = DK3_COLOR_SPACE_CMYK; } break; case JCS_YCCK: { $? ". ycck" (bp->cf)->cs = DK3_COLOR_SPACE_CMYK; } break; case JCS_YCbCr: { $? ". ycbcr" (bp->cf)->cs = DK3_COLOR_SPACE_YCbCr; } break; default: { /* No setting available (yet). */ } break; } if((dis->cinfo).saw_JFIF_marker) { switch((dis->cinfo).density_unit) { case 0x01: { /* per inch */ if(((dis->cinfo).X_density) && ((dis->cinfo).Y_density)) { (bp->cf)->xres = (double)((dis->cinfo).X_density); (bp->cf)->yres = (double)((dis->cinfo).Y_density); } } break; case 0x02: { /* per cm */ if(((dis->cinfo).X_density) && ((dis->cinfo).Y_density)) { (bp->cf)->xres = 2.54 * (double)((dis->cinfo).X_density); (bp->cf)->yres = 2.54 * (double)((dis->cinfo).Y_density); } } break; } } back = 1; if((dis->cinfo).saw_Adobe_marker) { fdis->is_adobe = 1; } } } #if DK3_HAVE_SETJMP_H } else { } #endif } } $? "- dk3bif_read_jpeg_header %d", back return back; } /** Read data for JPEG image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_jpeg_data(dk3_bif_t *bp) { dk3_bif_jpeg_t *dis = NULL; dk3_bif_frame_jpeg_t *fdis = NULL; JSAMPROW *rp = NULL; JDIMENSION y; int back = 0; int ok; int occ; $? "+ dk3bif_read_jpeg_data" if(bp->implspec) { $? ". implspec ok" if(bp->cf) { $? ". cf ok" if((bp->cf)->implspec) { $? ". cf->implspec ok" dis = (dk3_bif_jpeg_t *)(bp->implspec); fdis = (dk3_bif_frame_jpeg_t *)((bp->cf)->implspec); $? ". dis/fdis" if(dis->st == 3) { $? ". state ok" #if DK3_HAVE_SETJMP_H if(setjmp((dis->errmgr).setjmp_buffer) == 0) { $? ". setjmp" #endif dis->st = 4; /* We attempted to continue. */ jpeg_start_decompress(&(dis->cinfo)); dis->st = 5; /* Decompression started. */ fdis->rows = dk3_new_app(JSAMPROW,fdis->h,bp->app); if(fdis->rows) { $? ". alloc ok" occ = (dis->cinfo).out_color_components; ok = 1; $? ". occ = %d", occ rp = fdis->rows; $? ". fdis->w=%lu", (unsigned long)(fdis->w) for(y = 0; y < fdis->h; y++) { *(rp++) = NULL; } occ = occ * fdis->w; $? ". occ = %d", occ rp = fdis->rows; for(y = 0; y < fdis->h; y++) { $? ". alloc %lu", (unsigned long)y *rp = dk3_new_app(JSAMPLE,occ,bp->app); if(!(*rp)) { ok = 0; $? "! memory" } rp++; } if(ok) { $? ". memory allocated" dis->st = 6; /* Decompression started. */ rp = fdis->rows; $? ". decompression started" for(y = 0; y < fdis->h; y++) { $? ". now %lu", (unsigned long)y jpeg_read_scanlines(&(dis->cinfo), rp, 1); rp++; $? ". line scanned" } $? ". image data read" dis->st = 7; /* Data was read successfully. */ jpeg_finish_decompress(&(dis->cinfo)); $? ". finished" dis->st = 8; /* Decompression finished. */ switch((dis->cinfo).out_color_space) { case JCS_GRAYSCALE: { $? ". now grey" (bp->cf)->cs = DK3_COLOR_SPACE_GRAY; back = 1; } break; case JCS_RGB: { $? ". now rgb" (bp->cf)->cs = DK3_COLOR_SPACE_RGB; back = 1; } break; default: { (bp->cf)->cs = 0; } break; } } else { } } else { $? "! memory" } #if DK3_HAVE_SETJMP_H } else { } #endif } else { $? "! st" } } else { $? "! cf->implspec" } } else { $? "! cf" } } $? "- dk3bif_read_jpeg_data %d", back return back; } /** Retrieve one pixel component from JPEG. @param bp Bitmap image. @param x X coordinate. @param y Y coordinate. @param c Choose component: 0=red/gray, 1=green, 2=blue, 3=alpha. @return Pixel component. */ static dk3_bif_pixel_t dk3bif_get_jpeg_pixel_component( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ) { dk3_bif_jpeg_t *dis = NULL; dk3_bif_frame_jpeg_t *fdis = NULL; dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; JSAMPLE value; JSAMPLE *row; if(bp) { if(bp->cf) { if(bp->implspec) { if((bp->cf)->implspec) { dis = (dk3_bif_jpeg_t *)(bp->implspec); fdis = (dk3_bif_frame_jpeg_t *)((bp->cf)->implspec); if(c == 3) { back = 255; } else { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: { if((c >= 0) && (c < 3)) { if(fdis->rows) { row = (fdis->rows)[y]; if(row) { value = row[x]; back = (dk3_bif_pixel_t)value; back &= 0x00FFU; } } } } break; case DK3_COLOR_SPACE_RGB: { if((c >= 0) && (c < 3)) { if(fdis->rows) { row = (fdis->rows)[y]; if(row) { value = row[3 * x + c]; back = (dk3_bif_pixel_t)value; back &= 0x00FFU; } } } } break; } } } } } } return back; } #endif /* if DK3_HAVE_JPEGLIB_H */ #if DK3_HAVE_TIFF_H /** Per frame data, TIFF-specific. */ typedef struct { uint32 *r; /**< Raster image data. */ uint32 w; /**< Image width. */ uint32 h; /**< Image height. */ uint16 cps; uint16 spp; uint16 ori; /**< Orientation. */ } dk3_bif_frame_tiff_t; /** Per file data, TIFF-specific. */ typedef struct { TIFF *tiff; } dk3_bif_tiff_t; /** Release type-specific information for TIFF file. @param is Bitmap-type specific data. */ static void dk3bif_frame_release_implspec_tiff(void *is) { dk3_bif_frame_tiff_t *fdis; fdis = (dk3_bif_frame_tiff_t *)is; if(fdis->r) { _TIFFfree(fdis->r); fdis->r = NULL; } fdis->w = fdis->h = 0UL; fdis->spp = fdis->cps = 0U; dk3_delete(fdis); } /** Release type specific information for TIFF file (image). @param is Bitmap-type specific data. */ static void dk3bif_release_implspec_tiff(void *is) { dk3_bif_tiff_t *dis; dis = (dk3_bif_tiff_t *)is; if(dis->tiff) { TIFFClose(dis->tiff); dis->tiff = NULL; } dk3_delete(dis); } /** Read header for TIFF image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_tiff_header(dk3_bif_t *bp) { dk3_bif_frame_tiff_t *fdis; dk3_bif_tiff_t *dis; float rv; #if VERSION_BEFORE_20140809 unsigned long wh = 0UL; #else dk3_um_t wh = DK3_UM_0; #endif uint32 w; uint32 h; int back = 0; int me = 0; size_t sz; uint16 cps; uint16 spp; uint16 ru; uint16 orient; $? "+ dk3bif_read_tiff_header" if(bp->tmpfn) { $? ". have tmpfn" dis = dk3_new_app(dk3_bif_tiff_t,1,bp->app); if(dis) { $? ". dis" /* Initialization of TIFF per file. */ bp->implspec = (void *)dis; dis->tiff = NULL; dis->tiff = TIFFOpen(bp->tmpfn, "rb"); if(dis->tiff) { $? ". TIFFOpen" back = 1; do { $? ". loop start" w = h = 0UL; rv = 0.0; ru = 0; cps = spp = 0U; bp->cf = dk3bif_frame_new(bp); if(bp->cf) { $? ". frame ok" (bp->cf)->realbits = (bp->cf)->bits = 8; (bp->cf)->cs = DK3_COLOR_SPACE_RGBA; fdis = dk3_new_app(dk3_bif_frame_tiff_t,1,bp->app); if(fdis) { $? ". fdis ok" /* Initialize TIFF per frame. */ fdis->w = fdis->h = 0UL; fdis->cps = fdis->spp = 0U; fdis->r = NULL; fdis->ori = ORIENTATION_BOTLEFT; (bp->cf)->implspec = (void *)fdis; if(TIFFGetField(dis->tiff, TIFFTAG_IMAGEWIDTH, &w) == 1) { fdis->w = w; $? ". width ok" (bp->cf)->w = (dk3_bif_coord_t)w; if(TIFFGetField(dis->tiff, TIFFTAG_IMAGELENGTH, &h) == 1) { fdis->h = h; $? ". height ok" (bp->cf)->h = (dk3_bif_coord_t)h; rv = 0.0; if(TIFFGetField(dis->tiff, TIFFTAG_XRESOLUTION, &rv) == 1) { (bp->cf)->xres = (double)rv; $? ". x resolution found" } rv = 0.0; if(TIFFGetField(dis->tiff, TIFFTAG_YRESOLUTION, &rv) == 1) { (bp->cf)->yres = (double)rv; $? ". y resolution found" } ru = 0; if(TIFFGetField(dis->tiff, TIFFTAG_RESOLUTIONUNIT, &ru) == 1) { $? ". resolution unit found" switch(ru) { case RESUNIT_CENTIMETER: { $? ". unit cm" (bp->cf)->xres = 2.54 * (bp->cf)->xres; (bp->cf)->yres = 2.54 * (bp->cf)->yres; } break; case RESUNIT_NONE: { $? ". other unit" (bp->cf)->xres = (bp->cf)->yres = -1.0; } break; } } orient = ORIENTATION_TOPLEFT; if(TIFFGetFieldDefaulted( dis->tiff, TIFFTAG_ORIENTATION, &orient ) == 1 ) { $? ". orientation = %u", (unsigned)orient fdis->ori = orient; switch(orient) { case 5: case 6: case 7: case 8: { $? ". swap w/h" fdis->h = w; (bp->cf)->h = w; fdis->w = h; (bp->cf)->w = h; rv = (float)((bp->cf)->xres); (bp->cf)->xres = (bp->cf)->yres; (bp->cf)->yres = rv; } break; } } else { orient = ORIENTATION_TOPLEFT; } #if VERSION_BEFORE_20140809 wh = dk3ma_ul_mul_ok(w, h, &me); wh = dk3ma_ul_mul_ok(4UL, wh, &me); #else wh = dk3ma_um_mul_ok((dk3_um_t)w, (dk3_um_t)h, &me); wh = dk3ma_um_mul_ok((dk3_um_t)4U, wh, &me); #endif if(me) { back = 0; $? "! math error" } else { $? ". wh product ok" #if VERSION_BEFORE_20140809 sz = (size_t)wh; if(wh == (unsigned long)sz) #else sz = dk3ma_um_to_sz(wh, &me); if (0 != sz) #endif { $? ". wh ok" fdis->r = (uint32 *)_TIFFmalloc(sz); if(fdis->r) { $? ". allocation ok" if(TIFFReadRGBAImageOriented( dis->tiff, w, h, fdis->r, orient, 0 ) ) { back = 1; $? ". image was read" } else { $? "! read image failed" back = 0; } } else { $? "! memory" back = 0; } } else { back = 0; $? "! numeric overflow" } } } else { $? "! height not found" back = 0; } } else { $? "! width not found" back = 0; } } else { back = 0; $? "! memory fdis" } } else { back = 0; $? "! memory bp->cf" } w = h = 0UL; cps = spp = 0U; $? ". loop end" } while((back == 1) && TIFFReadDirectory(dis->tiff)); TIFFClose(dis->tiff); dis->tiff = NULL; $? ". tiff file closed" if(bp->i_frames) { $? ". i_frames" dk3sto_it_reset(bp->i_frames); bp->cf = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames); if(!(bp->cf)) { $? "! no frame" back = 0; } } else { $? "! i_frames" } } else { $? "! TIFFOpen" } } else { $? "! dis" } } else { $? "! no file name" } $? "- dk3bif_read_tiff_header %d", back return back; } /** Read data for TIFF image. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_tiff_data(dk3_bif_t *bp) { int back = 0; if(bp->i_frames) { dk3sto_it_reset(bp->i_frames); bp->cf = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames); if(bp->cf) { back = 1; } } return back; } /** Retrieve one pixel component from TIFF. @param bp Bitmap image. @param x X coordinate. @param y Y coordinate. @param c Choose component: 0=red/gray, 1=green, 2=blue, 3=alpha. @return Pixel component. */ static dk3_bif_pixel_t dk3bif_get_tiff_pixel_component( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ) { dk3_bif_frame_tiff_t *fdis; dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; uint32 uv; if(bp) { if(bp->cf) { if(bp->implspec) { if((bp->cf)->implspec) { fdis = (dk3_bif_frame_tiff_t *)((bp->cf)->implspec); if(fdis->r) { uv = (fdis->r)[y * (bp->cf)->w + x]; /* uv = (fdis->r)[((bp->cf)->h - y - 1) * (bp->cf)->w + x]; */ switch(c) { case 3: { uv = ((uv >> 24) & 0x000000FFUL); } break; case 2: { uv = ((uv >> 16) & 0x000000FFUL); } break; case 1: { uv = ((uv >> 8) & 0x000000FFUL); } break; default: { uv = (uv & 0x000000FFUL); } break; } back = (dk3_bif_pixel_t)uv; } } } } } return back; } #endif /* if DK3_HAVE_TIFF_H */ /** Calculate gray value from red, green, blue. @param r Red value. @param g Green value. @param b Blue value. @return Gray value. */ static dk3_bif_pixel_t dk3bif_ntsc(dk3_bif_pixel_t r, dk3_bif_pixel_t g, dk3_bif_pixel_t b) { dk3_bif_pixel_t back; back = (dk3_bif_pixel_t)( ( 30UL * (unsigned long)r + 59UL * (unsigned long)g + 11UL * (unsigned long)b ) / 100UL ); return back; } /** Delete BIF frame, release memory. @param tp Image type. @param fp Frame to delete. */ static void dk3bif_frame_delete(dk3_bif_frame_t *fp, int tp) { $? "+ dk3bif_frame_delete %s", TR_PTR(fp) if(fp) { /* Release type-depending components. */ if(fp->implspec) { switch(tp) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H dk3bif_frame_release_implspec_png(fp->implspec); #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H dk3bif_frame_release_implspec_jpeg(fp->implspec); #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H dk3bif_frame_release_implspec_tiff(fp->implspec); #endif } break; } } fp->implspec = NULL; /* Release type-independent components. */ fp->w = fp->h = 0L; fp->realbits = fp->bits = fp->n = 0; fp->cs = 0; /* Release frame itself. */ dk3_delete(fp); } $? "- dk3bif_frame_delete" } /** Allocate memory for new frame. @param bp Bitmap image file. @return Pointer to new frame on success, NULL on error. */ static dk3_bif_frame_t * dk3bif_frame_new(dk3_bif_t *bp) { dk3_bif_frame_t *back = NULL; back = dk3_new_app(dk3_bif_frame_t,1,bp->app); if(back) { back->implspec = NULL; back->xres = -1.0; back->yres = -1.0; back->w = 0L; back->h = 0L; back->realbits = back->bits = 0; back->realcolor = 1; back->realalpha = 1; back->n = bp->n_frames; back->cs = 0; back->bg = 0; back->bgr = back->bgg = back->bgb = back->bggr = 0U; if(dk3sto_add(bp->s_frames, (void *)back)) { bp->n_frames += 1; } else { dk3bif_frame_delete(back, bp->bt); back = NULL; } } return back; } dk3_bif_pixel_t dk3bif_get_pixel_component_not_resampled( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_pixel_component_not_resampled %lu %lu %d", (unsigned long)x, (unsigned long)y, c if(c == 3) { $? ". alpha component asked, default is full" back = dk3pixre_get_max_value(&(bp->pr)); } if((x >= 0L) && (x < (bp->cf)->w)) { if((y >= 0L) && (y < (bp->cf)->h)) { switch(bp->bt) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H back = dk3bif_get_png_pixel_component(bp, x, y, c); #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H back = dk3bif_get_jpeg_pixel_component(bp, x, y, c); #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H back = dk3bif_get_tiff_pixel_component(bp, x, y, c); #endif } break; } } } $? "- dk3bif_get_pixel_component_not_resampled %u", (unsigned)back return back; } /** Retrieve one pixel component resampled to output bit size. @param bp Bitmap image. @param x X coordinate. @param y Y coordinate. @param c Choose component: 0=red/gray, 1=green, 2=blue, 3=alpha. @return Pixel component. */ static dk3_bif_pixel_t dk3bif_get_pixel_component( dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y, int c ) { dk3_bif_pixel_t back; $? "+ dk3bif_get_pixel_component %lu %lu %d", (unsigned long)x, (unsigned long)y, c /* Get unresampled value. */ back = dk3bif_get_pixel_component_not_resampled(bp, x, y, c); /* Resample value to requested output bit size. */ $? "- dk3bif_get_pixel_component %u", (unsigned)back back = dk3pixre_convert(&(bp->pr), back); return back; } /** Compare two frames by number. @param l Left frame. @param r Right frame or number. @param cr Comparison criteria: 0=frame/frame, 1=frame/number. @return Comparison result. */ static int dk3bif_frame_compare(void const *l, void const *r, int cr) { int back = 0; dk3_bif_frame_t const *pl; dk3_bif_frame_t const *pr; size_t *psz; if(l) { if(r) { pl = (dk3_bif_frame_t const *)l; pr = (dk3_bif_frame_t const *)r; psz = (size_t *)r; switch(cr) { case 1: { if(pl->n > *psz) { back = 1; } else { if(pl->n < *psz) { back = -1; } } } break; default: { if(pl->n > pr->n) { back = 1; } else { if(pl->n < pr->n) { back = -1; } } } break; } } else { back = 1; } } else { if(r) { back = -1; } } return back; } /** Set up upsampling/downsampling after changing frame or output bit number. @param bp Bitmap image file. */ static void dk3bif_set_pixel_sampling(dk3_bif_t *bp) { $? "+ dk3bif_set_pixel_sampling" if(bp) { if(bp->cf) { if(bp->bits) { $? ". resampling probably needed" dk3pixre_set(&(bp->pr), (bp->cf)->bits, bp->bits); } else { $? ". no resampling required" dk3pixre_set(&(bp->pr), (bp->cf)->bits, (bp->cf)->bits); } } } $? "- dk3bif_set_pixel_sampling" } /** Allocate memory for bitmap image file. @param tp Image type. @param app Application structure for diagnostics, may not be NULL. @return Pointer to new structure on success, NULL on error. */ static dk3_bif_t * dk3bif_allocate_app(int tp, dk3_app_t *app) { dk3_bif_t *back = NULL; int ok = 0; $? "+ dk3bif_allocate_app" if(app) { back = dk3_new_app(dk3_bif_t,1,app); if(back) { dk3pixre_set(&(back->pr), 8, 8); back->app = app; back->tmpfn = NULL; back->tmpfipo = NULL; back->s_frames = NULL; back->i_frames = NULL; back->cf = NULL; back->implspec = NULL; back->n = dk3bif_temp_number++; back->n_frames = 0; back->bits = 0; back->bt = tp; back->bg = 0; back->remtmpf = 0; back->bgr = back->bgg = back->bgb = 255U; back->s_frames = dk3sto_open_app(app); if(back->s_frames) { dk3sto_set_comp(back->s_frames, dk3bif_frame_compare, 0); back->i_frames = dk3sto_it_open(back->s_frames); if(back->i_frames) { ok = 1; } } if(!(ok)) { dk3bif_close(back); back = NULL; } } } $? "- dk3bif_allocate_app %s", TR_PTR(back) return back; } /** Read image header information. Create the frames, fill implspec for bif and frame. @param bp Bitmap image file. @return 1 on success, 0 on error. */ static int dk3bif_read_header(dk3_bif_t *bp) { int back = 0; $? "+ dk3bif_read_header" switch(bp->bt) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H back = dk3bif_read_png_header(bp); #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H back = dk3bif_read_jpeg_header(bp); #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H back = dk3bif_read_tiff_header(bp); #endif } break; } dk3bif_set_pixel_sampling(bp); $? "- dk3bif_read_header %d", back return back; } /** Create a temporary file name (8 bit characters). @param fnb File name buffer. @param bp Bitmap image file pointer. */ static void dk3bif_create_tmpfilename(char *fnb, dk3_bif_t *bp) { $? "+ dk3bif_create_tmpfilename" #if DK3_ON_WINDOWS sprintf(fnb, dk3bif_kw_c8[1], _getpid(), bp->n); #else #if DK3_HAVE_GETPID sprintf(fnb, dk3bif_kw_c8[0], (unsigned long)getpid(), bp->n); #else time_t timer; time(&timer); sprintf(fnb, dk3bif_kw_c8[0], (unsigned long)timer, bp->n); #endif #endif $? "- dk3bif_create_tmpfilename" } /** Copy input file to temporary file. This function relies on tmpfn set. @param bp Bitmap image file. @param fipos Source file, must be opened "rb". @param app Application structure for diagnostics. @return 1 on success, 0 on error. */ static int dk3bif_copy_to_temp(dk3_bif_t *bp, FILE *fipos, dk3_app_t *app) { char bu[4096]; /* Buffer. */ FILE *fipod; /* Destination file. */ int back = 0; int cc = 1; /* Flag: Can continue copying. */ size_t rdb; /* Bytes read. */ $? "+ dk3bif_copy_to_temp" fipod = dk3sf_c8_fopen_app(bp->tmpfn, "wb", app); if(fipod) { back = 1; while(cc) { cc = 0; rdb = dk3sf_fread_app(bu, 1, sizeof(bu), fipos, app); if(rdb > 0) { if(dk3sf_fwrite_app(bu, 1, rdb, fipod, app)) { cc = 1; } else { back = 0; } } } #if DK3_CHAR_SIZE == 1 if(!dk3sf_fclose_fn_app(fipod, bp->tmpfn, app)) { back = 0; } #else if(!dk3sf_fclose_fn_app(fipod, NULL, app)) { back = 0; } #endif } $? "- dk3bif_copy_to_temp %d", back return back; } /** Correct image type. @param tp Original image type, may need correction. @return Corrected value (set to DK3_BIF_IMAGE_TYPE_UNKNOWN if necessary). */ static int dk3bif_correct_type(int tp) { int back; back = tp; $? "+ dk3bif_correct_type %d", tp if(tp != DK3_BIF_IMAGE_TYPE_PNG) { if(tp != DK3_BIF_IMAGE_TYPE_JPEG) { if(tp != DK3_BIF_IMAGE_TYPE_TIFF) { /* +++ further file types here +++ */ back = DK3_BIF_IMAGE_TYPE_UNKNOWN; } } } $? "- dk3bif_correct_type %d", back return back; } dk3_bif_t * dk3bif_open_filename_app(dkChar const *fn, int tp, dk3_app_t *app) { char fnb[128]; /* File name buffer for temp file. */ dk3_bif_t *back = NULL; FILE *fipos; int mytp; /* Type, corrected if necessary. */ int ok = 0; /* Flag: Success. */ $? "+ dk3bif_open_filename_app" mytp = dk3bif_correct_type(tp); if((fn) && (app)) { if(mytp == DK3_BIF_IMAGE_TYPE_UNKNOWN) { mytp = dk3bif_check_file_name(fn); } if(dk3bif_type_supported(mytp)) { back = dk3bif_allocate_app(mytp, app); if(back) { switch(back->bt) { case DK3_BIF_IMAGE_TYPE_TIFF: { dk3bif_create_tmpfilename(fnb, back); back->tmpfn = dk3str_c8_dup_app(fnb, NULL); if(back->tmpfn) { back->remtmpf = 1; fipos = dk3sf_fopen_app(fn, dk3bif_kw_dk[0], app); if(fipos) { ok = dk3bif_copy_to_temp(back, fipos, app); fclose(fipos); if(ok) { ok = dk3bif_read_header(back); } } } } break; default: { back->tmpfipo = dk3sf_fopen_app(fn, dk3bif_kw_dk[0], app); if(back->tmpfipo) { ok = dk3bif_read_header(back); } } break; } if(!(ok)) { dk3bif_close(back); back = NULL; } } } else { if(app) { /* ERROR: File type unknown or unsupported! */ dk3app_log_i1(app, DK3_LL_ERROR, 257); } } } $? "- dk3bif_open_filename_app %s", TR_PTR(back) return back; } dk3_bif_t * dk3bif_open_c8_filename_app(char const *fn, int tp, dk3_app_t *app) { dk3_bif_t *back = NULL; int mytp; /* Type, corrected if necessary. */ int ok = 0; /* Flag: Success. */ $? "+ dk3bif_open_c8_filename_app" mytp = dk3bif_correct_type(tp); if((fn) && (app)) { if(mytp == DK3_BIF_IMAGE_TYPE_UNKNOWN) { mytp = dk3bif_check_c8_file_name(fn); } if(dk3bif_type_supported(mytp)) { back = dk3bif_allocate_app(mytp, app); if(back) { switch(back->bt) { case DK3_BIF_IMAGE_TYPE_TIFF: { back->tmpfn = dk3str_c8_dup_app(fn, NULL); if(back->tmpfn) { ok = dk3bif_read_header(back); } } break; default: { back->tmpfipo = dk3sf_c8_fopen_app(fn, "rb", app); if(back->tmpfipo) { ok = dk3bif_read_header(back); } } break; } if(!(ok)) { dk3bif_close(back); back = NULL; } } } else { if(app) { /* ERROR: File type unknown or unsupported! */ dk3app_log_i1(app, DK3_LL_ERROR, 257); } } } $? "- dk3bif_open_c8_filename_app %s", TR_PTR(back) return back; } dk3_bif_t * dk3bif_open_file_app(FILE *fipo, int tp, dk3_app_t *app) { char fnb[128]; dk3_bif_t *back = NULL; int ok = 0; int mytp; $? "+ dk3bif_open_file_app" mytp = dk3bif_correct_type(tp); if((fipo) && (app) && (mytp != DK3_BIF_IMAGE_TYPE_UNKNOWN)) { if(dk3bif_type_supported(mytp)) { back = dk3bif_allocate_app(mytp, app); if(back) { dk3bif_create_tmpfilename(fnb, back); back->tmpfn = dk3str_c8_dup_app(fnb, NULL); if(back->tmpfn) { back->remtmpf = 1; if(dk3bif_copy_to_temp(back, fipo, app)) { ok = dk3bif_read_header(back); } } if(!(ok)) { dk3bif_close(back); back = NULL; } } } else { /* ERROR: Unknown/unsupported file type! */ if(app) { dk3app_log_i1(app, DK3_LL_ERROR, 257); } } } $? "- dk3bif_open_file_app %s", TR_PTR(back) return back; } void dk3bif_close(dk3_bif_t *bp) { dk3_bif_frame_t *fp; $? "+ dk3bif_close" if(bp) { /* Release image type specific data per frame. */ if(bp->s_frames) { if(bp->i_frames) { dk3sto_it_reset(bp->i_frames); while((fp = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames)) != NULL) { /* Close and delete frame. */ dk3bif_frame_delete(fp, bp->bt); } dk3sto_it_close(bp->i_frames); } dk3sto_close(bp->s_frames); } bp->s_frames = NULL; bp->i_frames = NULL; bp->cf = NULL; /* Release image type specific data for file. */ if(bp->implspec) { switch(bp->bt) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H dk3bif_release_implspec_png(bp->implspec); #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H dk3bif_release_implspec_jpeg(bp->implspec); #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H dk3bif_release_implspec_tiff(bp->implspec); #endif } break; } } bp->implspec = NULL; bp->n = 0UL; bp->n_frames = 0; bp->bits = 0; bp->bt = DK3_BIF_IMAGE_TYPE_UNKNOWN; /* Close file if open. */ if(bp->tmpfipo) { $? ". close file" fclose(bp->tmpfipo); bp->tmpfipo = NULL; } /* Delete file and release file name memory. */ if(bp->tmpfn) { $? ". delete temp file name and remove file" if(bp->remtmpf) { dk3sf_c8_remove_file_app(bp->tmpfn, bp->app); } dk3_release(bp->tmpfn); } bp->app = NULL; dk3_delete(bp); } $? "- dk3bif_close" } int dk3bif_check_suffix_without_dot(dkChar const *sn) { int back = DK3_BIF_IMAGE_TYPE_UNKNOWN; int tp = -1; $? "+ dk3bif_check_suffix_without_dot" if(sn) { tp = dk3str_array_index(dk3bif_dk_type_names, sn, 0); $? ". tp=%d", tp switch(tp) { case 0: { $? ". png" back = DK3_BIF_IMAGE_TYPE_PNG; } break; case 1: case 2: { $? ". jpeg" back = DK3_BIF_IMAGE_TYPE_JPEG; } break; case 3: case 4: { $? ". tiff" back = DK3_BIF_IMAGE_TYPE_TIFF; } break; } } $? "- dk3bif_check_suffix_without_dot %d", back return back; } int dk3bif_check_c8_suffix_without_dot(char const *sn) { int back = DK3_BIF_IMAGE_TYPE_UNKNOWN; int tp = -1; if(sn) { tp = dk3str_c8_array_index(dk3bif_c8_type_names, sn, 0); switch(tp) { case 0: { back = DK3_BIF_IMAGE_TYPE_PNG; } break; case 1: case 2: { back = DK3_BIF_IMAGE_TYPE_JPEG; } break; case 3: case 4: { back = DK3_BIF_IMAGE_TYPE_TIFF; } break; } } return back; } int dk3bif_check_file_name(dkChar const *fn) { int back = DK3_BIF_IMAGE_TYPE_UNKNOWN; dkChar const *sp; $? "+ dk3bif_check_file_name" if(fn) { sp = dk3str_get_suffix(fn); if(sp) { sp++; back = dk3bif_check_suffix_without_dot(sp); } } $? "- dk3bif_check_file_name %d", back return back; } int dk3bif_check_c8_file_name(char const *fn) { int back = DK3_BIF_IMAGE_TYPE_UNKNOWN; char const *sp; if(fn) { sp = dk3str_c8_get_suffix(fn); if(sp) { sp++; back = dk3bif_check_c8_suffix_without_dot(sp); } } return back; } /** Transfer background color from image to frame. @param bp Bitmap image file (source). @param fr Frame (destination). */ void dk3_bif_transfer_background(dk3_bif_t *bp, dk3_bif_frame_t *fr) { dk3_pixel_resample_t pixre; dk3pixre_set(&pixre, 8, fr->bits); fr->bgr = dk3pixre_convert(&pixre, bp->bgr); fr->bgg = dk3pixre_convert(&pixre, bp->bgg); fr->bgb = dk3pixre_convert(&pixre, bp->bgb); } int dk3bif_read_data(dk3_bif_t *bp) { int back = 0; dk3_bif_frame_t *fr = NULL; $? "+ dk3bif_read_data" if(bp) { switch(bp->bt) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H back = dk3bif_read_png_data(bp); #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H $? ". read jpeg" back = dk3bif_read_jpeg_data(bp); $? ". jpeg read successfully" #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H back = dk3bif_read_tiff_data(bp); #endif } break; } } if(back) { dk3sto_it_reset(bp->i_frames); while((fr = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames)) != NULL) { /* The following settings are overwritten by dk3bif_analyze(). */ switch(fr->cs) { case DK3_COLOR_SPACE_GRAY: case DK3_COLOR_SPACE_GRAY_ALPHA: { fr->realcolor = 0; } break; default: { fr->realcolor = 1; } break; } switch(fr->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { fr->realalpha = 1; } break; default: { fr->realalpha = 0; } break; } fr->realbits = fr->bits; /* Obtain background color from per-file settings. */ if((!(fr->bg)) || (bp->bg)) { dk3_bif_transfer_background(bp, fr); } fr->bggr = dk3bif_ntsc(fr->bgr, fr->bgg, fr->bgb); } dk3sto_it_reset(bp->i_frames); bp->cf = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames); if(!(bp->cf)) { back = 0; } } dk3bif_set_pixel_sampling(bp); $? "- dk3bif_read_data %d", back return back; } size_t dk3bif_number_of_frames(dk3_bif_t *bp) { size_t back = 0; $? "+ dk3bif_number_of_frames" if(bp) { back = bp->n_frames; } $? "- dk3bif_number_of_frames %u", (unsigned)back return back; } int dk3bif_set_frame(dk3_bif_t *bp, size_t fn) { int back = 0; $? "+ dk3bif_set_frame %u", (unsigned)fn if(bp) { bp->cf = (dk3_bif_frame_t *)dk3sto_it_find_like(bp->i_frames, (void *)(&fn), 1); if(bp->cf) { back = 1; dk3bif_set_pixel_sampling(bp); } else { dk3sto_it_reset(bp->i_frames); } } $? "- dk3bif_set_frame %d", back return back; } size_t dk3bif_get_bits_per_pixel(dk3_bif_t *bp) { size_t back = 0; $? "+ dk3bif_get_bits_per_pixel" if(bp) { if(bp->cf) { back = (bp->cf)->bits; } } $? "- dk3bif_get_bits_per_pixel %u", (unsigned)back return back; } size_t dk3bif_real_bits_per_pixel(dk3_bif_t *bp) { size_t back = 0; $? "+ dk3bif_real_bits_per_pixel" if(bp) { if(bp->cf) { back = (bp->cf)->realbits; } } $? "- dk3bif_real_bits_per_pixel %u", (unsigned)back return back; } int dk3bif_real_color(dk3_bif_t *bp) { int back = 0; if(bp) { if(bp->cf) { back = (bp->cf)->realcolor; } } return back; } int dk3bif_real_alpha(dk3_bif_t *bp) { int back = 0; if(bp) { if(bp->cf) { back = (bp->cf)->realalpha; } } return back; } int dk3bif_set_bits_per_pixel(dk3_bif_t *bp, size_t sz) { int back = 0; $? "+ dk3bif_set_bits_per_pixel" if((bp) && (sz)) { if(sz < 17) { bp->bits = sz; dk3bif_set_pixel_sampling(bp); back = 1; } else { bp->bits = 16; dk3bif_set_pixel_sampling(bp); /* Maximum number of bits exceeded! */ if(bp->app) { dk3app_log_i1(bp->app, DK3_LL_WARNING, 258); } } } $? "- dk3bif_set_bits_per_pixel %d", back return back; } dk3_bif_coord_t dk3bif_get_width(dk3_bif_t *bp) { dk3_bif_coord_t back = 0L; $? "+ dk3bif_get_width" if(bp) { if(bp->cf) { back = (bp->cf)->w; } } $? "- dk3bif_get_width %ld", (long)back return back; } dk3_bif_coord_t dk3bif_get_height(dk3_bif_t *bp) { dk3_bif_coord_t back = 0L; $? "+ dk3bif_get_height" if(bp) { if(bp->cf) { back = (bp->cf)->h; } } $? "- dk3bif_get_height %ld", (long)back return back; } dk3_bif_coord_t dk3bif_get_largest_width(dk3_bif_t *bp) { dk3_bif_frame_t *fp; dk3_bif_coord_t back = 0L; $? "+ dk3bif_get_largest_width" if(bp) { dk3sto_it_reset(bp->i_frames); while((fp = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames)) != NULL) { if(fp->w > back) { back = fp->w; } } } $? "- dk3bif_get_largest_width %ld", (long)back return back; } dk3_bif_coord_t dk3bif_get_largest_height(dk3_bif_t *bp) { dk3_bif_frame_t *fp; dk3_bif_coord_t back = 0L; $? "+ dk3bif_get_largest_height" if(bp) { dk3sto_it_reset(bp->i_frames); while((fp = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames)) != NULL) { if(fp->h > back) { back = fp->h; } } } $? "- dk3bif_get_largest_height %ld", (long)back return back; } dk3_bif_pixel_t dk3bif_get_red(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_red" if(bp) { if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: case DK3_COLOR_SPACE_GRAY_ALPHA: { back = dk3bif_get_pixel_component(bp, x, y, 0); } break; case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_get_pixel_component(bp, x, y, 0); } break; } } } $? "- dk3bif_get_red %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_green(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_green" if(bp) { if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: case DK3_COLOR_SPACE_GRAY_ALPHA: { back = dk3bif_get_pixel_component(bp, x, y, 0); } break; case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_get_pixel_component(bp, x, y, 1); } break; } } } $? "- dk3bif_get_green %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_blue(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_blue" if(bp) { if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: case DK3_COLOR_SPACE_GRAY_ALPHA: { back = dk3bif_get_pixel_component(bp, x, y, 0); } break; case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_get_pixel_component(bp, x, y, 2); } break; } } } $? "- dk3bif_get_blue %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_gray(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_gray" if(bp) { if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY: case DK3_COLOR_SPACE_GRAY_ALPHA: { back = dk3bif_get_pixel_component(bp, x, y, 0); } break; case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_ntsc( dk3bif_get_pixel_component(bp, x, y, 0), dk3bif_get_pixel_component(bp, x, y, 1), dk3bif_get_pixel_component(bp, x, y, 2) ); back &= dk3pixre_get_max_value(&(bp->pr)); $? ". r=%u g=%u b=%u gray=%u", dk3bif_get_pixel_component(bp, x, y, 0), dk3bif_get_pixel_component(bp, x, y, 1), dk3bif_get_pixel_component(bp, x, y, 2), back } break; } } } $? "- dk3bif_get_gray %u", (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_alpha(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = (dk3_bif_pixel_t)0; $? "+ dk3bif_get_alpha" if(bp) { back = dk3pixre_get_max_value(&(bp->pr)); if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_get_pixel_component(bp, x, y, 3); } break; default: { if((x >= 0L) && (x < (bp->cf)->w)) { if((y >= 0L) && (y < (bp->cf)->h)) { back = dk3pixre_get_max_value(&(bp->pr)); } } } break; } } } $? "- dk3bif_get_alpha %u", (unsigned)back return back; } /** Mix pixel value against background value. @param v Pixel value. @param w Background value. @param a Alpha channel value (opacity). @param m Maximum alpha value. @return Mixing result. */ static dk3_bif_pixel_t dk3bif_mix( dk3_bif_pixel_t v, dk3_bif_pixel_t w, dk3_bif_pixel_t a, dk3_bif_pixel_t m ) { unsigned long l1, l2, l3, l4, l5, l6; dk3_bif_pixel_t back; dk3_bif_pixel_t b; int me = 0; back = v; b = m - a; l1 = (unsigned long)v; l2 = (unsigned long)a; l3 = (unsigned long)w; l4 = (unsigned long)b; l5 = (unsigned long)m; l6 = dk3ma_ul_div_ok( dk3ma_ul_add_ok( dk3ma_ul_mul_ok(l1, l2, &me), dk3ma_ul_mul_ok(l3, l4, &me), &me ), l5, &me ); if(me == 0) { back = (((dk3_bif_pixel_t)l6) & m); } return back; } dk3_bif_pixel_t dk3bif_get_mixed_red(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = 0U; $? "+ dk3bif_get_mixed_red" back = dk3bif_get_red(bp, x, y); if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_mix( back, (bp->cf)->bgr, dk3bif_get_alpha(bp, x, y), dk3pixre_get_max_value(&(bp->pr)) ); } break; } } $? "- dk3bif_get_mixed_red %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_mixed_green(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = 0U; $? "+ dk3bif_get_mixed_green" back = dk3bif_get_green(bp, x, y); if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_mix( back, (bp->cf)->bgg, dk3bif_get_alpha(bp, x, y), dk3pixre_get_max_value(&(bp->pr)) ); } break; } } $? "- dk3bif_get_mixed_green %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_mixed_blue(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = 0U; $? "+ dk3bif_get_mixed_blue" back = dk3bif_get_blue(bp, x, y); if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { back = dk3bif_mix( back, (bp->cf)->bgb, dk3bif_get_alpha(bp, x, y), dk3pixre_get_max_value(&(bp->pr)) ); } break; } } $? "- dk3bif_get_mixed_blue %ld %ld %u", (long)x, (long)y, (unsigned)back return back; } dk3_bif_pixel_t dk3bif_get_mixed_gray(dk3_bif_t *bp, dk3_bif_coord_t x, dk3_bif_coord_t y) { dk3_bif_pixel_t back = 0U; $? "+ dk3bif_get_mixed_gray %ld %ld", x, y back = dk3bif_get_gray(bp, x, y); if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_GRAY_ALPHA: case DK3_COLOR_SPACE_RGBA: { $? ". mix" back = dk3bif_mix( back, (bp->cf)->bggr, dk3bif_get_alpha(bp, x, y), dk3pixre_get_max_value(&(bp->pr)) ); } break; } } $? "- dk3bif_get_mixed_gray %u", (unsigned)back return back; } int dk3bif_type_supported(int tp) { int back = 0; $? "+ dk3bif_type_supported %d", tp switch(tp) { case DK3_BIF_IMAGE_TYPE_PNG: { #if DK3_HAVE_PNG_H back = 1; #endif } break; case DK3_BIF_IMAGE_TYPE_JPEG: { #if DK3_HAVE_JPEGLIB_H back = 1; #endif } break; case DK3_BIF_IMAGE_TYPE_TIFF: { #if DK3_HAVE_TIFF_H back = 1; #endif } break; } $? "- dk3bif_type_supported %d", back return back; } FILE * dk3bif_get_file(dk3_bif_t *bp) { FILE *back = NULL; $? "+ dk3bif_get_file" if(bp) { back = bp->tmpfipo; } $? "- dk3bif_get_file %s", TR_PTR(back) return back; } int dk3bif_is_colored(dk3_bif_t *bp) { int back = 0; dk3_bif_coord_t x; dk3_bif_coord_t y; dk3_bif_pixel_t r; dk3_bif_pixel_t g; dk3_bif_pixel_t b; if(bp) { if(bp->cf) { switch((bp->cf)->cs) { case DK3_COLOR_SPACE_RGB: case DK3_COLOR_SPACE_RGBA: { for(y = 0L; (y < (bp->cf)->h) && (back == 0); y++) { for(x = 0L; (x < (bp->cf)->w) && (back == 0); x++) { r = dk3bif_get_red(bp, x, y); g = dk3bif_get_green(bp, x, y); b = dk3bif_get_blue(bp, x, y); if(r != g) { back = 1; } if(r != b) { back = 1; } } } } break; } } } return back; } double dk3bif_get_xres(dk3_bif_t *bp) { double back = -1.0; $? "+ dk3bif_get_xres" if(bp) { if(bp->cf) { back = (bp->cf)->xres; } } $? "- dk3bif_get_xres %lg", back return back; } double dk3bif_get_yres(dk3_bif_t *bp) { double back = -1.0; $? "+ dk3bif_get_yres" if(bp) { if(bp->cf) { back = (bp->cf)->yres; } } $? "- dk3bif_get_yres %lg", back return back; } int dk3bif_next_frame(dk3_bif_t *bp) { int back = 0; if(bp) { if(bp->i_frames) { bp->cf = (dk3_bif_frame_t *)dk3sto_it_next(bp->i_frames); if(bp->cf) { back = 1; dk3bif_set_pixel_sampling(bp); } } } return back; } void dk3bif_reset_frames(dk3_bif_t *bp) { if(bp) { bp->cf = NULL; dk3sto_it_reset(bp->i_frames); } } void dk3bif_set_background( dk3_bif_t *bp, dk3_bif_pixel_t r, dk3_bif_pixel_t g, dk3_bif_pixel_t b, int f ) { if(bp) { bp->bgr = r; bp->bgg = g; bp->bgb = b; bp->bg = (f ? 1 : 0); } } int dk3bif_get_color_space(dk3_bif_t *bp) { int back = 0; if(bp) { if(bp->cf) { back = (bp->cf)->cs; } } return back; } int dk3bif_get_type(dk3_bif_t *bp) { int back = DK3_BIF_IMAGE_TYPE_UNKNOWN; if(bp) { back = bp->bt; } return back; } $!trace-on int dk3bif_jpeg_get_num_components(dk3_bif_t *bif) { int back = 0; #if DK3_HAVE_JPEGLIB_H dk3_bif_frame_jpeg_t *jpf; $? "+ dk3bif_jpeg_get_num_components" if(bif) { $? ". bif" if(bif->cf) { $? ". cf" if(bif->bt == DK3_BIF_IMAGE_TYPE_JPEG) { $? ". cs ok" jpf = (dk3_bif_frame_jpeg_t *)((bif->cf)->implspec); if(jpf) { $? ". jpf" back = jpf->num_comp; } else { $? "! jpf" } } else { $? "! cs" } } else { $? "! cf" } } else { $? "! bif" } $? "- dk3bif_jpeg_get_num_components %d", back #endif return back; } $!trace-off int dk3bif_jpeg_get_found_adobe_marker(dk3_bif_t *bif) { int back = 0; #if DK3_HAVE_JPEGLIB_H dk3_bif_frame_jpeg_t *jpf; if(bif) { if(bif->cf) { if(bif->bt == DK3_BIF_IMAGE_TYPE_JPEG) { jpf = (dk3_bif_frame_jpeg_t *)((bif->cf)->implspec); if(jpf) { back = jpf->is_adobe; } } } } #endif return back; } dk3_bif_pixel_t dk3bif_average(dk3_bif_pixel_t left, dk3_bif_pixel_t upper) { dk3_bif_pixel_t back; long x; x = (long)left + (long)upper; x = x / 2; back = (dk3_bif_pixel_t)x; return back; } dk3_bif_pixel_t dk3bif_paeth( dk3_bif_pixel_t v1, dk3_bif_pixel_t v2, dk3_bif_pixel_t v3 ) { dk3_bif_pixel_t back; long p, pa, pb, pc; p = (long)v1 + (long)v2 - (long)v3; pa = p - (long)v1; pb = p - (long)v2; pc = p - (long)v3; if(pa < 0) { pa = 0L - pa; } if(pb < 0) { pb = 0L - pb; } if(pc < 0) { pc = 0L - pc; } if((pa <= pb) && (pa <= pc)) { back = v1; } else { if(pb <= pc) { back = v2; } else { back = v3; } } return back; } /* vim: set ai sw=2 : */