kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'icc-profiles'
commit
b219bc2c73
|
@ -16,7 +16,7 @@ endif
|
|||
|
||||
AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
|
||||
scanimage_SOURCES = scanimage.c stiff.c stiff.h
|
||||
scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
|
||||
scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
|
||||
$(PNG_LIBS) $(JPEG_LIBS)
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ AM_V_lt = $(am__v_lt_@AM_V@)
|
|||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
am_scanimage_OBJECTS = scanimage.$(OBJEXT) stiff.$(OBJEXT)
|
||||
am_scanimage_OBJECTS = scanimage.$(OBJEXT) sicc.$(OBJEXT) stiff.$(OBJEXT)
|
||||
scanimage_OBJECTS = $(am_scanimage_OBJECTS)
|
||||
scanimage_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \
|
||||
../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
|
@ -381,7 +381,7 @@ target_alias = @target_alias@
|
|||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
scanimage_SOURCES = scanimage.c stiff.c stiff.h
|
||||
scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
|
||||
scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
|
||||
$(PNG_LIBS) $(JPEG_LIBS)
|
||||
|
||||
|
@ -550,6 +550,7 @@ distclean-compile:
|
|||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saned.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanimage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sicc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stiff.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tstbackend.Po@am__quote@
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "../include/sane/sanei.h"
|
||||
#include "../include/sane/saneopts.h"
|
||||
|
||||
#include "sicc.h"
|
||||
#include "stiff.h"
|
||||
|
||||
#include "../include/md5.h"
|
||||
|
@ -1165,12 +1166,14 @@ write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp
|
|||
|
||||
#ifdef HAVE_LIBPNG
|
||||
static void
|
||||
write_png_header (SANE_Frame format, int width, int height, int depth, int dpi, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
|
||||
write_png_header (SANE_Frame format, int width, int height, int depth, int dpi, const char * icc_profile, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
|
||||
{
|
||||
int color_type;
|
||||
/* PNG does not have imperial reference units, so we must convert to metric. */
|
||||
/* There are nominally 39.3700787401575 inches in a meter. */
|
||||
const double pixels_per_meter = dpi * 39.3700787401575;
|
||||
size_t icc_size = 0;
|
||||
void *icc_buffer;
|
||||
|
||||
*png_ptr = png_create_write_struct
|
||||
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
@ -1207,6 +1210,36 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,
|
|||
pixels_per_meter, pixels_per_meter,
|
||||
PNG_RESOLUTION_METER);
|
||||
|
||||
if (icc_profile)
|
||||
{
|
||||
icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
|
||||
if (icc_size > 0)
|
||||
{
|
||||
/* libpng will abort if the profile and image colour spaces do not match*/
|
||||
/* The data colour space field is at bytes 16 to 20 in an ICC profile */
|
||||
/* see: ICC.1:2010 § 7.2.6 */
|
||||
int is_gray_profile = strncmp((char *) icc_buffer + 16, "GRAY", 4) == 0;
|
||||
int is_rgb_profile = strncmp((char *) icc_buffer + 16, "RGB ", 4) == 0;
|
||||
if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) ||
|
||||
(is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB))
|
||||
{
|
||||
png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_gray_profile)
|
||||
{
|
||||
fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n");
|
||||
}
|
||||
if (is_rgb_profile)
|
||||
{
|
||||
fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n");
|
||||
}
|
||||
}
|
||||
free(icc_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
png_write_info(*png_ptr, *info_ptr);
|
||||
}
|
||||
#endif
|
||||
|
@ -1387,7 +1420,7 @@ scan_it (FILE *ofp)
|
|||
case OUTPUT_PNG:
|
||||
write_png_header (parm.format, parm.pixels_per_line,
|
||||
parm.lines, parm.depth, resolution_value,
|
||||
ofp, &png_ptr, &info_ptr);
|
||||
icc_profile, ofp, &png_ptr, &info_ptr);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_LIBJPEG
|
||||
|
@ -1659,7 +1692,7 @@ scan_it (FILE *ofp)
|
|||
case OUTPUT_PNG:
|
||||
write_png_header (parm.format, parm.pixels_per_line,
|
||||
image.height, parm.depth, resolution_value,
|
||||
ofp, &png_ptr, &info_ptr);
|
||||
icc_profile, ofp, &png_ptr, &info_ptr);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_LIBJPEG
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/* Load an ICC profile for embedding in an output file
|
||||
Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void *
|
||||
sanei_load_icc_profile (const char *path, size_t *size)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
size_t stated_size = 0;
|
||||
void *profile = NULL;
|
||||
struct stat s;
|
||||
|
||||
fd = fopen(path, "r");
|
||||
|
||||
if (!fd)
|
||||
{
|
||||
fprintf(stderr, "Could not open ICC profile %s\n", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
fstat(fileno(fd), &s);
|
||||
stated_size = 16777216 * fgetc(fd) + 65536 * fgetc(fd) + 256 * fgetc(fd) + fgetc(fd);
|
||||
rewind(fd);
|
||||
|
||||
if (stated_size > (size_t) s.st_size)
|
||||
{
|
||||
fprintf(stderr, "Ignoring ICC profile because file %s is shorter than the profile\n", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = malloc(stated_size);
|
||||
|
||||
if (fread(profile, stated_size, 1, fd) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading ICC profile %s\n", path);
|
||||
free(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fd);
|
||||
*size = stated_size;
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/* Load an ICC profile for embedding in an output file
|
||||
Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
void *
|
||||
sanei_load_icc_profile (const char *path, size_t *size);
|
|
@ -1,6 +1,7 @@
|
|||
/* Create SANE/tiff headers TIFF interfacing routines for SANE
|
||||
Copyright (C) 2000 Peter Kirchgessner
|
||||
Copyright (C) 2002 Oliver Rauch: added tiff ICC profile
|
||||
Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
|
@ -20,6 +21,7 @@
|
|||
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
|
||||
2017-04-16, AMH: Separate ICC profile loading into a separate file
|
||||
*/
|
||||
#ifdef _AIX
|
||||
# include "../include/lalloca.h" /* MUST come first for AIX! */
|
||||
|
@ -31,6 +33,7 @@
|
|||
#include "../include/sane/config.h"
|
||||
#include "../include/sane/sane.h"
|
||||
|
||||
#include "sicc.h"
|
||||
#include "stiff.h"
|
||||
|
||||
typedef struct {
|
||||
|
@ -269,22 +272,12 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
|
|||
int strip_bytecount;
|
||||
int ntags;
|
||||
int motorola, bps, maxsamplevalue;
|
||||
FILE *icc_file = 0;
|
||||
int icc_len = -1;
|
||||
void *icc_buffer = NULL;
|
||||
size_t icc_size = 0;
|
||||
|
||||
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) + 256 * fgetc(icc_file) + fgetc(icc_file);
|
||||
rewind(icc_file);
|
||||
}
|
||||
icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
|
||||
}
|
||||
|
||||
ifd = create_ifd ();
|
||||
|
@ -302,10 +295,10 @@ 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 */
|
||||
if (icc_size > 0) /* if icc profile exists add memory for tag */
|
||||
{
|
||||
ntags += 1;
|
||||
data_size += icc_len;
|
||||
data_size += icc_size;
|
||||
}
|
||||
|
||||
ifd_size = 2 + ntags*12 + 4;
|
||||
|
@ -355,10 +348,10 @@ 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 */
|
||||
if (icc_size > 0) /* add ICC-profile TAG */
|
||||
{
|
||||
add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
|
||||
data_offset += icc_len;
|
||||
add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
|
||||
data_offset += icc_size;
|
||||
}
|
||||
|
||||
/* I prefer motorola format. Its human readable. But for 16 bit, */
|
||||
|
@ -383,33 +376,16 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
|
|||
write_i4 (fptr, 1, motorola);
|
||||
}
|
||||
|
||||
/* Write ICC profile */
|
||||
if (icc_len > 0)
|
||||
if (icc_size > 0)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<icc_len; i++)
|
||||
{
|
||||
if (!feof(icc_file))
|
||||
{
|
||||
fputc(fgetc(icc_file), fptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fwrite(icc_buffer, icc_size, 1, fptr);
|
||||
}
|
||||
|
||||
if (icc_file)
|
||||
{
|
||||
fclose(icc_file);
|
||||
}
|
||||
free(icc_buffer);
|
||||
|
||||
free_ifd (ifd);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_tiff_color_header (FILE *fptr, int width, int height, int depth,
|
||||
int resolution, const char *icc_profile)
|
||||
|
@ -419,22 +395,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
|
|||
int strip_bytecount;
|
||||
int ntags;
|
||||
int motorola, bps, maxsamplevalue;
|
||||
FILE *icc_file = 0;
|
||||
int icc_len = -1;
|
||||
void *icc_buffer = NULL;
|
||||
size_t icc_size = 0;
|
||||
|
||||
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) + 256 * fgetc(icc_file) + fgetc(icc_file);
|
||||
rewind(icc_file);
|
||||
}
|
||||
icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -454,10 +420,10 @@ write_tiff_color_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 */
|
||||
if (icc_size > 0) /* if icc profile exists add memory for tag */
|
||||
{
|
||||
ntags += 1;
|
||||
data_size += icc_len;
|
||||
data_size += icc_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -513,10 +479,10 @@ write_tiff_color_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 */
|
||||
if (icc_size > 0) /* add ICC-profile TAG */
|
||||
{
|
||||
add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
|
||||
data_offset += icc_len;
|
||||
add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
|
||||
data_offset += icc_size;
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,27 +524,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
|
|||
}
|
||||
|
||||
/* Write ICC profile */
|
||||
if (icc_len > 0)
|
||||
if (icc_size > 0)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<icc_len; i++)
|
||||
{
|
||||
if (!feof(icc_file))
|
||||
{
|
||||
fputc(fgetc(icc_file), fptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fwrite(icc_buffer, icc_size, 1, fptr);
|
||||
}
|
||||
|
||||
if (icc_file)
|
||||
{
|
||||
fclose(icc_file);
|
||||
}
|
||||
free(icc_buffer);
|
||||
|
||||
free_ifd (ifd);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue