void cupsImageSetMaxTiles( cups_image_t *img, /* I - Image to set */ int max_tiles) /* I - Number of tiles to cache */ { int cache_size, /* Size of tile cache in bytes */ min_tiles, /* Minimum number of tiles to cache */ max_size; /* Maximum cache size in bytes */ char *cache_env, /* Cache size environment variable */ cache_units[255]; /* Cache size units */ min_tiles = max(CUPS_TILE_MINIMUM, 1 + max((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE, (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE)); if (max_tiles == 0) max_tiles = ((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE) * ((img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE); cache_size = max_tiles * CUPS_TILE_SIZE * CUPS_TILE_SIZE * cupsImageGetDepth(img); if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL) { switch (sscanf(cache_env, "%d%254s", &max_size, cache_units)) { case 0 : max_size = 32 * 1024 * 1024; break; case 1 : max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE; break; case 2 : if (tolower(cache_units[0] & 255) == 'g') max_size *= 1024 * 1024 * 1024; else if (tolower(cache_units[0] & 255) == 'm') max_size *= 1024 * 1024; else if (tolower(cache_units[0] & 255) == 'k') max_size *= 1024; else if (tolower(cache_units[0] & 255) == 't') max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE; break; } } else max_size = 32 * 1024 * 1024; if (cache_size > max_size) max_tiles = max_size / CUPS_TILE_SIZE / CUPS_TILE_SIZE / cupsImageGetDepth(img); if (max_tiles < min_tiles) max_tiles = min_tiles; img->max_ics = max_tiles; DEBUG_printf(("max_ics=%d...\n", img->max_ics)); }
static void flush_tile(cups_image_t *img) /* I - Image */ { int bpp; /* Bytes per pixel */ cups_itile_t *tile; /* Pointer to tile */ bpp = cupsImageGetDepth(img); tile = img->first->tile; if (!tile->dirty) { tile->ic = NULL; return; } if (img->cachefile < 0) { if ((img->cachefile = cupsTempFd(img->cachename, sizeof(img->cachename))) < 0) { tile->ic = NULL; tile->dirty = 0; return; } DEBUG_printf(("Created swap file \"%s\"...\n", img->cachename)); } if (tile->pos >= 0) { if (lseek(img->cachefile, tile->pos, SEEK_SET) != tile->pos) { tile->ic = NULL; tile->dirty = 0; return; } } else { if ((tile->pos = lseek(img->cachefile, 0, SEEK_END)) < 0) { tile->ic = NULL; tile->dirty = 0; return; } } write(img->cachefile, tile->ic->pixels, bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE); tile->ic = NULL; tile->dirty = 0; }
int /* O - Read status */ _cupsImageReadPNG( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { int y; /* Looping var */ png_structp pp; /* PNG read pointer */ png_infop info; /* PNG info pointers */ png_uint_32 width, /* Width of image */ height; /* Height of image */ int bit_depth, /* Bit depth */ color_type, /* Color type */ interlace_type, /* Interlace type */ compression_type, /* Compression type */ filter_type; /* Filter type */ png_uint_32 xppm, /* X pixels per meter */ yppm; /* Y pixels per meter */ int bpp; /* Bytes per pixel */ int pass, /* Current pass */ passes; /* Number of passes required */ cups_ib_t *in, /* Input pixels */ *inptr, /* Pointer into pixels */ *out; /* Output pixels */ png_color_16 bg; /* Background color */ /* * Setup the PNG data structures... */ pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(pp); /* * Initialize the PNG read "engine"... */ png_init_io(pp, fp); /* * Get the image dimensions and load the output image... */ png_read_info(pp, info); png_get_IHDR(pp, info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n", (int)width, (int)height, bit_depth, color_type, (color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE", (color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "", (color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : ""); if (color_type & PNG_COLOR_MASK_PALETTE) png_set_expand(pp); else if (bit_depth < 8) { png_set_packing(pp); png_set_expand(pp); } else if (bit_depth == 16) png_set_strip_16(pp); if (color_type & PNG_COLOR_MASK_COLOR) img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; else img->colorspace = secondary; if (width == 0 || width > CUPS_IMAGE_MAX_WIDTH || height == 0 || height > CUPS_IMAGE_MAX_HEIGHT) { fprintf(stderr, "DEBUG: PNG image has invalid dimensions %ux%u!\n", (unsigned)width, (unsigned)height); fclose(fp); return (1); } img->xsize = width; img->ysize = height; if ((xppm = png_get_x_pixels_per_meter(pp, info)) != 0 && (yppm = png_get_y_pixels_per_meter(pp, info)) != 0) { img->xppi = (int)((float)xppm * 0.0254); img->yppi = (int)((float)yppm * 0.0254); if (img->xppi == 0 || img->yppi == 0) { fprintf(stderr, "DEBUG: PNG image has invalid resolution %dx%d PPI\n", img->xppi, img->yppi); img->xppi = img->yppi = 128; } } cupsImageSetMaxTiles(img, 0); passes = png_set_interlace_handling(pp); /* * Handle transparency... */ if (png_get_valid(pp, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(pp); bg.red = 65535; bg.green = 65535; bg.blue = 65535; png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); if (passes == 1) { /* * Load one row at a time... */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) in = malloc(img->xsize); else in = malloc(img->xsize * 3); } else { /* * Interlaced images must be loaded all at once... */ size_t bufsize; /* Size of buffer */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { bufsize = img->xsize * img->ysize; if ((bufsize / img->ysize) != img->xsize) { fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n", (unsigned)width, (unsigned)height); fclose(fp); return (1); } } else { bufsize = img->xsize * img->ysize * 3; if ((bufsize / (img->ysize * 3)) != img->xsize) { fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n", (unsigned)width, (unsigned)height); fclose(fp); return (1); } } in = malloc(bufsize); } bpp = cupsImageGetDepth(img); out = malloc(img->xsize * bpp); if (!in || !out) { fputs("DEBUG: Unable to allocate memory for PNG image!\n", stderr); if (in) free(in); if (out) free(out); fclose(fp); return (1); } /* * Read the image, interlacing as needed... */ for (pass = 1; pass <= passes; pass ++) for (inptr = in, y = 0; y < img->ysize; y ++) { png_read_row(pp, (png_bytep)inptr, NULL); if (pass == passes) { /* * Output this row... */ if (color_type & PNG_COLOR_MASK_COLOR) { if ((saturation != 100 || hue != 0) && bpp > 1) cupsImageRGBAdjust(inptr, img->xsize, saturation, hue); switch (img->colorspace) { case CUPS_IMAGE_WHITE : cupsImageRGBToWhite(inptr, out, img->xsize); break; case CUPS_IMAGE_RGB : case CUPS_IMAGE_RGB_CMYK : cupsImageRGBToRGB(inptr, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageRGBToBlack(inptr, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageRGBToCMY(inptr, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageRGBToCMYK(inptr, out, img->xsize); break; } } else { switch (img->colorspace) { case CUPS_IMAGE_WHITE : memcpy(out, inptr, img->xsize); break; case CUPS_IMAGE_RGB : case CUPS_IMAGE_RGB_CMYK : cupsImageWhiteToRGB(inptr, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageWhiteToBlack(inptr, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageWhiteToCMY(inptr, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageWhiteToCMYK(inptr, out, img->xsize); break; } } if (lut) cupsImageLut(out, img->xsize * bpp, lut); _cupsImagePutRow(img, 0, y, img->xsize, out); } if (passes > 1) { if (color_type & PNG_COLOR_MASK_COLOR) inptr += img->xsize * 3; else inptr += img->xsize; } } png_read_end(pp, info); png_destroy_read_struct(&pp, &info, NULL); fclose(fp); free(in); free(out); return (0); }
static cups_ib_t * /* O - Pointer to tile or NULL */ get_tile(cups_image_t *img, /* I - Image */ int x, /* I - Column in image */ int y) /* I - Row in image */ { int bpp, /* Bytes per pixel */ tilex, /* Column within tile */ tiley, /* Row within tile */ xtiles, /* Number of tiles horizontally */ ytiles; /* Number of tiles vertically */ cups_ic_t *ic; /* Cache pointer */ cups_itile_t *tile; /* Tile pointer */ if (img->tiles == NULL) { xtiles = (img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE; ytiles = (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE; DEBUG_printf(("Creating tile array (%dx%d)\n", xtiles, ytiles)); if ((img->tiles = calloc(sizeof(cups_itile_t *), ytiles)) == NULL) return (NULL); if ((tile = calloc(xtiles * sizeof(cups_itile_t), ytiles)) == NULL) return (NULL); for (tiley = 0; tiley < ytiles; tiley ++) { img->tiles[tiley] = tile; for (tilex = xtiles; tilex > 0; tilex --, tile ++) tile->pos = -1; } } bpp = cupsImageGetDepth(img); tilex = x / CUPS_TILE_SIZE; tiley = y / CUPS_TILE_SIZE; tile = img->tiles[tiley] + tilex; x &= (CUPS_TILE_SIZE - 1); y &= (CUPS_TILE_SIZE - 1); if ((ic = tile->ic) == NULL) { if (img->num_ics < img->max_ics) { if ((ic = calloc(sizeof(cups_ic_t) + bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE, 1)) == NULL) { if (img->num_ics == 0) return (NULL); flush_tile(img); ic = img->first; } else { ic->pixels = ((cups_ib_t *)ic) + sizeof(cups_ic_t); img->num_ics ++; DEBUG_printf(("Allocated cache tile %d (%p)...\n", img->num_ics, ic)); } } else { DEBUG_printf(("Flushing old cache tile (%p)...\n", img->first)); flush_tile(img); ic = img->first; } ic->tile = tile; tile->ic = ic; if (tile->pos >= 0) { DEBUG_printf(("Loading cache tile from file position " CUPS_LLFMT "...\n", CUPS_LLCAST tile->pos)); lseek(img->cachefile, tile->pos, SEEK_SET); read(img->cachefile, ic->pixels, bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE); } else { DEBUG_puts("Clearing cache tile..."); memset(ic->pixels, 0, bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE); } } if (ic == img->first) { if (ic->next != NULL) ic->next->prev = NULL; img->first = ic->next; ic->next = NULL; ic->prev = NULL; } else if (img->first == NULL) img->first = ic; if (ic != img->last) { /* * Remove the cache entry from the list... */ if (ic->prev != NULL) ic->prev->next = ic->next; if (ic->next != NULL) ic->next->prev = ic->prev; /* * And add it to the end... */ if (img->last != NULL) img->last->next = ic; ic->prev = img->last; img->last = ic; } ic->next = NULL; return (ic->pixels + bpp * (y * CUPS_TILE_SIZE + x)); }
int /* O - -1 on error, 0 on success */ _cupsImagePutCol( cups_image_t *img, /* I - Image */ int x, /* I - Column */ int y, /* I - Start row */ int height, /* I - Column height */ const cups_ib_t *pixels) /* I - Pixels to put */ { int bpp, /* Bytes per pixel */ twidth, /* Width of tile */ count; /* Number of pixels to put */ int tilex, /* Column within tile */ tiley; /* Row within tile */ cups_ib_t *ib; /* Pointer to pixels in tile */ if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize) return (-1); if (y < 0) { height += y; y = 0; } if ((y + height) > img->ysize) height = img->ysize - y; if (height < 1) return (-1); bpp = cupsImageGetDepth(img); twidth = bpp * (CUPS_TILE_SIZE - 1); tilex = x / CUPS_TILE_SIZE; tiley = y / CUPS_TILE_SIZE; while (height > 0) { ib = get_tile(img, x, y); if (ib == NULL) return (-1); img->tiles[tiley][tilex].dirty = 1; tiley ++; count = CUPS_TILE_SIZE - (y & (CUPS_TILE_SIZE - 1)); if (count > height) count = height; y += count; height -= count; for (; count > 0; count --, ib += twidth) switch (bpp) { case 4 : *ib++ = *pixels++; case 3 : *ib++ = *pixels++; *ib++ = *pixels++; case 1 : *ib++ = *pixels++; break; } } return (0); }
int /* O - Read status */ _cupsImageReadSGI( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { int i, y; /* Looping vars */ int bpp; /* Bytes per pixel */ sgi_t *sgip; /* SGI image file */ cups_ib_t *in, /* Input pixels */ *inptr, /* Current input pixel */ *out; /* Output pixels */ unsigned short *rows[4], /* Row pointers for image data */ *red, *green, *blue, *gray, *alpha; /* * Setup the SGI file... */ sgip = sgiOpenFile(fp, SGI_READ, 0, 0, 0, 0, 0); /* * Get the image dimensions and load the output image... */ /* * Check the image dimensions; since xsize and ysize are unsigned shorts, * just check if they are 0 since they can't exceed CUPS_IMAGE_MAX_WIDTH or * CUPS_IMAGE_MAX_HEIGHT... */ if (sgip->xsize == 0 || sgip->ysize == 0 || sgip->zsize == 0 || sgip->zsize > 4) { fprintf(stderr, "DEBUG: Bad SGI image dimensions %ux%ux%u!\n", sgip->xsize, sgip->ysize, sgip->zsize); sgiClose(sgip); return (1); } if (sgip->zsize < 3) img->colorspace = secondary; else img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; img->xsize = sgip->xsize; img->ysize = sgip->ysize; cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); if ((in = malloc(img->xsize * sgip->zsize)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); sgiClose(sgip); return (1); } if ((out = malloc(img->xsize * bpp)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); sgiClose(sgip); free(in); return (1); } if ((rows[0] = calloc(img->xsize * sgip->zsize, sizeof(unsigned short))) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); sgiClose(sgip); free(in); free(out); return (1); } for (i = 1; i < sgip->zsize; i ++) rows[i] = rows[0] + i * img->xsize; /* * Read the SGI image file... */ for (y = 0; y < img->ysize; y ++) { for (i = 0; i < sgip->zsize; i ++) sgiGetRow(sgip, rows[i], img->ysize - 1 - y, i); switch (sgip->zsize) { case 1 : if (sgip->bpp == 1) for (i = img->xsize - 1, gray = rows[0], inptr = in; i >= 0; i --) { *inptr++ = *gray++; } else for (i = img->xsize - 1, gray = rows[0], inptr = in; i >= 0; i --) { *inptr++ = (*gray++) / 256 + 128; } break; case 2 : if (sgip->bpp == 1) for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in; i >= 0; i --) { *inptr++ = (*gray++) * (*alpha++) / 255; } else for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in; i >= 0; i --) { *inptr++ = ((*gray++) / 256 + 128) * (*alpha++) / 32767; } break; case 3 : if (sgip->bpp == 1) for (i = img->xsize - 1, red = rows[0], green = rows[1], blue = rows[2], inptr = in; i >= 0; i --) { *inptr++ = *red++; *inptr++ = *green++; *inptr++ = *blue++; } else for (i = img->xsize - 1, red = rows[0], green = rows[1], blue = rows[2], inptr = in; i >= 0; i --) { *inptr++ = (*red++) / 256 + 128; *inptr++ = (*green++) / 256 + 128; *inptr++ = (*blue++) / 256 + 128; } break; case 4 : if (sgip->bpp == 1) for (i = img->xsize - 1, red = rows[0], green = rows[1], blue = rows[2], alpha = rows[3], inptr = in; i >= 0; i --) { *inptr++ = (*red++) * (*alpha) / 255; *inptr++ = (*green++) * (*alpha) / 255; *inptr++ = (*blue++) * (*alpha++) / 255; } else for (i = img->xsize - 1, red = rows[0], green = rows[1], blue = rows[2], alpha = rows[3], inptr = in; i >= 0; i --) { *inptr++ = ((*red++) / 256 + 128) * (*alpha) / 32767; *inptr++ = ((*green++) / 256 + 128) * (*alpha) / 32767; *inptr++ = ((*blue++) / 256 + 128) * (*alpha++) / 32767; } break; } if (sgip->zsize < 3) { if (img->colorspace == CUPS_IMAGE_WHITE) { if (lut) cupsImageLut(in, img->xsize, lut); _cupsImagePutRow(img, 0, y, img->xsize, in); } else { switch (img->colorspace) { default : break; case CUPS_IMAGE_RGB : case CUPS_IMAGE_RGB_CMYK : cupsImageWhiteToRGB(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageWhiteToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageWhiteToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageWhiteToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * bpp, lut); _cupsImagePutRow(img, 0, y, img->xsize, out); } } else { if ((saturation != 100 || hue != 0) && bpp > 1) cupsImageRGBAdjust(in, img->xsize, saturation, hue); switch (img->colorspace) { default : break; case CUPS_IMAGE_WHITE : cupsImageRGBToWhite(in, out, img->xsize); break; case CUPS_IMAGE_RGB : cupsImageRGBToRGB(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageRGBToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageRGBToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageRGBToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * bpp, lut); _cupsImagePutRow(img, 0, y, img->xsize, out); } } free(in); free(out); free(rows[0]); sgiClose(sgip); return (0); }
int /* O - -1 on error, 0 on success */ cupsImageGetCol(cups_image_t *img, /* I - Image */ int x, /* I - Column */ int y, /* I - Start row */ int height, /* I - Column height */ cups_ib_t *pixels) /* O - Pixel data */ { int bpp, /* Bytes per pixel */ twidth, /* Tile width */ count; /* Number of pixels to get */ const cups_ib_t *ib; /* Pointer into tile */ if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize) return (-1); if (y < 0) { height += y; y = 0; } if ((y + height) > img->ysize) height = img->ysize - y; if (height < 1) return (-1); bpp = cupsImageGetDepth(img); twidth = bpp * (CUPS_TILE_SIZE - 1); while (height > 0) { ib = get_tile(img, x, y); if (ib == NULL) return (-1); count = CUPS_TILE_SIZE - (y & (CUPS_TILE_SIZE - 1)); if (count > height) count = height; y += count; height -= count; for (; count > 0; count --, ib += twidth) switch (bpp) { case 4 : *pixels++ = *ib++; case 3 : *pixels++ = *ib++; *pixels++ = *ib++; case 1 : *pixels++ = *ib++; break; } } return (0); }
int /* O - Read status */ _cupsImageReadGIF( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { unsigned char buf[1024]; /* Input buffer */ gif_cmap_t cmap; /* Colormap */ int i, /* Looping var */ bpp, /* Bytes per pixel */ gray, /* Grayscale image? */ ncolors, /* Bits per pixel */ transparent; /* Transparent color index */ /* * GIF files are either grayscale or RGB - no CMYK... */ if (primary == CUPS_IMAGE_RGB_CMYK) primary = CUPS_IMAGE_RGB; /* * Read the header; we already know it is a GIF file... */ fread(buf, 13, 1, fp); img->xsize = (buf[7] << 8) | buf[6]; img->ysize = (buf[9] << 8) | buf[8]; ncolors = 2 << (buf[10] & 0x07); gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE; if (buf[10] & GIF_COLORMAP) if (gif_read_cmap(fp, ncolors, cmap, &gray)) { fclose(fp); return (-1); } transparent = -1; for (;;) { switch (getc(fp)) { case ';' : /* End of image */ fclose(fp); return (-1); /* Early end of file */ case '!' : /* Extension record */ buf[0] = getc(fp); if (buf[0] == 0xf9) /* Graphic Control Extension */ { gif_get_block(fp, buf); if (buf[0] & 1) /* Get transparent color index */ transparent = buf[3]; } while (gif_get_block(fp, buf) != 0); break; case ',' : /* cupsImage data */ fread(buf, 9, 1, fp); if (buf[8] & GIF_COLORMAP) { ncolors = 2 << (buf[8] & 0x07); gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE; if (gif_read_cmap(fp, ncolors, cmap, &gray)) { fclose(fp); return (-1); } } if (transparent >= 0) { /* * Make transparent color white... */ cmap[transparent][0] = 255; cmap[transparent][1] = 255; cmap[transparent][2] = 255; } if (gray) { switch (secondary) { case CUPS_IMAGE_CMYK : for (i = ncolors - 1; i >= 0; i --) cupsImageWhiteToCMYK(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_CMY : for (i = ncolors - 1; i >= 0; i --) cupsImageWhiteToCMY(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_BLACK : for (i = ncolors - 1; i >= 0; i --) cupsImageWhiteToBlack(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_WHITE : break; case CUPS_IMAGE_RGB : case CUPS_IMAGE_RGB_CMYK : for (i = ncolors - 1; i >= 0; i --) cupsImageWhiteToRGB(cmap[i], cmap[i], 1); break; } img->colorspace = secondary; } else { if (hue != 0 || saturation != 100) for (i = ncolors - 1; i >= 0; i --) cupsImageRGBAdjust(cmap[i], 1, saturation, hue); switch (primary) { case CUPS_IMAGE_CMYK : for (i = ncolors - 1; i >= 0; i --) cupsImageRGBToCMYK(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_CMY : for (i = ncolors - 1; i >= 0; i --) cupsImageRGBToCMY(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_BLACK : for (i = ncolors - 1; i >= 0; i --) cupsImageRGBToBlack(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_WHITE : for (i = ncolors - 1; i >= 0; i --) cupsImageRGBToWhite(cmap[i], cmap[i], 1); break; case CUPS_IMAGE_RGB : case CUPS_IMAGE_RGB_CMYK : for (i = ncolors - 1; i >= 0; i --) cupsImageRGBToRGB(cmap[i], cmap[i], 1); break; } img->colorspace = primary; } if (lut) { bpp = cupsImageGetDepth(img); for (i = ncolors - 1; i >= 0; i --) cupsImageLut(cmap[i], bpp, lut); } img->xsize = (buf[5] << 8) | buf[4]; img->ysize = (buf[7] << 8) | buf[6]; /* * Check the dimensions of the image; since the dimensions are * a 16-bit integer we just need to check for 0... */ if (img->xsize == 0 || img->ysize == 0) { fprintf(stderr, "DEBUG: Bad GIF image dimensions: %dx%d\n", img->xsize, img->ysize); fclose(fp); return (1); } i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE); fclose(fp); return (i); } } }
int /* O - Read status */ _cupsImageReadPIX( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { short width, /* Width of image */ height, /* Height of image */ depth; /* Depth of image (bits) */ int count, /* Repetition count */ bpp, /* Bytes per pixel */ x, y; /* Looping vars */ cups_ib_t r, g, b; /* Red, green/gray, blue values */ cups_ib_t *in, /* Input pixels */ *out, /* Output pixels */ *ptr; /* Pointer into pixels */ /* * Get the image dimensions and setup the image... */ width = read_short(fp); height = read_short(fp); read_short(fp); read_short(fp); depth = read_short(fp); /* * Check the dimensions of the image. Since the short values used for the * width and height cannot exceed CUPS_IMAGE_MAX_WIDTH or * CUPS_IMAGE_MAX_HEIGHT, we just need to verify they are positive integers. */ if (width <= 0 || height <= 0 || (depth != 8 && depth != 24)) { fprintf(stderr, "DEBUG: Bad PIX image dimensions %dx%dx%d\n", width, height, depth); fclose(fp); return (1); } if (depth == 8) img->colorspace = secondary; else img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; img->xsize = width; img->ysize = height; cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); if ((in = malloc(img->xsize * (depth / 8))) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); fclose(fp); return (1); } if ((out = malloc(img->xsize * bpp)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); fclose(fp); free(in); return (1); } /* * Read the image data... */ if (depth == 8) { for (count = 0, y = 0, g = 0; y < img->ysize; y ++) { if (img->colorspace == CUPS_IMAGE_WHITE) ptr = out; else ptr = in; for (x = img->xsize; x > 0; x --, count --) { if (count == 0) { count = getc(fp); g = getc(fp); } *ptr++ = g; } if (img->colorspace != CUPS_IMAGE_WHITE) switch (img->colorspace) { default : cupsImageWhiteToRGB(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageWhiteToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageWhiteToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageWhiteToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * bpp, lut); _cupsImagePutRow(img, 0, y, img->xsize, out); } } else { for (count = 0, y = 0, r = 0, g = 0, b = 0; y < img->ysize; y ++) { ptr = in; for (x = img->xsize; x > 0; x --, count --) { if (count == 0) { count = getc(fp); b = getc(fp); g = getc(fp); r = getc(fp); } *ptr++ = r; *ptr++ = g; *ptr++ = b; } if (saturation != 100 || hue != 0) cupsImageRGBAdjust(in, img->xsize, saturation, hue); switch (img->colorspace) { default : break; case CUPS_IMAGE_WHITE : cupsImageRGBToWhite(in, out, img->xsize); break; case CUPS_IMAGE_RGB : cupsImageRGBToWhite(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageRGBToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageRGBToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageRGBToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * bpp, lut); _cupsImagePutRow(img, 0, y, img->xsize, out); } } fclose(fp); free(in); free(out); return (0); }
static int /* I - 0 = success, -1 = failure */ gif_read_image(FILE *fp, /* I - Input file */ cups_image_t *img, /* I - cupsImage pointer */ gif_cmap_t cmap, /* I - Colormap */ int interlace) /* I - Non-zero = interlaced image */ { unsigned char code_size; /* Code size */ cups_ib_t *pixels, /* Pixel buffer */ *temp; /* Current pixel */ int xpos, /* Current X position */ ypos, /* Current Y position */ pass; /* Current pass */ int pixel; /* Current pixel */ int bpp; /* Bytes per pixel */ static const int xpasses[4] = /* X interleaving */ { 8, 8, 4, 2 }, ypasses[5] = /* Y interleaving */ { 0, 4, 2, 1, 999999 }; bpp = cupsImageGetDepth(img); pixels = calloc(bpp, img->xsize); xpos = 0; ypos = 0; pass = 0; code_size = getc(fp); if (!pixels) return (-1); if (code_size > GIF_MAX_BITS || gif_read_lzw(fp, 1, code_size) < 0) { free(pixels); return (-1); } temp = pixels; while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0) { switch (bpp) { case 4 : temp[3] = cmap[pixel][3]; case 3 : temp[2] = cmap[pixel][2]; case 2 : temp[1] = cmap[pixel][1]; default : temp[0] = cmap[pixel][0]; } xpos ++; temp += bpp; if (xpos == img->xsize) { _cupsImagePutRow(img, 0, ypos, img->xsize, pixels); xpos = 0; temp = pixels; if (interlace) { ypos += xpasses[pass]; if (ypos >= img->ysize) { pass ++; ypos = ypasses[pass]; } } else ypos ++; } if (ypos >= img->ysize) break; } free(pixels); return (0); }
int /* O - Read status */ _cupsImageReadJPEG( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { struct jpeg_decompress_struct cinfo; /* Decompressor info */ struct jpeg_error_mgr jerr; /* Error handler info */ cups_ib_t *in, /* Input pixels */ *out; /* Output pixels */ jpeg_saved_marker_ptr marker; /* Pointer to marker data */ int psjpeg = 0; /* Non-zero if Photoshop CMYK JPEG */ static const char *cspaces[] = { /* JPEG colorspaces... */ "JCS_UNKNOWN", "JCS_GRAYSCALE", "JCS_RGB", "JCS_YCbCr", "JCS_CMYK", "JCS_YCCK" }; /* * Read the JPEG header... */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 0xffff); /* Adobe JPEG */ jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, 1); /* * Parse any Adobe APPE data embedded in the JPEG file. Since Adobe doesn't * bother following standards, we have to invert the CMYK JPEG data written by * Adobe apps... */ for (marker = cinfo.marker_list; marker; marker = marker->next) if (marker->marker == (JPEG_APP0 + 14) && marker->data_length >= 12 && !memcmp(marker->data, "Adobe", 5)) { fputs("DEBUG: Adobe CMYK JPEG detected (inverting color values)\n", stderr); psjpeg = 1; } cinfo.quantize_colors = 0; fprintf(stderr, "DEBUG: num_components = %d\n", cinfo.num_components); fprintf(stderr, "DEBUG: jpeg_color_space = %s\n", cspaces[cinfo.jpeg_color_space]); if (cinfo.num_components == 1) { fputs("DEBUG: Converting image to grayscale...\n", stderr); cinfo.out_color_space = JCS_GRAYSCALE; cinfo.out_color_components = 1; cinfo.output_components = 1; img->colorspace = secondary; } else if (cinfo.num_components == 4) { fputs("DEBUG: Converting image to CMYK...\n", stderr); cinfo.out_color_space = JCS_CMYK; cinfo.out_color_components = 4; cinfo.output_components = 4; img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_CMYK : primary; } else { fputs("DEBUG: Converting image to RGB...\n", stderr); cinfo.out_color_space = JCS_RGB; cinfo.out_color_components = 3; cinfo.output_components = 3; img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; } jpeg_calc_output_dimensions(&cinfo); if (cinfo.output_width <= 0 || cinfo.output_width > CUPS_IMAGE_MAX_WIDTH || cinfo.output_height <= 0 || cinfo.output_height > CUPS_IMAGE_MAX_HEIGHT) { fprintf(stderr, "DEBUG: Bad JPEG dimensions %dx%d!\n", cinfo.output_width, cinfo.output_height); jpeg_destroy_decompress(&cinfo); fclose(fp); return (1); } img->xsize = cinfo.output_width; img->ysize = cinfo.output_height; if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0) { if (cinfo.density_unit == 1) { img->xppi = cinfo.X_density; img->yppi = cinfo.Y_density; } else { img->xppi = (int)((float)cinfo.X_density * 2.54); img->yppi = (int)((float)cinfo.Y_density * 2.54); } if (img->xppi == 0 || img->yppi == 0) { fprintf(stderr, "DEBUG: Bad JPEG image resolution %dx%d PPI.\n", img->xppi, img->yppi); img->xppi = img->yppi = 128; } } fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n", img->xsize, img->ysize, cinfo.output_components, img->xppi, img->yppi); cupsImageSetMaxTiles(img, 0); in = malloc(img->xsize * cinfo.output_components); out = malloc(img->xsize * cupsImageGetDepth(img)); jpeg_start_decompress(&cinfo); while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1); if (psjpeg && cinfo.output_components == 4) { /* * Invert CMYK data from Photoshop... */ cups_ib_t *ptr; /* Pointer into buffer */ int i; /* Looping var */ for (ptr = in, i = img->xsize * 4; i > 0; i --, ptr ++) *ptr = 255 - *ptr; } if ((saturation != 100 || hue != 0) && cinfo.output_components == 3) cupsImageRGBAdjust(in, img->xsize, saturation, hue); if ((img->colorspace == CUPS_IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) || (img->colorspace == CUPS_IMAGE_CMYK && cinfo.out_color_space == JCS_CMYK)) { #ifdef DEBUG int i, j; cups_ib_t *ptr; fputs("DEBUG: Direct Data...\n", stderr); fputs("DEBUG:", stderr); for (i = 0, ptr = in; i < img->xsize; i ++) { putc(' ', stderr); for (j = 0; j < cinfo.output_components; j ++, ptr ++) fprintf(stderr, "%02X", *ptr & 255); } putc('\n', stderr); #endif /* DEBUG */ if (lut) cupsImageLut(in, img->xsize * cupsImageGetDepth(img), lut); _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in); } else if (cinfo.out_color_space == JCS_GRAYSCALE) { switch (img->colorspace) { default : break; case CUPS_IMAGE_BLACK : cupsImageWhiteToBlack(in, out, img->xsize); break; case CUPS_IMAGE_RGB : cupsImageWhiteToRGB(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageWhiteToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageWhiteToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut); _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out); } else if (cinfo.out_color_space == JCS_RGB) { switch (img->colorspace) { default : break; case CUPS_IMAGE_RGB : cupsImageRGBToRGB(in, out, img->xsize); break; case CUPS_IMAGE_WHITE : cupsImageRGBToWhite(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageRGBToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageRGBToCMY(in, out, img->xsize); break; case CUPS_IMAGE_CMYK : cupsImageRGBToCMYK(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut); _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out); } else /* JCS_CMYK */ { fputs("DEBUG: JCS_CMYK\n", stderr); switch (img->colorspace) { default : break; case CUPS_IMAGE_WHITE : cupsImageCMYKToWhite(in, out, img->xsize); break; case CUPS_IMAGE_BLACK : cupsImageCMYKToBlack(in, out, img->xsize); break; case CUPS_IMAGE_CMY : cupsImageCMYKToCMY(in, out, img->xsize); break; case CUPS_IMAGE_RGB : cupsImageCMYKToRGB(in, out, img->xsize); break; } if (lut) cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut); _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out); } } free(in); free(out); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { cups_image_t *img; /* Image to print */ cups_icspace_t primary; /* Primary image colorspace */ FILE *out; /* Output PPM/PGM file */ cups_ib_t *line; /* Line from file */ int y, /* Current line */ width, /* Width of image */ height, /* Height of image */ depth; /* Depth of image */ if (argc != 3) { puts("Usage: testimage filename.ext filename.[ppm|pgm]"); return (1); } if (strstr(argv[2], ".ppm") != NULL) primary = CUPS_IMAGE_RGB; else primary = CUPS_IMAGE_WHITE; img = cupsImageOpen(argv[1], primary, CUPS_IMAGE_WHITE, 100, 0, NULL); if (!img) { perror(argv[1]); return (1); } out = fopen(argv[2], "wb"); if (!out) { perror(argv[2]); cupsImageClose(img); return (1); } width = cupsImageGetWidth(img); height = cupsImageGetHeight(img); depth = cupsImageGetDepth(img); line = calloc(width, depth); fprintf(out, "P%d\n%d\n%d\n255\n", cupsImageGetColorSpace(img) == CUPS_IMAGE_WHITE ? 5 : 6, width, height); for (y = 0; y < height; y ++) { cupsImageGetRow(img, 0, y, width, line); fwrite(line, width, depth, out); } cupsImageClose(img); fclose(out); return (0); }
int /* O - Read status */ _cupsImageReadPhotoCD( cups_image_t *img, /* IO - cupsImage */ FILE *fp, /* I - cupsImage file */ cups_icspace_t primary, /* I - Primary choice for colorspace */ cups_icspace_t secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */ { int x, y; /* Looping vars */ int xdir, /* X direction */ xstart; /* X starting point */ int bpp; /* Bytes per pixel */ int pass; /* Pass number */ int rotation; /* 0 for 768x512, 1 for 512x768 */ int temp, /* Adjusted luminance */ temp2, /* Red, green, and blue values */ cb, cr; /* Adjusted chroma values */ cups_ib_t *in, /* Input (YCC) pixels */ *iy, /* Luminance */ *icb, /* Blue chroma */ *icr, /* Red chroma */ *rgb, /* RGB */ *rgbptr, /* Pointer into RGB data */ *out; /* Output pixels */ (void)secondary; /* * Get the image orientation... */ fseek(fp, 72, SEEK_SET); rotation = (getc(fp) & 63) != 8; /* * Seek to the start of the base image... */ fseek(fp, 0x30000, SEEK_SET); /* * Allocate and initialize... */ img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; img->xppi = 128; img->yppi = 128; if (rotation) { img->xsize = 512; img->ysize = 768; } else { img->xsize = 768; img->ysize = 512; } cupsImageSetMaxTiles(img, 0); bpp = cupsImageGetDepth(img); if ((in = malloc(768 * 3)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); fclose(fp); return (1); } if ((out = malloc(768 * bpp)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); fclose(fp); free(in); return (1); } if (bpp > 1) { if ((rgb = malloc(768 * 3)) == NULL) { fputs("DEBUG: Unable to allocate memory!\n", stderr); fclose(fp); free(in); free(out); return (1); } } else rgb = NULL; if (rotation) { xstart = 767 * bpp; xdir = -2 * bpp; } else { xstart = 0; xdir = 0; } /* * Read the image file... */ for (y = 0; y < 512; y += 2) { /* * Grab the next two scanlines: * * YYYYYYYYYYYYYYY... * YYYYYYYYYYYYYYY... * CbCbCb...CrCrCr... */ if (fread(in, 1, 768 * 3, fp) < (768 * 3)) { /* * Couldn't read a row of data - return an error! */ free(in); free(out); if (bpp > 1) free(rgb); return (-1); } /* * Process the two scanlines... */ for (pass = 0, iy = in; pass < 2; pass ++) { if (bpp == 1) { /* * Just extract the luminance channel from the line and put it * in the image... */ if (primary == CUPS_IMAGE_BLACK) { if (rotation) { for (rgbptr = out + xstart, x = 0; x < 768; x ++) *rgbptr-- = 255 - *iy++; if (lut) cupsImageLut(out, 768, lut); _cupsImagePutCol(img, 511 - y - pass, 0, 768, out); } else { cupsImageWhiteToBlack(iy, out, 768); if (lut) cupsImageLut(out, 768, lut); _cupsImagePutRow(img, 0, y + pass, 768, out); iy += 768; } } else if (rotation) { for (rgbptr = out + xstart, x = 0; x < 768; x ++) *rgbptr-- = 255 - *iy++; if (lut) cupsImageLut(out, 768, lut); _cupsImagePutCol(img, 511 - y - pass, 0, 768, out); } else { if (lut) cupsImageLut(iy, 768, lut); _cupsImagePutRow(img, 0, y + pass, 768, iy); iy += 768; } } else { /* * Convert YCbCr to RGB... While every pixel gets a luminance * value, adjacent pixels share chroma information. */ cb = cr = 0.0f; for (x = 0, rgbptr = rgb + xstart, icb = in + 1536, icr = in + 1920; x < 768; x ++, iy ++, rgbptr += xdir) { if (!(x & 1)) { cb = (float)(*icb - 156); cr = (float)(*icr - 137); } temp = 92241 * (*iy); temp2 = (temp + 86706 * cr) / 65536; if (temp2 < 0) *rgbptr++ = 0; else if (temp2 > 255) *rgbptr++ = 255; else *rgbptr++ = temp2; temp2 = (temp - 25914 * cb - 44166 * cr) / 65536; if (temp2 < 0) *rgbptr++ = 0; else if (temp2 > 255) *rgbptr++ = 255; else *rgbptr++ = temp2; temp2 = (temp + 133434 * cb) / 65536; if (temp2 < 0) *rgbptr++ = 0; else if (temp2 > 255) *rgbptr++ = 255; else *rgbptr++ = temp2; if (x & 1) { icb ++; icr ++; } } /* * Adjust the hue and saturation if needed... */ if (saturation != 100 || hue != 0) cupsImageRGBAdjust(rgb, 768, saturation, hue); /* * Then convert the RGB data to the appropriate colorspace and * put it in the image... */ switch (img->colorspace) { default : break; case CUPS_IMAGE_RGB : cupsImageRGBToRGB(rgb, out, 768); break; case CUPS_IMAGE_CMY : cupsImageRGBToCMY(rgb, out, 768); break; case CUPS_IMAGE_CMYK : cupsImageRGBToCMYK(rgb, out, 768); break; } if (lut) cupsImageLut(out, 768 * bpp, lut); if (rotation) _cupsImagePutCol(img, 511 - y - pass, 0, 768, out); else _cupsImagePutRow(img, 0, y + pass, 768, out); } } } /* * Free memory and return... */ free(in); free(out); if (bpp > 1) free(rgb); return (0); }
cups_izoom_t * _cupsImageZoomNew( cups_image_t *img, /* I - cupsImage to zoom */ int xc0, /* I - Upper-lefthand corner */ int yc0, /* I - ... */ int xc1, /* I - Lower-righthand corner */ int yc1, /* I - ... */ int xsize, /* I - Final width of image */ int ysize, /* I - Final height of image */ int rotated, /* I - Non-zero if image is rotated 90 degs */ cups_iztype_t type) /* I - Zoom type */ { cups_izoom_t *z; /* New zoom record */ int flip; /* Flip on X axis? */ if (xsize > CUPS_IMAGE_MAX_WIDTH || ysize > CUPS_IMAGE_MAX_HEIGHT || (xc1 - xc0) > CUPS_IMAGE_MAX_WIDTH || (yc1 - yc0) > CUPS_IMAGE_MAX_HEIGHT) return (NULL); /* Protect against integer overflow */ if ((z = (cups_izoom_t *)calloc(1, sizeof(cups_izoom_t))) == NULL) return (NULL); z->img = img; z->row = 0; z->depth = cupsImageGetDepth(img); z->rotated = rotated; z->type = type; if (xsize < 0) { flip = 1; xsize = -xsize; } else { flip = 0; } if (rotated) { z->xorig = xc1; z->yorig = yc0; z->width = yc1 - yc0 + 1; z->height = xc1 - xc0 + 1; z->xsize = xsize; z->ysize = ysize; z->xmod = z->width % z->xsize; z->xstep = z->width / z->xsize; z->xincr = 1; z->ymod = z->height % z->ysize; z->ystep = z->height / z->ysize; z->yincr = 1; z->instep = z->xstep * z->depth; z->inincr = /* z->xincr * */ z->depth; /* z->xincr is always 1 */ if (z->width < img->ysize) z->xmax = z->width; else z->xmax = z->width - 1; if (z->height < img->xsize) z->ymax = z->height; else z->ymax = z->height - 1; } else { z->xorig = xc0; z->yorig = yc0; z->width = xc1 - xc0 + 1; z->height = yc1 - yc0 + 1; z->xsize = xsize; z->ysize = ysize; z->xmod = z->width % z->xsize; z->xstep = z->width / z->xsize; z->xincr = 1; z->ymod = z->height % z->ysize; z->ystep = z->height / z->ysize; z->yincr = 1; z->instep = z->xstep * z->depth; z->inincr = /* z->xincr * */ z->depth; /* z->xincr is always 1 */ if (z->width < img->xsize) z->xmax = z->width; else z->xmax = z->width - 1; if (z->height < img->ysize) z->ymax = z->height; else z->ymax = z->height - 1; } if (flip) { z->instep = -z->instep; z->inincr = -z->inincr; } if ((z->rows[0] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL) { free(z); return (NULL); } if ((z->rows[1] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL) { free(z->rows[0]); free(z); return (NULL); } if ((z->in = (cups_ib_t *)malloc(z->width * z->depth)) == NULL) { free(z->rows[0]); free(z->rows[1]); free(z); return (NULL); } return (z); }