diff options
author | Marti Maria <info@littlecms.com> | 2010-02-08 17:20:25 +0100 |
---|---|---|
committer | Marti Maria <info@littlecms.com> | 2010-02-08 17:20:25 +0100 |
commit | 3cefc4ee12fe7144a65a205f6645c14ec5be68ce (patch) | |
tree | 37c160448e2accb5bbada6f6d4798a90741e4a12 /utils/jpgicc | |
download | lcms2-3cefc4ee12fe7144a65a205f6645c14ec5be68ce.tar.gz |
initial commit
Diffstat (limited to 'utils/jpgicc')
-rw-r--r-- | utils/jpgicc/Makefile.am | 22 | ||||
-rw-r--r-- | utils/jpgicc/Makefile.in | 583 | ||||
-rw-r--r-- | utils/jpgicc/iccjpeg.c | 248 | ||||
-rw-r--r-- | utils/jpgicc/iccjpeg.h | 73 | ||||
-rw-r--r-- | utils/jpgicc/jpgicc.1 | 79 | ||||
-rw-r--r-- | utils/jpgicc/jpgicc.c | 964 |
6 files changed, 1969 insertions, 0 deletions
diff --git a/utils/jpgicc/Makefile.am b/utils/jpgicc/Makefile.am new file mode 100644 index 0000000..59d5ab1 --- /dev/null +++ b/utils/jpgicc/Makefile.am @@ -0,0 +1,22 @@ +# +# Makefile for building jpegicc +# Written by Bob Friesenhahn, June 2003 +# Bugs introduced by Marti Maria on October 2004 + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7 foreign + +AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/utils/common -I$(top_builddir)/utils/common +if HasJPEG +bin_PROGRAMS = jpgicc +else +bin_PROGRAMS = +endif + +jpgicc_LDADD = $(top_builddir)/src/liblcms2.la @JPEGICC_DEPLIBS@ +jpgicc_LDFLAGS = @LDFLAGS@ +jpgicc_SOURCES = jpgicc.c iccjpeg.c ../common/xgetopt.c ../common/vprf.c ../common/utils.h +man_MANS = jpgicc.1 + +EXTRA_DIST = iccjpeg.h $(man_MANS) diff --git a/utils/jpgicc/Makefile.in b/utils/jpgicc/Makefile.in new file mode 100644 index 0000000..4c244b0 --- /dev/null +++ b/utils/jpgicc/Makefile.in @@ -0,0 +1,583 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Makefile for building jpegicc +# Written by Bob Friesenhahn, June 2003 +# Bugs introduced by Marti Maria on October 2004 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +LIBOBJDIR = +@HasJPEG_TRUE@bin_PROGRAMS = jpgicc$(EXEEXT) +subdir = utils/jpgicc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_jpgicc_OBJECTS = jpgicc.$(OBJEXT) iccjpeg.$(OBJEXT) \ + xgetopt.$(OBJEXT) vprf.$(OBJEXT) +jpgicc_OBJECTS = $(am_jpgicc_OBJECTS) +jpgicc_DEPENDENCIES = $(top_builddir)/src/liblcms2.la +DEFAULT_INCLUDES = -I. -I$(srcdir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(jpgicc_SOURCES) +DIST_SOURCES = $(jpgicc_SOURCES) +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HasJPEG_FALSE = @HasJPEG_FALSE@ +HasJPEG_TRUE = @HasJPEG_TRUE@ +HasTIFF_FALSE = @HasTIFF_FALSE@ +HasTIFF_TRUE = @HasTIFF_TRUE@ +HasZLIB_FALSE = @HasZLIB_FALSE@ +HasZLIB_TRUE = @HasZLIB_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JPEGICC_DEPLIBS = @JPEGICC_DEPLIBS@ +LCMS_LIB_DEPLIBS = @LCMS_LIB_DEPLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBRARY_AGE = @LIBRARY_AGE@ +LIBRARY_CURRENT = @LIBRARY_CURRENT@ +LIBRARY_REVISION = @LIBRARY_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIB_JPEG = @LIB_JPEG@ +LIB_MATH = @LIB_MATH@ +LIB_TIFF = @LIB_TIFF@ +LIB_ZLIB = @LIB_ZLIB@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TIFFICC_DEPLIBS = @TIFFICC_DEPLIBS@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +inline = @inline@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +to_host_path_cmd = @to_host_path_cmd@ + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7 foreign +AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/utils/common -I$(top_builddir)/utils/common + +jpgicc_LDADD = $(top_builddir)/src/liblcms2.la @JPEGICC_DEPLIBS@ +jpgicc_LDFLAGS = @LDFLAGS@ +jpgicc_SOURCES = jpgicc.c iccjpeg.c ../common/xgetopt.c ../common/vprf.c ../common/utils.h +man_MANS = jpgicc.1 +EXTRA_DIST = iccjpeg.h $(man_MANS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign utils/jpgicc/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign utils/jpgicc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +jpgicc$(EXEEXT): $(jpgicc_OBJECTS) $(jpgicc_DEPENDENCIES) + @rm -f jpgicc$(EXEEXT) + $(LINK) $(jpgicc_LDFLAGS) $(jpgicc_OBJECTS) $(jpgicc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iccjpeg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jpgicc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vprf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetopt.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +xgetopt.o: ../common/xgetopt.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xgetopt.o -MD -MP -MF "$(DEPDIR)/xgetopt.Tpo" -c -o xgetopt.o `test -f '../common/xgetopt.c' || echo '$(srcdir)/'`../common/xgetopt.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/xgetopt.Tpo" "$(DEPDIR)/xgetopt.Po"; else rm -f "$(DEPDIR)/xgetopt.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../common/xgetopt.c' object='xgetopt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgetopt.o `test -f '../common/xgetopt.c' || echo '$(srcdir)/'`../common/xgetopt.c + +xgetopt.obj: ../common/xgetopt.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xgetopt.obj -MD -MP -MF "$(DEPDIR)/xgetopt.Tpo" -c -o xgetopt.obj `if test -f '../common/xgetopt.c'; then $(CYGPATH_W) '../common/xgetopt.c'; else $(CYGPATH_W) '$(srcdir)/../common/xgetopt.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/xgetopt.Tpo" "$(DEPDIR)/xgetopt.Po"; else rm -f "$(DEPDIR)/xgetopt.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../common/xgetopt.c' object='xgetopt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgetopt.obj `if test -f '../common/xgetopt.c'; then $(CYGPATH_W) '../common/xgetopt.c'; else $(CYGPATH_W) '$(srcdir)/../common/xgetopt.c'; fi` + +vprf.o: ../common/vprf.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vprf.o -MD -MP -MF "$(DEPDIR)/vprf.Tpo" -c -o vprf.o `test -f '../common/vprf.c' || echo '$(srcdir)/'`../common/vprf.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/vprf.Tpo" "$(DEPDIR)/vprf.Po"; else rm -f "$(DEPDIR)/vprf.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../common/vprf.c' object='vprf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vprf.o `test -f '../common/vprf.c' || echo '$(srcdir)/'`../common/vprf.c + +vprf.obj: ../common/vprf.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vprf.obj -MD -MP -MF "$(DEPDIR)/vprf.Tpo" -c -o vprf.obj `if test -f '../common/vprf.c'; then $(CYGPATH_W) '../common/vprf.c'; else $(CYGPATH_W) '$(srcdir)/../common/vprf.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/vprf.Tpo" "$(DEPDIR)/vprf.Po"; else rm -f "$(DEPDIR)/vprf.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../common/vprf.c' object='vprf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vprf.obj `if test -f '../common/vprf.c'; then $(CYGPATH_W) '../common/vprf.c'; else $(CYGPATH_W) '$(srcdir)/../common/vprf.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: install-man1 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-man1 install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-info-am \ + uninstall-man uninstall-man1 + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/utils/jpgicc/iccjpeg.c b/utils/jpgicc/iccjpeg.c new file mode 100644 index 0000000..aa96c8b --- /dev/null +++ b/utils/jpgicc/iccjpeg.c @@ -0,0 +1,248 @@ +/* + * iccprofile.c + * + * This file provides code to read and write International Color Consortium + * (ICC) device profiles embedded in JFIF JPEG image files. The ICC has + * defined a standard format for including such data in JPEG "APP2" markers. + * The code given here does not know anything about the internal structure + * of the ICC profile data; it just knows how to put the profile data into + * a JPEG file being written, or get it back out when reading. + * + * This code depends on new features added to the IJG JPEG library as of + * IJG release 6b; it will not compile or work with older IJG versions. + * + * NOTE: this code would need surgery to work on 16-bit-int machines + * with ICC profiles exceeding 64K bytes in size. If you need to do that, + * change all the "unsigned int" variables to "INT32". You'll also need + * to find a malloc() replacement that can allocate more than 64K. + */ + +#include "iccjpeg.h" +#include <stdlib.h> /* define malloc() */ + + +/* + * Since an ICC profile can be larger than the maximum size of a JPEG marker + * (64K), we need provisions to split it into multiple markers. The format + * defined by the ICC specifies one or more APP2 markers containing the + * following data: + * Identifying string ASCII "ICC_PROFILE\0" (12 bytes) + * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte) + * Number of markers Total number of APP2's used (1 byte) + * Profile data (remainder of APP2 data) + * Decoders should use the marker sequence numbers to reassemble the profile, + * rather than assuming that the APP2 markers appear in the correct sequence. + */ + +#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ +#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ +#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */ +#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN) + + +/* + * This routine writes the given ICC profile data into a JPEG file. + * It *must* be called AFTER calling jpeg_start_compress() and BEFORE + * the first call to jpeg_write_scanlines(). + * (This ordering ensures that the APP2 marker(s) will appear after the + * SOI and JFIF or Adobe markers, but before all else.) + */ + +void +write_icc_profile (j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len) +{ + unsigned int num_markers; /* total number of markers we'll write */ + int cur_marker = 1; /* per spec, counting starts at 1 */ + unsigned int length; /* number of bytes to write in this marker */ + + /* Calculate the number of markers we'll need, rounding up of course */ + num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER; + if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len) + num_markers++; + + while (icc_data_len > 0) { + /* length of profile to put in this marker */ + length = icc_data_len; + if (length > MAX_DATA_BYTES_IN_MARKER) + length = MAX_DATA_BYTES_IN_MARKER; + icc_data_len -= length; + + /* Write the JPEG marker header (APP2 code and marker length) */ + jpeg_write_m_header(cinfo, ICC_MARKER, + (unsigned int) (length + ICC_OVERHEAD_LEN)); + + /* Write the marker identifying string "ICC_PROFILE" (null-terminated). + * We code it in this less-than-transparent way so that the code works + * even if the local character set is not ASCII. + */ + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x43); + jpeg_write_m_byte(cinfo, 0x5F); + jpeg_write_m_byte(cinfo, 0x50); + jpeg_write_m_byte(cinfo, 0x52); + jpeg_write_m_byte(cinfo, 0x4F); + jpeg_write_m_byte(cinfo, 0x46); + jpeg_write_m_byte(cinfo, 0x49); + jpeg_write_m_byte(cinfo, 0x4C); + jpeg_write_m_byte(cinfo, 0x45); + jpeg_write_m_byte(cinfo, 0x0); + + /* Add the sequencing info */ + jpeg_write_m_byte(cinfo, cur_marker); + jpeg_write_m_byte(cinfo, (int) num_markers); + + /* Add the profile data */ + while (length--) { + jpeg_write_m_byte(cinfo, *icc_data_ptr); + icc_data_ptr++; + } + cur_marker++; + } +} + + +/* + * Prepare for reading an ICC profile + */ + +void +setup_read_icc_profile (j_decompress_ptr cinfo) +{ + /* Tell the library to keep any APP2 data it may find */ + jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF); +} + + +/* + * Handy subroutine to test whether a saved marker is an ICC profile marker. + */ + +static boolean +marker_is_icc (jpeg_saved_marker_ptr marker) +{ + return + marker->marker == ICC_MARKER && + marker->data_length >= ICC_OVERHEAD_LEN && + /* verify the identifying string */ + GETJOCTET(marker->data[0]) == 0x49 && + GETJOCTET(marker->data[1]) == 0x43 && + GETJOCTET(marker->data[2]) == 0x43 && + GETJOCTET(marker->data[3]) == 0x5F && + GETJOCTET(marker->data[4]) == 0x50 && + GETJOCTET(marker->data[5]) == 0x52 && + GETJOCTET(marker->data[6]) == 0x4F && + GETJOCTET(marker->data[7]) == 0x46 && + GETJOCTET(marker->data[8]) == 0x49 && + GETJOCTET(marker->data[9]) == 0x4C && + GETJOCTET(marker->data[10]) == 0x45 && + GETJOCTET(marker->data[11]) == 0x0; +} + + +/* + * See if there was an ICC profile in the JPEG file being read; + * if so, reassemble and return the profile data. + * + * TRUE is returned if an ICC profile was found, FALSE if not. + * If TRUE is returned, *icc_data_ptr is set to point to the + * returned data, and *icc_data_len is set to its length. + * + * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc() + * and must be freed by the caller with free() when the caller no longer + * needs it. (Alternatively, we could write this routine to use the + * IJG library's memory allocator, so that the data would be freed implicitly + * at jpeg_finish_decompress() time. But it seems likely that many apps + * will prefer to have the data stick around after decompression finishes.) + * + * NOTE: if the file contains invalid ICC APP2 markers, we just silently + * return FALSE. You might want to issue an error message instead. + */ + +boolean +read_icc_profile (j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len) +{ + jpeg_saved_marker_ptr marker; + int num_markers = 0; + int seq_no; + JOCTET *icc_data; + unsigned int total_length; +#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */ + char marker_present[MAX_SEQ_NO+1]; /* 1 if marker found */ + unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */ + unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */ + + *icc_data_ptr = NULL; /* avoid confusion if FALSE return */ + *icc_data_len = 0; + + /* This first pass over the saved markers discovers whether there are + * any ICC markers and verifies the consistency of the marker numbering. + */ + + for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++) + marker_present[seq_no] = 0; + + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + if (num_markers == 0) + num_markers = GETJOCTET(marker->data[13]); + else if (num_markers != GETJOCTET(marker->data[13])) + return FALSE; /* inconsistent num_markers fields */ + seq_no = GETJOCTET(marker->data[12]); + if (seq_no <= 0 || seq_no > num_markers) + return FALSE; /* bogus sequence number */ + if (marker_present[seq_no]) + return FALSE; /* duplicate sequence numbers */ + marker_present[seq_no] = 1; + data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN; + } + } + + if (num_markers == 0) + return FALSE; + + /* Check for missing markers, count total space needed, + * compute offset of each marker's part of the data. + */ + + total_length = 0; + for (seq_no = 1; seq_no <= num_markers; seq_no++) { + if (marker_present[seq_no] == 0) + return FALSE; /* missing sequence number */ + data_offset[seq_no] = total_length; + total_length += data_length[seq_no]; + } + + if (total_length <= 0) + return FALSE; /* found only empty markers? */ + + /* Allocate space for assembled data */ + icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET)); + if (icc_data == NULL) + return FALSE; /* oops, out of memory */ + + /* and fill it in */ + for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker_is_icc(marker)) { + JOCTET FAR *src_ptr; + JOCTET *dst_ptr; + unsigned int length; + seq_no = GETJOCTET(marker->data[12]); + dst_ptr = icc_data + data_offset[seq_no]; + src_ptr = marker->data + ICC_OVERHEAD_LEN; + length = data_length[seq_no]; + while (length--) { + *dst_ptr++ = *src_ptr++; + } + } + } + + *icc_data_ptr = icc_data; + *icc_data_len = total_length; + + return TRUE; +} diff --git a/utils/jpgicc/iccjpeg.h b/utils/jpgicc/iccjpeg.h new file mode 100644 index 0000000..5e1888d --- /dev/null +++ b/utils/jpgicc/iccjpeg.h @@ -0,0 +1,73 @@ +/* + * iccprofile.h + * + * This file provides code to read and write International Color Consortium + * (ICC) device profiles embedded in JFIF JPEG image files. The ICC has + * defined a standard format for including such data in JPEG "APP2" markers. + * The code given here does not know anything about the internal structure + * of the ICC profile data; it just knows how to put the profile data into + * a JPEG file being written, or get it back out when reading. + * + * This code depends on new features added to the IJG JPEG library as of + * IJG release 6b; it will not compile or work with older IJG versions. + * + * NOTE: this code would need surgery to work on 16-bit-int machines + * with ICC profiles exceeding 64K bytes in size. See iccprofile.c + * for details. + */ + +#include <stdio.h> /* needed to define "FILE", "NULL" */ +#include "jpeglib.h" + + +/* + * This routine writes the given ICC profile data into a JPEG file. + * It *must* be called AFTER calling jpeg_start_compress() and BEFORE + * the first call to jpeg_write_scanlines(). + * (This ordering ensures that the APP2 marker(s) will appear after the + * SOI and JFIF or Adobe markers, but before all else.) + */ + +extern void write_icc_profile JPP((j_compress_ptr cinfo, + const JOCTET *icc_data_ptr, + unsigned int icc_data_len)); + + +/* + * Reading a JPEG file that may contain an ICC profile requires two steps: + * + * 1. After jpeg_create_decompress() but before jpeg_read_header(), + * call setup_read_icc_profile(). This routine tells the IJG library + * to save in memory any APP2 markers it may find in the file. + * + * 2. After jpeg_read_header(), call read_icc_profile() to find out + * whether there was a profile and obtain it if so. + */ + + +/* + * Prepare for reading an ICC profile + */ + +extern void setup_read_icc_profile JPP((j_decompress_ptr cinfo)); + + +/* + * See if there was an ICC profile in the JPEG file being read; + * if so, reassemble and return the profile data. + * + * TRUE is returned if an ICC profile was found, FALSE if not. + * If TRUE is returned, *icc_data_ptr is set to point to the + * returned data, and *icc_data_len is set to its length. + * + * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc() + * and must be freed by the caller with free() when the caller no longer + * needs it. (Alternatively, we could write this routine to use the + * IJG library's memory allocator, so that the data would be freed implicitly + * at jpeg_finish_decompress() time. But it seems likely that many apps + * will prefer to have the data stick around after decompression finishes.) + */ + +extern boolean read_icc_profile JPP((j_decompress_ptr cinfo, + JOCTET **icc_data_ptr, + unsigned int *icc_data_len)); diff --git a/utils/jpgicc/jpgicc.1 b/utils/jpgicc/jpgicc.1 new file mode 100644 index 0000000..19a3669 --- /dev/null +++ b/utils/jpgicc/jpgicc.1 @@ -0,0 +1,79 @@ +.\"Shiju P. Nair September 30, 2004 +.TH JPEGICC 1 "September 30, 2004" +.SH NAME +jpegicc - little cms ICC profile applier for JPEG. +.SH SYNOPSIS +.B jpegicc +.RI [ options ] " input.jpg output.jpg" +.SH DESCRIPTION +lcms is a standalone CMM engine, which deals with the color management. +It implements a fast transformation between ICC profiles. +.B jpegicc +is little cms ICC profile applier for JPEG. +.SH OPTIONS +.TP +.B \-b +Black point compensation. +.TP +.B \-c <0,1,2,3> +Precalculates transform. (0=Off, 1=Normal, 2=Hi-res, 3=LoRes) [defaults to 1] +.TP +.B \-g +Marks out-of-gamut colors on softproof. +.TP +.B \-h <0,1,2> +Show summary of options and examples. +.TP +.BI \-i\ profile +Input profile (defaults to sRGB). +.TP +.B \-m <0,1,2,3> +SoftProof intent. +.TP +.B \-n +Ignore embedded profile. +.TP +.BI \-p\ profile +Soft proof profile +.TP +.BI \-o\ profile +.p +Output profile (defaults to sRGB). +.TP +.B \-q <0..100> +Output JPEG quality. +.TP +.B \-t <0,1,2,3> +Intent (0=Perceptual, 1=Colorimetric, 2=Saturation, 3=Absolute). +.TP +.B \-v +Verbose. +.SH EXAMPLES +.nf +To color correct from scanner to sRGB: + jpegicc -iscanner.icm in.jpg out.jpg + +To convert from monitor1 to monitor2: + jpegicc -imon1.icm -omon2.icm in.jpg out.jpg + +To make a CMYK separation: + jpegicc -oprinter.icm inrgb.jpg outcmyk.jpg + +To recover sRGB from a CMYK separation: + jpegicc -iprinter.icm incmyk.jpg outrgb.jpg + +To convert from CIELab ITU/Fax JPEG to sRGB + jpegicc -iitufax.icm in.jpg out.jpg +.fi +.SH NOTES +For suggestions, comments, bug reports etc. send mail to +info@littlecms.com. +.SH SEE ALSO +.BR tifficc (1), +.BR icc2ps (1), +.BR icclink (1), +.BR icctrans (1), +.BR wtpt (1) +.SH AUTHOR +This manual page was written by Shiju p. Nair <shiju.p@gmail.com>, +for the Debian project. diff --git a/utils/jpgicc/jpgicc.c b/utils/jpgicc/jpgicc.c new file mode 100644 index 0000000..12a30f6 --- /dev/null +++ b/utils/jpgicc/jpgicc.c @@ -0,0 +1,964 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2010 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +// This program does apply profiles to (some) JPEG files + + +#include "utils.h" + +#include "jpeglib.h" +#include "iccjpeg.h" + +// Flags +static cmsBool BlackPointCompensation = FALSE; +static cmsBool IgnoreEmbedded = FALSE; +static cmsBool GamutCheck = FALSE; +static cmsBool lIsITUFax = FALSE; +static cmsBool lIsPhotoshopApp13 = FALSE; +static cmsBool lIsDeviceLink = FALSE; +static cmsBool EmbedProfile = FALSE; + +static const char* SaveEmbedded = NULL; + +static int Intent = INTENT_PERCEPTUAL; +static int ProofingIntent = INTENT_PERCEPTUAL; +static int PrecalcMode = 1; + +static int jpegQuality = 75; + +static char *cInpProf = NULL; +static char *cOutProf = NULL; +static char *cProofing = NULL; + +static FILE * InFile; +static FILE * OutFile; + +static struct jpeg_decompress_struct Decompressor; +static struct jpeg_compress_struct Compressor; + + +static struct my_error_mgr { + + struct jpeg_error_mgr pub; // "public" fields + void* Cargo; // "private" fields + +} ErrorHandler; + + + +// Out of mem +static +void OutOfMem(size_t size) +{ + FatalError("Out of memory on allocating %d bytes.", size); +} + + +static +void my_error_exit (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + FatalError(buffer); +} + + +static +cmsBool IsITUFax(jpeg_saved_marker_ptr ptr) +{ + while (ptr) + { + if (ptr -> marker == (JPEG_APP0 + 1) && ptr -> data_length > 5) + { + const char* data = (const char*) ptr -> data; + + if (strcmp(data, "G3FAX") == 0) return TRUE; + } + + ptr = ptr -> next; + } + + return FALSE; +} + +static +void SetITUFax(j_compress_ptr cinfo) +{ + unsigned char Marker[] = "G3FAX\x00\0x07\xCA\x00\xC8"; + + jpeg_write_marker(cinfo, (JPEG_APP0 + 1), Marker, 10); +} + + +// Build a profile for decoding ITU T.42/Fax JPEG streams. +// The profile has an additional ability in the input direction of +// gamut compress values between 85 < a < -85 and -75 < b < 125. This conforms +// the default range for ITU/T.42 -- See RFC 2301, section 6.2.3 for details + +// L* = [0, 100] +// a* = [–85, 85] +// b* = [–75, 125] + + +// These functions does convert the encoding of ITUFAX to floating point +// and vice-versa. No gamut mapping is performed yet. + +static +void ITU2Lab(const cmsUInt16Number In[3], cmsCIELab* Lab) +{ + Lab -> L = (double) In[0] / 655.35; + Lab -> a = (double) 170.* (In[1] - 32768.) / 65535.; + Lab -> b = (double) 200.* (In[2] - 24576.) / 65535.; +} + +static +void Lab2ITU(const cmsCIELab* Lab, cmsUInt16Number Out[3]) +{ + Out[0] = (cmsUInt16Number) floor((double) (Lab -> L / 100.)* 65535. ); + Out[1] = (cmsUInt16Number) floor((double) (Lab -> a / 170.)* 65535. + 32768. ); + Out[2] = (cmsUInt16Number) floor((double) (Lab -> b / 200.)* 65535. + 24576. ); +} + +// These are the samplers-- They are passed as callbacks to cmsSample3DGrid() +// then, cmsSample3DGrid() will sweel whole Lab gamut calling these functions +// once for each node. In[] will contain the Lab PCS value to convert to ITUFAX +// on PCS2ITU, or the ITUFAX value to convert to Lab in ITU2PCS +// You can change the number of sample points if desired, the algorithm will +// remain same. 33 points gives good accurancy, but you can reduce to 22 or less +// is space is critical + +#define GRID_POINTS 33 + +static +int PCS2ITU(register cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsCIELab Lab; + + cmsLabEncoded2Float(&Lab, In); + cmsDesaturateLab(&Lab, 85, -85, 125, -75); // This function does the necessary gamut remapping + Lab2ITU(&Lab, Out); + return TRUE; +} + + +static +int ITU2PCS(const register cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsCIELab Lab; + + ITU2Lab(In, &Lab); + cmsFloat2LabEncoded(Out, &Lab); + return TRUE; +} + +// This function does create the virtual input profile, which decoded ITU +// to the profile connection space +static +cmsHPROFILE CreateITU2PCS_ICC(void) +{ + cmsHPROFILE hProfile; + cmsPipeline* AToB0; + cmsStage* ColorMap; + + AToB0 = cmsPipelineAlloc(0, 3, 3); + if (AToB0 == NULL) return NULL; + + ColorMap = cmsStageAllocCLut16bit(0, GRID_POINTS, 3, 3, NULL); + if (ColorMap == NULL) return NULL; + + cmsPipelineInsertStage(AToB0, cmsAT_BEGIN, ColorMap); + cmsStageSampleCLut16bit(ColorMap, ITU2PCS, NULL, 0); + + hProfile = cmsCreateProfilePlaceholder(0); + if (hProfile == NULL) { + cmsPipelineFree(AToB0); + return NULL; + } + + cmsWriteTag(hProfile, cmsSigAToB0Tag, AToB0); + cmsSetColorSpace(hProfile, cmsSigLabData); + cmsSetPCS(hProfile, cmsSigLabData); + cmsSetDeviceClass(hProfile, cmsSigColorSpaceClass); + cmsPipelineFree(AToB0); + + return hProfile; +} + + + +#define PS_FIXED_TO_FLOAT(h, l) ((float) (h) + ((float) (l)/(1<<16))) + +static +cmsBool ProcessPhotoshopAPP13(JOCTET FAR *data, int datalen) +{ + int i; + + for (i = 14; i < datalen; ) + { + long len; + unsigned int type; + + if (!(GETJOCTET(data[i] ) == 0x38 && + GETJOCTET(data[i+1]) == 0x42 && + GETJOCTET(data[i+2]) == 0x49 && + GETJOCTET(data[i+3]) == 0x4D)) break; // Not recognized + + i += 4; // identifying string + + type = (unsigned int) (GETJOCTET(data[i]<<8) + GETJOCTET(data[i+1])); + + i += 2; // resource type + + i += GETJOCTET(data[i]) + ((GETJOCTET(data[i]) & 1) ? 1 : 2); // resource name + + len = ((((GETJOCTET(data[i]<<8) + GETJOCTET(data[i+1]))<<8) + + GETJOCTET(data[i+2]))<<8) + GETJOCTET(data[i+3]); + + i += 4; // Size + + if (type == 0x03ED && len >= 16) { + + Decompressor.X_density = (int) PS_FIXED_TO_FLOAT(GETJOCTET(data[i]<<8) + GETJOCTET(data[i+1]), + GETJOCTET(data[i+2]<<8) + GETJOCTET(data[i+3])); + Decompressor.Y_density = (int) PS_FIXED_TO_FLOAT(GETJOCTET(data[i+8]<<8) + GETJOCTET(data[i+9]), + GETJOCTET(data[i+10]<<8) + GETJOCTET(data[i+11])); + + // Set the density unit to 1 since the + // Vertical and Horizontal resolutions + // are specified in Pixels per inch + + Decompressor.density_unit = 0x01; + return TRUE; + + } + + i += len + ((len & 1) ? 1 : 0); // Alignment + } + return FALSE; +} + + +static +cmsBool HandlePhotoshopAPP13(jpeg_saved_marker_ptr ptr) +{ + while (ptr) { + + if (ptr -> marker == (JPEG_APP0 + 13) && ptr -> data_length > 9) + { + JOCTET FAR* data = ptr -> data; + + if(GETJOCTET(data[0]) == 0x50 && + GETJOCTET(data[1]) == 0x68 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x74 && + GETJOCTET(data[4]) == 0x6F && + GETJOCTET(data[5]) == 0x73 && + GETJOCTET(data[6]) == 0x68 && + GETJOCTET(data[7]) == 0x6F && + GETJOCTET(data[8]) == 0x70) { + + ProcessPhotoshopAPP13(data, ptr -> data_length); + return TRUE; + } + } + + ptr = ptr -> next; + } + + return FALSE; +} + + + +static +cmsBool OpenInput(const char* FileName) +{ + int m; + + lIsITUFax = FALSE; + InFile = fopen(FileName, "rb"); + if (InFile == NULL) { + FatalError("Cannot open '%s'", FileName); + } + + // Now we can initialize the JPEG decompression object. + Decompressor.err = jpeg_std_error(&ErrorHandler.pub); + ErrorHandler.pub.error_exit = my_error_exit; + ErrorHandler.pub.output_message = my_error_exit; + + jpeg_create_decompress(&Decompressor); + jpeg_stdio_src(&Decompressor, InFile); + + for (m = 0; m < 16; m++) + jpeg_save_markers(&Decompressor, JPEG_APP0 + m, 0xFFFF); + + // setup_read_icc_profile(&Decompressor); + + fseek(InFile, 0, SEEK_SET); + jpeg_read_header(&Decompressor, TRUE); + + return TRUE; +} + + +static +cmsBool OpenOutput(const char* FileName) +{ + + OutFile = fopen(FileName, "wb"); + if (OutFile == NULL) { + FatalError("Cannot create '%s'", FileName); + + } + + Compressor.err = jpeg_std_error(&ErrorHandler.pub); + ErrorHandler.pub.error_exit = my_error_exit; + ErrorHandler.pub.output_message = my_error_exit; + + Compressor.input_components = Compressor.num_components = 4; + + jpeg_create_compress(&Compressor); + jpeg_stdio_dest(&Compressor, OutFile); + return TRUE; +} + +static +cmsBool Done() +{ + jpeg_destroy_decompress(&Decompressor); + jpeg_destroy_compress(&Compressor); + return fclose(InFile) + fclose(OutFile); + +} + + +// Build up the pixeltype descriptor + +static +cmsUInt32Number GetInputPixelType(void) +{ + int space, bps, extra, ColorChannels, Flavor; + + + lIsITUFax = IsITUFax(Decompressor.marker_list); + lIsPhotoshopApp13 = HandlePhotoshopAPP13(Decompressor.marker_list); + + ColorChannels = Decompressor.num_components; + extra = 0; // Alpha = None + bps = 1; // 8 bits + Flavor = 0; // Vanilla + + if (lIsITUFax) { + + space = PT_Lab; + Decompressor.out_color_space = JCS_YCbCr; // Fake to don't touch + } + else + switch (Decompressor.jpeg_color_space) { + + case JCS_GRAYSCALE: // monochrome + space = PT_GRAY; + Decompressor.out_color_space = JCS_GRAYSCALE; + break; + + case JCS_RGB: // red/green/blue + space = PT_RGB; + Decompressor.out_color_space = JCS_RGB; + break; + + case JCS_YCbCr: // Y/Cb/Cr (also known as YUV) + space = PT_RGB; // Let IJG code to do the conversion + Decompressor.out_color_space = JCS_RGB; + break; + + case JCS_CMYK: // C/M/Y/K + space = PT_CMYK; + Decompressor.out_color_space = JCS_CMYK; + if (Decompressor.saw_Adobe_marker) // Adobe keeps CMYK inverted, so change flavor + Flavor = 1; // from vanilla to chocolate + break; + + case JCS_YCCK: // Y/Cb/Cr/K + space = PT_CMYK; + Decompressor.out_color_space = JCS_CMYK; + if (Decompressor.saw_Adobe_marker) // ditto + Flavor = 1; + break; + + default: + FatalError("Unsupported color space (0x%x)", Decompressor.jpeg_color_space); + return 0; + } + + return (EXTRA_SH(extra)|CHANNELS_SH(ColorChannels)|BYTES_SH(bps)|COLORSPACE_SH(space)|FLAVOR_SH(Flavor)); +} + + +// Rearrange pixel type to build output descriptor +static +cmsUInt32Number ComputeOutputFormatDescriptor(cmsUInt32Number dwInput, int OutColorSpace) +{ + int IsPlanar = T_PLANAR(dwInput); + int Channels = 0; + int Flavor = 0; + + switch (OutColorSpace) { + + case PT_GRAY: + Channels = 1; + break; + case PT_RGB: + case PT_CMY: + case PT_Lab: + case PT_YUV: + case PT_YCbCr: + Channels = 3; + break; + + case PT_CMYK: + if (Compressor.write_Adobe_marker) // Adobe keeps CMYK inverted, so change flavor to chocolate + Flavor = 1; + + Channels = 4; + break; + default: + FatalError("Unsupported output color space"); + } + + return (COLORSPACE_SH(OutColorSpace)|PLANAR_SH(IsPlanar)|CHANNELS_SH(Channels)|BYTES_SH(1)|FLAVOR_SH(Flavor)); +} + + +// Equivalence between ICC color spaces and lcms color spaces +static +int GetProfileColorSpace(cmsHPROFILE hProfile) +{ + cmsColorSpaceSignature ProfileSpace = cmsGetColorSpace(hProfile); + + return _cmsLCMScolorSpace(ProfileSpace); +} + +// From TRANSUPP + +static +void jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo) +{ + jpeg_saved_marker_ptr marker; + + /* In the current implementation, we don't actually need to examine the + * option flag here; we just copy everything that got saved. + * But to avoid confusion, we do not output JFIF and Adobe APP14 markers + * if the encoder library already wrote one. + */ + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + + if (dstinfo->write_JFIF_header && + marker->marker == JPEG_APP0 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x4A && + GETJOCTET(marker->data[1]) == 0x46 && + GETJOCTET(marker->data[2]) == 0x49 && + GETJOCTET(marker->data[3]) == 0x46 && + GETJOCTET(marker->data[4]) == 0) + continue; /* reject duplicate JFIF */ + + if (dstinfo->write_Adobe_marker && + marker->marker == JPEG_APP0+14 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x41 && + GETJOCTET(marker->data[1]) == 0x64 && + GETJOCTET(marker->data[2]) == 0x6F && + GETJOCTET(marker->data[3]) == 0x62 && + GETJOCTET(marker->data[4]) == 0x65) + continue; /* reject duplicate Adobe */ + + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); + } +} + +static +void WriteOutputFields(int OutputColorSpace) +{ + J_COLOR_SPACE in_space, jpeg_space; + int components; + + switch (OutputColorSpace) { + + case PT_GRAY: in_space = jpeg_space = JCS_GRAYSCALE; + components = 1; + break; + + case PT_RGB: in_space = JCS_RGB; + jpeg_space = JCS_YCbCr; + components = 3; + break; // red/green/blue + + case PT_YCbCr: in_space = jpeg_space = JCS_YCbCr; + components = 3; + break; // Y/Cb/Cr (also known as YUV) + + case PT_CMYK: in_space = JCS_CMYK; + jpeg_space = JCS_YCCK; + components = 4; + break; // C/M/Y/components + + case PT_Lab: in_space = jpeg_space = JCS_YCbCr; + components = 3; + break; // Fake to don't touch + default: + FatalError("Unsupported output color space"); + return; + } + + + if (jpegQuality >= 100) { + + // avoid destructive conversion when asking for lossless compression + jpeg_space = in_space; + } + + Compressor.in_color_space = in_space; + Compressor.jpeg_color_space = jpeg_space; + Compressor.input_components = Compressor.num_components = components; + jpeg_set_defaults(&Compressor); + jpeg_set_colorspace(&Compressor, jpeg_space); + + // Make sure to pass resolution through + if (OutputColorSpace == PT_CMYK) + Compressor.write_JFIF_header = 1; + + // Avoid subsampling on high quality factor + jpeg_set_quality(&Compressor, jpegQuality, 1); + if (jpegQuality >= 70) { + + int i; + for(i=0; i < Compressor.num_components; i++) { + + Compressor.comp_info[i].h_samp_factor = 1; + Compressor.comp_info[i].v_samp_factor = 1; + } + + } + +} + + +static +void DoEmbedProfile(const char* ProfileFile) +{ + FILE* f; + size_t size, EmbedLen; + cmsUInt8Number* EmbedBuffer; + + f = fopen(ProfileFile, "rb"); + if (f == NULL) return; + + size = cmsfilelength(f); + EmbedBuffer = (cmsUInt8Number*) malloc(size + 1); + EmbedLen = fread(EmbedBuffer, 1, size, f); + fclose(f); + EmbedBuffer[EmbedLen] = 0; + + write_icc_profile (&Compressor, EmbedBuffer, EmbedLen); + free(EmbedBuffer); +} + + + +static +int DoTransform(cmsHTRANSFORM hXForm) +{ + JSAMPROW ScanLineIn; + JSAMPROW ScanLineOut; + + + //Preserve resolution values from the original + // (Thanks to Robert Bergs for finding out this bug) + Compressor.density_unit = Decompressor.density_unit; + Compressor.X_density = Decompressor.X_density; + Compressor.Y_density = Decompressor.Y_density; + + // Compressor.write_JFIF_header = 1; + + jpeg_start_decompress(&Decompressor); + jpeg_start_compress(&Compressor, TRUE); + + // Embed the profile if needed + if (EmbedProfile && cOutProf) + DoEmbedProfile(cOutProf); + + ScanLineIn = (JSAMPROW) malloc(Decompressor.output_width * Decompressor.num_components); + ScanLineOut = (JSAMPROW) malloc(Compressor.image_width * Compressor.num_components); + + while (Decompressor.output_scanline < + Decompressor.output_height) { + + jpeg_read_scanlines(&Decompressor, &ScanLineIn, 1); + + cmsDoTransform(hXForm, ScanLineIn, ScanLineOut, Decompressor.output_width); + + jpeg_write_scanlines(&Compressor, &ScanLineOut, 1); + } + + free(ScanLineIn); + free(ScanLineOut); + + jpeg_finish_decompress(&Decompressor); + jpeg_finish_compress(&Compressor); + + return TRUE; +} + + + +// Transform one image + +static +int TransformImage(char *cDefInpProf, char *cOutProf) +{ + cmsHPROFILE hIn, hOut, hProof; + cmsHTRANSFORM xform; + cmsUInt32Number wInput, wOutput; + int OutputColorSpace; + cmsUInt32Number dwFlags = 0; + cmsUInt32Number EmbedLen; + cmsUInt8Number* EmbedBuffer; + + + if (BlackPointCompensation) { + + dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; + } + + + switch (PrecalcMode) { + + case 0: dwFlags |= cmsFLAGS_NOOPTIMIZE; break; + case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; + case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; + default:; + } + + + if (GamutCheck) + dwFlags |= cmsFLAGS_GAMUTCHECK; + + + if (lIsDeviceLink) { + + hIn = cmsOpenProfileFromFile(cDefInpProf, "r"); + hOut = NULL; + hProof = NULL; + } + else { + + if (!IgnoreEmbedded && read_icc_profile(&Decompressor, &EmbedBuffer, &EmbedLen)) + { + hIn = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen); + + if (Verbose) { + + fprintf(stdout, " (Embedded profile found)\n"); + PrintProfileInformation(hIn); + fflush(stdout); + } + + if (hIn != NULL && SaveEmbedded != NULL) + SaveMemoryBlock(EmbedBuffer, EmbedLen, SaveEmbedded); + + free(EmbedBuffer); + } + else + { + hIn = OpenStockProfile(0, cDefInpProf); + } + + hOut = OpenStockProfile(0, cOutProf); + + + hProof = NULL; + if (cProofing != NULL) { + + hProof = OpenStockProfile(0, cProofing); + dwFlags |= cmsFLAGS_SOFTPROOFING; + } + } + + // Take input color space + wInput = GetInputPixelType(); + + // Assure both, input profile and input JPEG are on same colorspace + if (cmsGetColorSpace(hIn) != _cmsICCcolorSpace(T_COLORSPACE(wInput))) + FatalError("Input profile is not operating in proper color space"); + + + // Output colorspace is given by output profile + + if (lIsDeviceLink) { + OutputColorSpace = T_COLORSPACE(wInput); + } + else { + OutputColorSpace = GetProfileColorSpace(hOut); + } + + jpeg_copy_critical_parameters(&Decompressor, &Compressor); + + WriteOutputFields(OutputColorSpace); + + wOutput = ComputeOutputFormatDescriptor(wInput, OutputColorSpace); + + xform = cmsCreateProofingTransform(hIn, wInput, + hOut, wOutput, + hProof, Intent, + ProofingIntent, dwFlags); + + DoTransform(xform); + + + jcopy_markers_execute(&Decompressor, &Compressor); + + cmsDeleteTransform(xform); + cmsCloseProfile(hIn); + cmsCloseProfile(hOut); + if (hProof) cmsCloseProfile(hProof); + + return 1; +} + + +// Simply print help + +static +void Help(int level) +{ + fprintf(stderr, "little cms ICC profile applier for JPEG - v3.0 [LittleCMS %2.2f]\n\n", LCMS_VERSION / 1000.0); + + switch(level) { + + default: + case 0: + + fprintf(stderr, "usage: jpegicc [flags] input.jpg output.jpg\n"); + + fprintf(stderr, "\nflags:\n\n"); + fprintf(stderr, "%cv - Verbose\n", SW); + fprintf(stderr, "%ci<profile> - Input profile (defaults to sRGB)\n", SW); + fprintf(stderr, "%co<profile> - Output profile (defaults to sRGB)\n", SW); + + PrintRenderingIntents(); + + + fprintf(stderr, "%cb - Black point compensation\n", SW); + fprintf(stderr, "%cn - Ignore embedded profile\n", SW); + fprintf(stderr, "%ce - Embed destination profile\n", SW); + fprintf(stderr, "%cs<new profile> - Save embedded profile as <new profile>\n", SW); + + fprintf(stderr, "\n"); + + fprintf(stderr, "%cc<0,1,2,3> - Precalculates transform (0=Off, 1=Normal, 2=Hi-res, 3=LoRes) [defaults to 1]\n", SW); + fprintf(stderr, "\n"); + + fprintf(stderr, "%cp<profile> - Soft proof profile\n", SW); + fprintf(stderr, "%cm<0,1,2,3> - SoftProof intent\n", SW); + fprintf(stderr, "%cg - Marks out-of-gamut colors on softproof\n", SW); + + fprintf(stderr, "\n"); + fprintf(stderr, "%cq<0..100> - Output JPEG quality\n", SW); + + fprintf(stderr, "\n"); + fprintf(stderr, "%ch<0,1,2> - More help\n", SW); + break; + + case 1: + + + fprintf(stderr, "Examples:\n\n" + "To color correct from scanner to sRGB:\n" + "\tjpegicc %ciscanner.icm in.jpg out.jpg\n" + "To convert from monitor1 to monitor2:\n" + "\tjpegicc %cimon1.icm %comon2.icm in.jpg out.jpg\n" + "To make a CMYK separation:\n" + "\tjpegicc %coprinter.icm inrgb.jpg outcmyk.jpg\n" + "To recover sRGB from a CMYK separation:\n" + "\tjpegicc %ciprinter.icm incmyk.jpg outrgb.jpg\n" + "To convert from CIELab ITU/Fax JPEG to sRGB\n" + "\tjpegicc %ciitufax.icm in.jpg out.jpg\n\n", + SW, SW, SW, SW, SW, SW); + break; + + case 2: + + fprintf(stderr, "This program is intended to be a demo of the little cms\n" + "engine. Both lcms and this program are freeware. You can\n" + "obtain both in source code at http://www.littlecms.com\n" + "For suggestions, comments, bug reports etc. send mail to\n" + "marti@littlecms.com\n\n"); + break; + } + + exit(0); +} + + +// The toggles stuff + +static +void HandleSwitches(int argc, char *argv[]) +{ + int s; + + while ((s=xgetopt(argc,argv,"bBnNvVGgh:H:i:I:o:O:P:p:t:T:c:C:Q:q:M:m:L:l:eEs:S:")) != EOF) { + + switch (s) + { + + case 'b': + case 'B': + BlackPointCompensation = TRUE; + break; + + case 'v': + case 'V': + Verbose = TRUE; + break; + + case 'i': + case 'I': + if (lIsDeviceLink) + FatalError("Device-link already specified"); + + cInpProf = xoptarg; + break; + + case 'o': + case 'O': + if (lIsDeviceLink) + FatalError("Device-link already specified"); + + cOutProf = xoptarg; + break; + + case 'l': + case 'L': + if (cInpProf != NULL || cOutProf != NULL) + FatalError("input/output profiles already specified"); + + cInpProf = xoptarg; + lIsDeviceLink = TRUE; + break; + + case 'p': + case 'P': + cProofing = xoptarg; + break; + + case 't': + case 'T': + Intent = atoi(xoptarg); + break; + + case 'N': + case 'n': + IgnoreEmbedded = TRUE; + break; + + case 'e': + case 'E': + EmbedProfile = TRUE; + break; + + + case 'g': + case 'G': + GamutCheck = TRUE; + break; + + case 'c': + case 'C': + PrecalcMode = atoi(xoptarg); + if (PrecalcMode < 0 || PrecalcMode > 2) + FatalError("Unknown precalc mode '%d'", PrecalcMode); + break; + + case 'H': + case 'h': { + + int a = atoi(xoptarg); + Help(a); + } + break; + + case 'q': + case 'Q': + jpegQuality = atoi(xoptarg); + if (jpegQuality > 100) jpegQuality = 100; + if (jpegQuality < 0) jpegQuality = 0; + break; + + case 'm': + case 'M': + ProofingIntent = atoi(xoptarg); + break; + + case 's': + case 'S': SaveEmbedded = xoptarg; + break; + + + default: + + FatalError("Unknown option - run without args to see valid ones"); + } + + } +} + + +int main(int argc, char* argv[]) +{ + InitUtils("jpegicc"); + + HandleSwitches(argc, argv); + + if ((argc - xoptind) != 2) { + + Help(0); + } + + OpenInput(argv[xoptind]); + OpenOutput(argv[xoptind+1]); + TransformImage(cInpProf, cOutProf); + + + if (Verbose) { fprintf(stdout, "\n"); fflush(stdout); } + + Done(); + + return 0; +} + + + |