From d054ded6c1f00aa3ea3012ffc80a92031a18d469 Mon Sep 17 00:00:00 2001 From: Oliver Rauch Date: Tue, 27 Aug 2002 17:57:19 +0000 Subject: [PATCH] 2002-08-18 Oliver Rauch * frontend/scanimage.c, frontend/stiff.h, frontend/stiff.c: Added option "-i filename"/"--icc-profile filename": When image is saved in tiff format then this icc-profile is added to the tiff file as tiff tag --- frontend/scanimage.c | 14 ++++-- frontend/stiff.c | 112 +++++++++++++++++++++++++++++++++++++++++-- frontend/stiff.h | 2 +- 3 files changed, 118 insertions(+), 10 deletions(-) diff --git a/frontend/scanimage.c b/frontend/scanimage.c index 7606af498..72da55841 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -88,13 +88,14 @@ static struct option basic_options[] = { {"batch-increment", required_argument, NULL, OPTION_BATCH_INCREMENT}, {"format", required_argument, NULL, OPTION_FORMAT}, {"accept-md5-only", no_argument, NULL, OPTION_MD5}, + {"icc-profile", required_argument, NULL, 'i'}, {0, 0, NULL, 0} }; #define OUTPUT_PNM 0 #define OUTPUT_TIFF 1 -#define BASE_OPTSTRING "d:hLf:vVTb" +#define BASE_OPTSTRING "d:hi:Lf:vVTb" #define STRIP_HEIGHT 256 /* # lines we increment image height */ static struct option *all_options; @@ -112,6 +113,7 @@ static int resolution_optind = -1, resolution_value = 0; static SANE_Word window_val[2]; static int window_val_user[2]; /* is width/height user-specified? */ static int accept_only_md5_auth = 0; +static const char *icc_profile = NULL; static void fetch_options (SANE_Device * device); static void scanimage_exit (void); @@ -1079,7 +1081,7 @@ scan_it (void) if (output_format == OUTPUT_TIFF) sanei_write_tiff_header (parm.format, parm.pixels_per_line, parm.lines, - parm.depth, resolution_value); + parm.depth, resolution_value, icc_profile); else write_pnm_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth); @@ -1246,7 +1248,7 @@ scan_it (void) image.height = image.y; if (output_format == OUTPUT_TIFF) sanei_write_tiff_header (parm.format, parm.pixels_per_line, - parm.lines, parm.depth, resolution_value); + parm.lines, parm.depth, resolution_value, icc_profile); else write_pnm_header (parm.format, image.width, image.height, parm.depth); if ((output_format == OUTPUT_TIFF) || (image.Bpp == 1) @@ -1495,6 +1497,9 @@ main (int argc, char **argv) case 'h': help = 1; break; + case 'i': /* icc profile */ + icc_profile = optarg; + break; case 'v': ++verbose; break; @@ -1676,7 +1681,8 @@ standard output.\n\ -T, --test test backend thoroughly\n\ -v, --verbose give even more status messages\n\ -V, --version print version information\n\ - --accept-md5-only only accept authorization requests using md5\n", prog_name); + --accept-md5-only only accept authorization requests using md5\n\ +-i, --icc-profile=PROFILE include this ICC profile into TIFF file\n", prog_name); if (!devname) { diff --git a/frontend/stiff.c b/frontend/stiff.c index eeebb6fed..a94124244 100644 --- a/frontend/stiff.c +++ b/frontend/stiff.c @@ -1,5 +1,6 @@ /* Create SANE/tiff headers TIFF interfacing routines for SANE Copyright (C) 2000 Peter Kirchgessner + Copyright (C) 2002 Oliver Rauch: added tiff ICC profile This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -18,6 +19,7 @@ /* Changes: 2000-11-19, PK: Color TIFF-header: write 3 values for bits per sample 2001-12-16, PK: Write fill order tag for b/w-images + 2002-08-27, OR: Added tiff tag for ICC profile */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ @@ -260,13 +262,30 @@ write_tiff_bw_header (FILE *fptr, int width, int height, int resolution) static void write_tiff_grey_header (FILE *fptr, int width, int height, int depth, - int resolution) + int resolution, const char *icc_profile) {IFD *ifd; int header_size = 8, ifd_size; int strip_offset, data_offset, data_size; int strip_bytecount; int ntags; int motorola, bps, maxsamplevalue; + FILE *icc_file = 0; + int icc_len = -1; + + if (icc_profile) + { + icc_file = fopen(icc_profile, "r"); + + if (!icc_file) + { + fprintf(stderr, "Could not open ICC profile %s\n", icc_profile); + } + else + { + icc_len = 16777216 * fgetc(icc_file)*65536+fgetc(icc_file)+fgetc(icc_file)*256+fgetc(icc_file); + rewind(icc_file); + } + } ifd = create_ifd (); @@ -283,6 +302,12 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth, data_size += 2*4 + 2*4; } + if (icc_len > 0) /* if icc profile exists add memory for tag */ + { + ntags += 1; + data_size += icc_len; + } + ifd_size = 2 + ntags*12 + 4; data_offset = header_size + ifd_size; strip_offset = data_offset + data_size; @@ -330,6 +355,12 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth, add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2); } + if (icc_len > 0) /* add ICC-profile TAG */ + { + add_ifd_entry(ifd, 34675, 7, icc_len, data_offset); + data_offset += icc_len; + } + /* I prefer motorola format. Its human readable. But for 16 bit, */ /* the image format is defined by SANE to be the native byte order */ if (bps == 1) @@ -352,19 +383,55 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth, write_i4 (fptr, 1, motorola); } + /* Write ICC profile */ + if (icc_len > 0) + { + int i; + for (i=0; i 0) { ntags += 3; data_size += 2*4 + 2*4; } + if (icc_len > 0) /* if icc profile exists add memory for tag */ + { + ntags += 1; + data_size += icc_len; + } + + ifd_size = 2 + ntags*12 + 4; data_offset = header_size + ifd_size; strip_offset = data_offset + data_size; @@ -416,6 +491,7 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth, /* max sample value */ add_ifd_entry (ifd, 281, IFDE_TYP_SHORT, 3, data_offset); data_offset += 3*2; + if (resolution > 0) { /* x resolution */ @@ -425,12 +501,20 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth, add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; } + if (resolution > 0) { /* resolution unit (dpi) */ add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2); } + if (icc_len > 0) /* add ICC-profile TAG */ + { + add_ifd_entry(ifd, 34675, 7, icc_len, data_offset); + data_offset += icc_len; + } + + /* I prefer motorola format. Its human readable. But for 16 bit, */ /* the image format is defined by SANE to be the native byte order */ if (bps == 1) @@ -468,13 +552,31 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth, write_i4 (fptr, 1, motorola); } + /* Write ICC profile */ + if (icc_len > 0) + { + int i; + for (i=0; i