📄 cctiff2.c
字号:
if next_space == CIE set dir = fwd next_space = profile.devspace else set dir = bwd check next_space == profile.devspace next_space = CIE create luo Make output TIFF colorspace match next_space Set any special output space encoding transform (ie. device, Lab flavour)*/ /* - - - - - - - - - - - - - - - */ /* Open up input tiff file ready for reading */ /* Discover input TIFF colorspace and set as (ICC) "last_colorspace" */ /* Set any special input space encoding transform (ie. device, Lab flavour) */ if ((rh = TIFFOpen(in_name, "r")) == NULL) error("error opening read file '%s'",in_name); TIFFGetField(rh, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(rh, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(rh, TIFFTAG_BITSPERSAMPLE, &bitspersample); if (bitspersample != 8 && bitspersample != 16) { error("TIFF Input file must be 8 or 16 bit/channel"); } TIFFGetField(rh, TIFFTAG_PHOTOMETRIC, &rphotometric); TIFFGetField(rh, TIFFTAG_SAMPLESPERPIXEL, &rsamplesperpixel); /* Figure out how to handle the input TIFF colorspace */ if ((su.ins = TiffPhotometric2ColorSpaceSignature(NULL, &su.icvt, &su.isign_mask, rphotometric, bitspersample, rsamplesperpixel)) == 0) error("Can't handle TIFF file photometric %s", Photometric2str(rphotometric)); TIFFGetField(rh, TIFFTAG_PLANARCONFIG, &pconfig); if (pconfig != PLANARCONFIG_CONTIG) error ("TIFF Input file must be planar"); TIFFGetField(rh, TIFFTAG_RESOLUTIONUNIT, &resunits); TIFFGetField(rh, TIFFTAG_XRESOLUTION, &resx); TIFFGetField(rh, TIFFTAG_YRESOLUTION, &resy); last_colorspace = su.ins; if (su.verb) { printf("TIFF file colorspace is %s\n",icm2str(icmColorSpaceSignature,su.ins)); } /* - - - - - - - - - - - - - - - */ /* Check and setup the chain of ICC profiles */ /* For each profile in the chain, configure it to transform the color */ /* appropriately */ for (i = 0; i < su.nprofs; i++) { /* Open up the profile for reading */ if ((su.profs[i].fp = new_icmFileStd_name(su.profs[i].name,"r")) == NULL) error ("Can't open profile '%s'",su.profs[i].name); if ((su.profs[i].c = new_icc()) == NULL) error ("Creation of ICC object for '%s' failed",su.profs[i].name); if ((rv = su.profs[i].c->read(su.profs[i].c, su.profs[i].fp, 0)) != 0) error ("%d, %s from '%s'",rv,su.profs[i].c->err,su.profs[i].name); su.profs[i].h = su.profs[i].c->header; /* Deal with different profile classes */ switch (su.profs[i].h->deviceClass) { case icSigAbstractClass: case icSigLinkClass: su.profs[i].func = icmFwd; su.profs[i].intent = icmDefaultIntent; break; case icSigColorSpaceClass: su.profs[i].intent = icmDefaultIntent; /* Fall through */ case icSigInputClass: case icSigDisplayClass: case icSigOutputClass: /* Note we don't handle an ambigious (both directions match) case. */ /* We would need direction from the user to resolve this. */ if (CSMatch(last_colorspace, su.profs[i].h->colorSpace)) su.profs[i].func = icmFwd; else { su.profs[i].func = icmBwd; /* PCS -> Device */ } break; default: error("Can't handle deviceClass %s from file '%s'", icm2str(icmProfileClassSignature,su.profs[i].h->deviceClass), su.profs[i].c->err,su.profs[i].name); } /* Get a conversion object */ if ((su.profs[i].luo = su.profs[i].c->get_luobj(su.profs[i].c, su.profs[i].func, su.profs[i].intent, icmSigDefaultData, icmLuOrdNorm)) == NULL) error ("%d, %s from '%s'",su.profs[i].c->errc, su.profs[i].c->err, su.profs[i].name); /* Get details of conversion */ su.profs[i].luo->spaces(su.profs[i].luo, &su.profs[i].ins, &su.profs[i].id, &su.profs[i].outs, &su.profs[i].od, &su.profs[i].alg, NULL, NULL, NULL); /* Get native PCS space */ su.profs[i].luo->lutspaces(su.profs[i].luo, NULL, NULL, NULL, NULL, &su.profs[i].natpcs); if (su.verb) { icmFile *op; if ((op = new_icmFileStd_fp(stdout)) == NULL) error ("Can't open stdout"); su.profs[i].h->dump(su.profs[i].h, op, 1); op->del(op); } /* Check that we can join to previous correctly */ if (!CSMatch(last_colorspace, su.profs[i].ins)) error("Last colorspace %s doesn't match input space %s of profile %s", icm2str(icmColorSpaceSignature,last_colorspace), icm2str(icmColorSpaceSignature,su.profs[i].h->colorSpace), su.profs[i].name); } /* Setup input/output curve use. if (su.profs[0].natpcs == icSigXYZData) su.icombine = 1; /* XYZ is to non-linear to be a benefit */ if (su.profs[su.nprofs-1].natpcs == icSigXYZData) su.ocombine = 1; /* XYZ is to non-linear to be a benefit */ /* - - - - - - - - - - - - - - - */ /* Open up the output file for writing */ if ((wh = TIFFOpen(out_name, "w")) == NULL) error("Can\'t create TIFF file '%s'!",out_name); wsamplesperpixel = su.profs[su.nprofs-1].od; su.od = wsamplesperpixel; /* Lookup and decide what TIFF photometric suites the output colorspace */ { int no_pmtc; /* Number of possible photometrics */ uint16 pmtc[10]; /* Photometrics of output file */ if ((no_pmtc = ColorSpaceSignature2TiffPhotometric(pmtc, last_colorspace)) == 0) error("TIFF file can't handle output colorspace '%s'!", icm2str(icmColorSpaceSignature, last_colorspace)); if (no_pmtc > 1) { /* Choose photometric */ if (su.verb) { printf("Possible photometrics for output colorspace %s are:\n", icm2str(icmColorSpaceSignature,last_colorspace)); for (i = 0; i < no_pmtc; i++) printf("%d: %s\n",i+1, Photometric2str(pmtc[i])); } if (ochoice < 1) ochoice = 1; else if (ochoice > no_pmtc) ochoice = no_pmtc; if (su.verb) printf("Using choice %d\n",ochoice); } wphotometric = pmtc[ochoice-1]; } /* Lookup what we need to handle this. */ if ((su.outs = TiffPhotometric2ColorSpaceSignature(&su.ocvt, NULL, &su.osign_mask, wphotometric, bitspersample, wsamplesperpixel)) == 0) error("Can't handle TIFF file photometric %s", Photometric2str(wphotometric)); /* Configure the output TIFF file appropriately */ TIFFSetField(wh, TIFFTAG_PHOTOMETRIC, wphotometric); if (wphotometric == PHOTOMETRIC_SEPARATED) { int iset; char *inames; iset = ColorSpaceSignature2TiffInkset(su.outs, &inames); if (iset != 0xffff) { TIFFSetField(wh, TIFFTAG_INKSET, iset); if (inames != NULL) { TIFFSetField(wh, TIFFTAG_INKNAMES, inames); } } } TIFFSetField(wh, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(wh, TIFFTAG_IMAGELENGTH, height); TIFFSetField(wh, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(wh, TIFFTAG_SAMPLESPERPIXEL, wsamplesperpixel); TIFFSetField(wh, TIFFTAG_BITSPERSAMPLE, bitspersample); TIFFSetField(wh, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(wh, TIFFTAG_COMPRESSION, COMPRESSION_NONE); if (resunits) { TIFFSetField(wh, TIFFTAG_RESOLUTIONUNIT, resunits); TIFFSetField(wh, TIFFTAG_XRESOLUTION, resx); TIFFSetField(wh, TIFFTAG_YRESOLUTION, resy); } TIFFSetField(wh, TIFFTAG_IMAGEDESCRIPTION, "Color corrected by Argyll"); /* - - - - - - - - - - - - - - - */ /* Setup the imdi */ /* Setup the imdi resolution */#ifdef NEVER if (only one profile in link) set res to res of first profile else select from table of link resolutions#endif /* If one conversion, make the resolution the same */ if (su.nprofs == 1 && su.profs[0].alg == icmLutType) { icmLut *lut; icmLuLut *luluo = (icmLuLut *)su.profs[0].luo; /* Safe to coerce */ luluo->get_info(luluo, &lut, NULL, NULL, NULL); /* Get some details */ clutres = lut->clutPoints; /* Desired table resolution */ } if (clutres <= 0) { /* Choose a "high quality" clut resolution. */ /* ~~ should scan through all the conversions and */ /* choose a level equal or greater than all conversions~~~~ */ if ((clutres = dim_to_clutres(su.id, 2)) == 0) error ("Illegal number of input chanels"); }// ~~~9999 if (!slow) { s = new_imdi( su.id, /* Number of input dimensions */ su.od, /* Number of output dimensions */ /* Input pixel representation */ bitspersample == 8 ? pixint8 : pixint16, /* Output pixel representation */ 0x0, /* Treat every channel as unsigned */ bitspersample == 8 ? pixint8 : pixint16, 0x0, /* Treat every channel as unsigned */ clutres, /* Desired table resolution */ input_curve, /* Callback functions */ md_table, output_curve, (void *)&su /* Context to callbacks */ ); if (s == NULL) error("new_imdi failed"); } /* - - - - - - - - - - - - - - - */ /* Process colors to translate */ /* (Should fix this to process a group of lines at a time ?) */ inbuf = _TIFFmalloc(TIFFScanlineSize(rh)); outbuf = _TIFFmalloc(TIFFScanlineSize(wh)); if (check) checkbuf = _TIFFmalloc(TIFFScanlineSize(wh)); inp[0] = (unsigned char *)inbuf; outp[0] = (unsigned char *)outbuf; if (!slow) { /* Fast */ for (y = 0; y < height; y++) { /* Read in the next line */ if (TIFFReadScanline(rh, inbuf, y, 0) < 0) error ("Failed to read TIFF line %d",y); /* Do fast conversion */ s->interp(s, (void **)outp, (void **)inp, width); if (check) { /* Do floating point conversion */ for (x = 0; x < width; x++) { int i; double in[MAX_CHAN], out[MAX_CHAN]; if (bitspersample == 8) for (i = 0; i < su.id; i++) in[i] = ((unsigned char *)inbuf)[x * su.id + i]/255.0; else for (i = 0; i < su.id; i++) in[i] = ((unsigned short *)inbuf)[x * su.id + i]/65535.0; if (su.link) { if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } else { if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } if (bitspersample == 8) for (i = 0; i < su.od; i++) ((unsigned char *)checkbuf)[x * su.od + i] = (int)(out[i] * 255.0 + 0.5); else for (i = 0; i < su.od; i++) ((unsigned short *)checkbuf)[x * su.od + i] = (int)(out[i] * 65535.0 + 0.5); } /* Compute the errors */ for (x = 0; x < (width * su.od); x++) { int err; if (bitspersample == 8) err = ((unsigned char *)outbuf)[x] - ((unsigned char *)checkbuf)[x]; else err = ((unsigned short *)outbuf)[x] - ((unsigned short *)checkbuf)[x]; if (err < 0) err = -err; if (err > mxerr) mxerr = err; avgerr += (double)err; avgcount++; } } if (TIFFWriteScanline(wh, outbuf, y, 0) < 0) error ("Failed to write TIFF line %d",y); } } else { /* Slow but precise */ if (bitspersample == 8) { for (y = 0; y < height; y++) { /* Read in the next line */ if (TIFFReadScanline(rh, inbuf, y, 0) < 0) error ("Failed to read TIFF line %d",y); /* Do floating point conversion */ for (x = 0; x < width; x++) { int i; double in[MAX_CHAN], out[MAX_CHAN]; for (i = 0; i < su.id; i++) { in[i] = ((unsigned char *)inbuf)[x * su.id + i]/255.0; } if (su.link) { if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } else { if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } for (i = 0; i < su.od; i++) { ((unsigned char *)outbuf)[x * su.od + i] = (int)(out[i] * 255.0 + 0.5); } } if (TIFFWriteScanline(wh, outbuf, y, 0) < 0) error ("Failed to write TIFF line %d",y); } } else if (bitspersample == 16) { for (y = 0; y < height; y++) { /* Read in the next line */ if (TIFFReadScanline(rh, inbuf, y, 0) < 0) error ("Failed to read TIFF line %d",y); /* Do floating point conversion */ for (x = 0; x < width; x++) { int i; double in[MAX_CHAN], out[MAX_CHAN]; for (i = 0; i < su.id; i++) { in[i] = ((unsigned short *)inbuf)[x * su.id + i]/65535.0; } if (su.link) { if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } else { if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1) error ("%d, %s",su.dev.c->errc,su.dev.c->err); } for (i = 0; i < su.od; i++) { ((unsigned short *)outbuf)[x * su.od + i] = (int)(out[i] * 65535.0 + 0.5); } } if (TIFFWriteScanline(wh, outbuf, y, 0) < 0) error ("Failed to write TIFF line %d",y); } } } if (check) { printf("Worst error = %d bits, average error = %f bits\n", mxerr, avgerr/avgcount); if (bitspersample == 8) printf("Worst error = %f%%, average error = %f%%\n", mxerr/2.55, avgerr/(2.55 * avgcount)); else printf("Worst error = %f%%, average error = %f%%\n", mxerr/655.35, avgerr/(655.35 * avgcount)); } /* Done with lookup object */ if (s != NULL) s->done(s); if (su.link) { su.in.luo->del(su.in.luo); su.in.c->del(su.in.c); su.in.fp->del(su.in.fp); su.out.luo->del(su.out.luo); su.out.c->del(su.out.c); su.out.fp->del(su.out.fp); } else { su.dev.luo->del(su.dev.luo); su.dev.c->del(su.dev.c); su.dev.fp->del(su.dev.fp); } _TIFFfree(inbuf); _TIFFfree(outbuf); if (check) _TIFFfree(checkbuf); TIFFClose(rh); /* Close Input file */ TIFFClose(wh); /* Close Output file */ return 0;}/* Basic printf type error() and warning() routines */voiderror(char *fmt, ...){ va_list args; fprintf(stderr,"cctiff: Error - "); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); exit (-1);}voidwarning(char *fmt, ...){ va_list args; fprintf(stderr,"cctiff: Warning - "); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -