From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- xicc/xutils.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 xicc/xutils.c (limited to 'xicc/xutils.c') diff --git a/xicc/xutils.c b/xicc/xutils.c new file mode 100644 index 0000000..019cee6 --- /dev/null +++ b/xicc/xutils.c @@ -0,0 +1,294 @@ + +/* + * xicc standalone utilities + * + * Author: Graeme W. Gill + * Date: 2/7/00 + * Version: 1.00 + * + * Copyright 2000 - 2006 Graeme W. Gill + * All rights reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + * + */ + +/* + * This module provides expanded capabilities, + * but is independent of other modules. + */ + +#include +#include +#include +#include +#ifdef __sun +#include +#endif +#if defined(__IBMC__) && defined(_M_IX86) +#include +#endif +#include "copyright.h" +#include "aconfig.h" +#include "icc.h" +#include "tiffio.h" +#include "jpeglib.h" +#include "iccjpeg.h" +#include "xutils.h" /* definitions for this library */ + + +#undef DEBUG + +#ifdef DEBUG +# define errout stderr +# define debug(xx) fprintf(errout, xx ) +# define debug2(xx) fprintf xx +#else +# define debug(xx) +# define debug2(xx) +#endif + +#if !defined(O_CREAT) && !defined(_O_CREAT) +# error "Need to #include fcntl.h!" +#endif + +/* ------------------------------------------------------ */ +/* Common clut table code */ + +/* Default table of clut resolutions */ +/* See discussion in imdi/imdi_gen.c for ideal numbers */ +static int lut_resolutions[9][4] = { + /* low, med, high, vhigh */ + { 0, 0, 0, 0 }, /* 0 */ + { 256, 772, 4370, 4370 }, /* 1 */ + { 86, 256, 256, 256 }, /* 2 */ + { 9, 17, 33, 52 }, /* 3 */ + { 6, 9, 18, 33 }, /* 4 */ + { 6, 9, 16, 18 }, /* 5 */ + { 6, 6, 9, 12 }, /* 6 */ + { 6, 7, 7, 9 }, /* 7 */ + { 3, 5, 5, 7 } /* 8 */ +}; + + +/* return a lut resolution given the input dimesion and quality */ +/* Input dimension [0-8], quality: low 0, medium 1, high 2, very high 3 . */ +/* A returned value of 0 indicates illegal. */ +int dim_to_clutres(int dim, int quality) { + if (dim < 0) + dim = 0; + else if (dim > 8) + dim = 8; + if (quality < 0) + quality = 0; + if (quality > 3) + quality = 3; + return lut_resolutions[dim][quality]; +} + +/* ------------------------------------------------------ */ + +/* JPEG error information */ +typedef struct { + jmp_buf env; /* setjmp/longjmp environment */ + char message[JMSG_LENGTH_MAX]; +} jpegerrorinfo; + +/* JPEG error handler */ +static void jpeg_error(j_common_ptr cinfo) { + jpegerrorinfo *p = (jpegerrorinfo *)cinfo->client_data; + (*cinfo->err->format_message) (cinfo, p->message); + longjmp(p->env, 1); +} + +/* ------------------------------------------------------ */ + +/* Open an ICC file or a TIFF or JPEG file with an embedded ICC profile for reading. */ +/* Return NULL on error */ +icc *read_embedded_icc(char *file_name) { + TIFF *rh = NULL; + int size; + void *tag, *buf; + icmAlloc *al; + icmFile *fp; + icc *icco; + TIFFErrorHandler olderrh, oldwarnh; + TIFFErrorHandlerExt olderrhx, oldwarnhx; + int rv; + + /* First see if the file can be opened as an ICC profile */ + if ((fp = new_icmFileStd_name(file_name,"r")) == NULL) { + debug2((errout,"Can't open file '%s'\n",file_name)); + return NULL; + } + + if ((icco = new_icc()) == NULL) { + debug("Creation of ICC object failed\n"); + fp->del(fp); + return NULL; + } + + if ((rv = icco->read_x(icco,fp,0,1)) == 0) { + debug2((errout,"Opened '%s' as an icc profile\n",file_name)); + return icco; + } + + debug2((errout,"icc read failed with %d, %s\n",rv,icco->err)); + icco->del(icco); /* icc wil fp->del() */ + + /* Not an ICC profile, see if it's a TIFF file */ + olderrh = TIFFSetErrorHandler(NULL); + oldwarnh = TIFFSetWarningHandler(NULL); + olderrhx = TIFFSetErrorHandlerExt(NULL); + oldwarnhx = TIFFSetWarningHandlerExt(NULL); + + if ((rh = TIFFOpen(file_name, "r")) != NULL) { + TIFFSetErrorHandler(olderrh); + TIFFSetWarningHandler(oldwarnh); + TIFFSetErrorHandlerExt(olderrhx); + TIFFSetWarningHandlerExt(oldwarnhx); + debug("TIFFOpen suceeded\n"); + + if (TIFFGetField(rh, TIFFTAG_ICCPROFILE, &size, &tag) == 0 || size == 0) { + debug2((errout,"no ICC profile found in '%s'\n",file_name)); + TIFFClose(rh); + return NULL; + } + + /* Make a copy of the profile to a memory buffer */ + if ((al = new_icmAllocStd()) == NULL) { + debug("new_icmAllocStd failed\n"); + TIFFClose(rh); + return NULL; + } + if ((buf = al->malloc(al, size)) == NULL) { + debug("malloc of profile buffer failed\n"); + al->del(al); + TIFFClose(rh); + return NULL; + } + + memmove(buf, tag, size); + TIFFClose(rh); + + } else { + jpegerrorinfo jpeg_rerr; + FILE *rf = NULL; + struct jpeg_decompress_struct rj; + struct jpeg_error_mgr jerr; + unsigned char *pdata; + unsigned int plen; + + debug2((errout,"TIFFOpen failed for '%s'\n",file_name)); + TIFFSetErrorHandler(olderrh); + TIFFSetWarningHandler(oldwarnh); + TIFFSetErrorHandlerExt(olderrhx); + TIFFSetWarningHandlerExt(oldwarnhx); + + /* We cope with the horrible ijg jpeg library error handling */ + /* by using a setjmp/longjmp. */ + jpeg_std_error(&jerr); + jerr.error_exit = jpeg_error; + if (setjmp(jpeg_rerr.env)) { + debug2((errout,"jpeg_read_header failed for '%s'\n",file_name)); + jpeg_destroy_decompress(&rj); + fclose(rf); + return NULL; + } + + rj.err = &jerr; + rj.client_data = &jpeg_rerr; + jpeg_create_decompress(&rj); + +#if defined(O_BINARY) || defined(_O_BINARY) + if ((rf = fopen(file_name,"rb")) == NULL) +#else + if ((rf = fopen(file_name,"r")) == NULL) +#endif + { + debug2((errout,"fopen failed for '%s'\n",file_name)); + jpeg_destroy_decompress(&rj); + return NULL; + } + + jpeg_stdio_src(&rj, rf); + setup_read_icc_profile(&rj); + + /* we'll longjmp on error */ + jpeg_read_header(&rj, TRUE); + + if (!read_icc_profile(&rj, &pdata, &plen)) { + debug2((errout,"no ICC profile found in '%s'\n",file_name)); + jpeg_destroy_decompress(&rj); + fclose(rf); + return NULL; + } + jpeg_destroy_decompress(&rj); + fclose(rf); + + /* Make a copy of the profile to a memory buffer */ + /* (icmAllocStd may not be the same as malloc ?) */ + if ((al = new_icmAllocStd()) == NULL) { + debug("new_icmAllocStd failed\n"); + return NULL; + } + if ((buf = al->malloc(al, plen)) == NULL) { + debug("malloc of profile buffer failed\n"); + al->del(al); + TIFFClose(rh); + return NULL; + } + memmove(buf, pdata, plen); + size = (int)plen; + free(pdata); + } + + /* Memory File fp that will free the buffer when deleted: */ + if ((fp = new_icmFileMem_ad(buf, size, al)) == NULL) { + debug("Creating memory file from CMProfileLocation failed"); + al->free(al, buf); + al->del(al); + return NULL; + } + + if ((icco = new_icc()) == NULL) { + debug("Creation of ICC object failed\n"); + fp->del(fp); /* fp will delete al */ + return NULL; + } + + if ((rv = icco->read_x(icco,fp,0,1)) == 0) { + debug2((errout,"Opened '%s' embedded icc profile\n",file_name)); + return icco; + } + + debug2((errout,"Failed to read '%s' embedded icc profile\n",file_name)); + icco->del(icco); /* icco will delete fp and al */ + return NULL; +} + +/* ------------------------------------------------------ */ + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3