📄 cctiff.c
字号:
/* * Color Correct a TIFF file, using an ICC Device link profile. * * Author: Graeme W. Gill * Date: 00/3/8 * Version: 1.30 * * Copyright 2000 - 2004 Graeme W. Gill * All rights reserved. * * This material is licenced under the GNU GENERAL PUBLIC LICENCE :- * see the Licence.txt file for licencing details. *//* * Thanks to Neil Okamoto for the 16 bit TIFF mods. *//* TTBD: *//* This program is a framework that exercises the IMDI code, as well as a demonstration of simple profile linking. It can also do the conversion using the floating point code in ICCLIB as a reference. */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <fcntl.h>#include <string.h>#include <math.h>#include "copyright.h"#include "config.h"#include "tiffio.h"#include "icc.h"#include "imdi.h"#undef TREAT_CMY_AS_RGBvoid error(char *fmt, ...), warning(char *fmt, ...);void usage(void) { fprintf(stderr,"Color Correct a TIFF file using an ICC device link profile, V%s\n",ARGYLL_VERSION_STR); fprintf(stderr,"Author: Graeme W. Gill, licensed under the GPL\n"); fprintf(stderr,"usage: cctiff [-options] devlinkprofile.icm infile.tif outfile.tif\n"); fprintf(stderr,"usage: cctiff [-options] -l inprofile.icm outprofile.icm infile.tif outfile.tif\n"); fprintf(stderr," -v Verbose\n"); fprintf(stderr," -c Combine linearisation curves into one transform\n"); fprintf(stderr," -p Use slow precise correction\n"); fprintf(stderr," -k Check fast result against precise, and report\n"); fprintf(stderr," -l Link input and output profiles\n"); fprintf(stderr," -i in_intent p = perceptual, r = relative colorimetric,\n"); fprintf(stderr," s = saturation, a = absolute colorimetric\n"); fprintf(stderr," -o out_intent p = perceptual, r = relative colorimetric,\n"); fprintf(stderr," s = saturation, a = absolute colorimetric\n"); exit(1);}/* Convert an ICC colorspace to the corresponding possible TIFF Photometric tags. *//* Return the number of matching tags, and 0 if there is no corresponding tag. */intColorSpaceSignature2TiffPhotometric(uint16 tags[10], /* Pointer to return array, up to 10 */icColorSpaceSignature cspace /* Input ICC colorspace */) { switch(cspace) { case icSigGrayData: tags[0] = PHOTOMETRIC_MINISBLACK; return 1; case icSigRgbData:#ifdef TREAT_CMY_AS_RGB case icSigCmyData:#endif tags[0] = PHOTOMETRIC_RGB; return 1;#ifndef TREAT_CMY_AS_RGB case icSigCmyData:#endif case icSigCmykData: tags[0] = PHOTOMETRIC_SEPARATED; return 1; case icSigYCbCrData: tags[0] = PHOTOMETRIC_YCBCR; return 1; case icSigLabData: tags[0] = PHOTOMETRIC_CIELAB;#ifdef PHOTOMETRIC_ICCLAB tags[1] = PHOTOMETRIC_ICCLAB; tags[2] = PHOTOMETRIC_ITULAB;#endif return 3; case icSigXYZData: case icSigLuvData: case icSigYxyData: case icSigHsvData: case icSigHlsData: return 0; case icSig2colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 2; /* Cheat */ return 1; case icSig3colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 3; /* Cheat */ return 1; case icSig4colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 4; /* Cheat */ return 1; case icSig5colorData: case icSigMch5Data: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 5; /* Cheat */ return 1; case icSig6colorData: case icSigMch6Data: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 6; /* Cheat */ return 1; case icSig7colorData: case icSigMch7Data: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 7; /* Cheat */ return 1; case icSig8colorData: case icSigMch8Data: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 8; /* Cheat */ return 1; case icSig9colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 9; /* Cheat */ return 1; case icSig10colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 10; /* Cheat */ return 1; case icSig11colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 11; /* Cheat */ return 1; case icSig12colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 12; /* Cheat */ return 1; case icSig13colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 13; /* Cheat */ return 1; case icSig14colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 14; /* Cheat */ return 1; case icSig15colorData: tags[0] = PHOTOMETRIC_SEPARATED; tags[1] = 15; /* Cheat */ return 1; default: return 0; } return 0;}/* Compute the length of a double nul terminated string, including *//* the nuls. */static int zzstrlen(char *s) { int i; for (i = 0;; i++) { if (s[i] == '\000' && s[i+1] == '\000') return i+2; } return 0;}/* Convert an ICC colorspace to the corresponding TIFF Inkset tag *//* return 0xffff if not possible or applicable. */intColorSpaceSignature2TiffInkset(icColorSpaceSignature cspace,int *len, /* Return length of ASCII inknames */char **inknames /* Return ASCII inknames if non NULL */) { switch(cspace) { case icSigCmyData: return 0xffff; // ~~9999 if (inknames != NULL) { *inknames = "cyan\000magenta\000yellow\000\000"; *len = zzstrlen(*inknames); } return 0; /* Not CMYK */ case icSigCmykData: if (inknames != NULL) { *inknames = NULL; /* No inknames */ *len = 0; } return INKSET_CMYK; case icSigGrayData: case icSigRgbData: case icSigYCbCrData: case icSigLabData: case icSigXYZData: case icSigLuvData: case icSigYxyData: case icSigHsvData: case icSigHlsData: case icSig2colorData: case icSig3colorData: case icSig4colorData: case icSig5colorData: case icSigMch5Data: return 0xffff; case icSig6colorData: case icSigMch6Data: /* This is a cheat and a hack. Should really make sure that icclink */ /* transfers the right information from the destination */ /* profile, and then copies it to the device profile, */ /* allowing cctiff to read it. */ if (inknames != NULL) { *inknames = "cyan\000magenta\000yellow\000black\000orange\000green\000\000"; *len = zzstrlen(*inknames); } return 0; /* Not CMYK */ case icSig7colorData: case icSigMch7Data: return 0xffff; case icSig8colorData: case icSigMch8Data: /* This is a cheat and a hack. Should really make sure that icclink */ /* transfers the right information from the destination */ /* profile, and then copies it to the device profile, */ /* allowing cctiff to read it. */ if (inknames != NULL) { *inknames = "cyan\000magenta\000yellow\000black\000orange\000green\000lightcyan\000lightmagenta\000\000"; *len = zzstrlen(*inknames); } return 0; /* Not CMYK */ case icSig9colorData: case icSig10colorData: case icSig11colorData: case icSig12colorData: case icSig13colorData: case icSig14colorData: case icSig15colorData: default: return 0xffff; } return 0xffff;}char *Photometric2str(int pmtc) { static char buf[80]; switch (pmtc) { case PHOTOMETRIC_MINISWHITE: return "Subtractive Gray"; case PHOTOMETRIC_MINISBLACK: return "Additive Gray"; case PHOTOMETRIC_RGB: return "RGB"; case PHOTOMETRIC_PALETTE: return "Indexed"; case PHOTOMETRIC_MASK: return "Transparency Mask"; case PHOTOMETRIC_SEPARATED: return "Separated"; case PHOTOMETRIC_YCBCR: return "YCbCr"; case PHOTOMETRIC_CIELAB: return "CIELab";#ifdef PHOTOMETRIC_ICCLAB case PHOTOMETRIC_ICCLAB: return "ICCLab"; case PHOTOMETRIC_ITULAB: return "ITULab";#endif case PHOTOMETRIC_LOGL: return "CIELog2L"; case PHOTOMETRIC_LOGLUV: return "CIELog2Luv"; } sprintf(buf,"Unknonw Tag %d",pmtc); return buf;}/* Callbacks used to initialise imdi *//* Information needed from a profile */struct _profinfo { char name[100]; icmFile *fp; icc *c; icmHeader *h; icRenderingIntent intent; icmLuBase *luo; /* Base Lookup type object */ icmLuAlgType alg; /* Type of lookup algorithm */ int chan; /* Device channels */}; typedef struct _profinfo profinfo;/* Context for imdi setup callbacks */typedef struct { /* Overall parameters */ int verb; /* Non-zero if verbose */ icColorSpaceSignature ins, outs; /* Input/Output spaces */ int id, od; /* Input/Output dimensions */ int icombine; /* Non-zero if input curves are to be combined */ int ocombine; /* Non-zero if output curves are to be combined */ int link; /* Non-zero if input and output profiles are to be linked */ profinfo dev; /* Device link profile */ profinfo in; /* Device to PCS profile */ profinfo out; /* PCS to Device profile */} sucntx;/* Input curve function */double input_curve( void *cntx, int ch, double in_val) { sucntx *rx = (sucntx *)cntx; int i; double vals[MAX_CHAN]; if (rx->icombine) return in_val; if (rx->link) { for (i = 0; i < rx->id; i++) vals[i] = 0.0; vals[ch] = in_val; switch(rx->in.alg) { case icmMonoFwdType: { icmLuMono *lu = (icmLuMono *)rx->in.luo; /* Safe to coerce */ lu->fwd_curve(lu, vals, vals); break; } case icmMatrixFwdType: { icmLuMatrix *lu = (icmLuMatrix *)rx->in.luo; /* Safe to coerce */ lu->fwd_curve(lu, vals, vals); break; } case icmLutType: { icmLuLut *lu = (icmLuLut *)rx->in.luo; /* Safe to coerce */ /* Since not PCS, in_abs and matrix cannot be valid, */ /* so input curve on own is ok to use. */ lu->input(lu, vals, vals); break; } default: error("Unexpected algorithm type in input curve"); } } else { icmLuLut *lu = (icmLuLut *)rx->dev.luo; /* Safe to coerce */ for (i = 0; i < rx->id; i++) vals[i] = 0.0; vals[ch] = in_val; /* Since input not PCS, in_abs and matrix cannot be valid, */ /* so input curve on own is ok to use. */ lu->input(lu, vals, vals); } return vals[ch];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -