2017-11-30 12:02:36 -05:00
|
|
|
/*
|
2003-11-26 04:05:41 -05:00
|
|
|
*
|
|
|
|
* tiff2pdf - converts a TIFF image to a PDF document
|
|
|
|
*
|
|
|
|
* Copyright (c) 2003 Ross Finlayson
|
2003-11-25 11:39:22 -05:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and
|
|
|
|
* its documentation for any purpose is hereby granted without fee, provided
|
|
|
|
* that (i) the above copyright notices and this permission notice appear in
|
2003-11-26 04:05:41 -05:00
|
|
|
* all copies of the software and related documentation, and (ii) the name of
|
|
|
|
* Ross Finlayson may not be used in any advertising or
|
2003-11-25 11:39:22 -05:00
|
|
|
* publicity relating to the software without the specific, prior written
|
2003-11-29 10:32:40 -05:00
|
|
|
* permission of Ross Finlayson.
|
2003-11-25 11:39:22 -05:00
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
|
|
|
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
2003-11-26 04:05:41 -05:00
|
|
|
* IN NO EVENT SHALL ROSS FINLAYSON BE LIABLE FOR
|
2003-11-25 11:39:22 -05:00
|
|
|
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
|
|
|
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
|
|
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
|
|
* OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2004-08-25 09:43:14 -04:00
|
|
|
#include "tif_config.h"
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
#include <stdio.h>
|
2003-11-29 10:32:40 -05:00
|
|
|
#include <stdlib.h>
|
2003-11-25 11:39:22 -05:00
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <time.h>
|
2010-06-30 10:12:03 -04:00
|
|
|
#include <errno.h>
|
2015-01-22 04:58:49 -05:00
|
|
|
#include <limits.h>
|
2004-08-25 09:43:14 -04:00
|
|
|
|
|
|
|
#if HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
2004-08-25 09:43:14 -04:00
|
|
|
|
2006-04-20 08:36:23 -04:00
|
|
|
#ifdef HAVE_FCNTL_H
|
|
|
|
# include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_IO_H
|
|
|
|
# include <io.h>
|
|
|
|
#endif
|
|
|
|
|
2009-01-22 15:53:07 -05:00
|
|
|
#ifdef NEED_LIBPORT
|
|
|
|
# include "libport.h"
|
|
|
|
#endif
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
#include "tiffiop.h"
|
2007-07-03 11:47:05 -04:00
|
|
|
#include "tiffio.h"
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-02-24 11:28:48 -05:00
|
|
|
#ifndef HAVE_GETOPT
|
2019-11-03 12:21:26 -05:00
|
|
|
extern int getopt(int argc, char * const argv[], const char *optstring);
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
#ifndef EXIT_SUCCESS
|
|
|
|
# define EXIT_SUCCESS 0
|
|
|
|
#endif
|
|
|
|
#ifndef EXIT_FAILURE
|
|
|
|
# define EXIT_FAILURE 1
|
|
|
|
#endif
|
|
|
|
|
2003-11-29 10:32:40 -05:00
|
|
|
#define TIFF2PDF_MODULE "tiff2pdf"
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-02-24 11:28:48 -05:00
|
|
|
#define PS_UNIT_SIZE 72.0F
|
|
|
|
|
2018-02-06 10:13:57 -05:00
|
|
|
#define TIFF_DIR_MAX 65534
|
|
|
|
|
2020-03-21 10:30:43 -04:00
|
|
|
#define DEFAULT_MAX_MALLOC (256 * 1024 * 1024)
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
/* This type is of PDF color spaces. */
|
2007-02-24 11:28:48 -05:00
|
|
|
typedef enum {
|
|
|
|
T2P_CS_BILEVEL = 0x01, /* Bilevel, black and white */
|
|
|
|
T2P_CS_GRAY = 0x02, /* Single channel */
|
|
|
|
T2P_CS_RGB = 0x04, /* Three channel tristimulus RGB */
|
|
|
|
T2P_CS_CMYK = 0x08, /* Four channel CMYK print inkset */
|
|
|
|
T2P_CS_LAB = 0x10, /* Three channel L*a*b* color space */
|
|
|
|
T2P_CS_PALETTE = 0x1000,/* One of the above with a color map */
|
|
|
|
T2P_CS_CALGRAY = 0x20, /* Calibrated single channel */
|
|
|
|
T2P_CS_CALRGB = 0x40, /* Calibrated three channel tristimulus RGB */
|
|
|
|
T2P_CS_ICCBASED = 0x80 /* ICC profile color specification */
|
2003-11-25 11:39:22 -05:00
|
|
|
} t2p_cs_t;
|
|
|
|
|
|
|
|
/* This type is of PDF compression types. */
|
|
|
|
typedef enum{
|
|
|
|
T2P_COMPRESS_NONE=0x00
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
, T2P_COMPRESS_G4=0x01
|
|
|
|
#endif
|
|
|
|
#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT)
|
|
|
|
, T2P_COMPRESS_JPEG=0x02
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
, T2P_COMPRESS_ZIP=0x04
|
|
|
|
#endif
|
|
|
|
} t2p_compress_t;
|
|
|
|
|
|
|
|
/* This type is whether TIFF image data can be used in PDF without transcoding. */
|
|
|
|
typedef enum{
|
|
|
|
T2P_TRANSCODE_RAW=0x01, /* The raw data from the input can be used without recompressing */
|
|
|
|
T2P_TRANSCODE_ENCODE=0x02 /* The data from the input is perhaps unencoded and reencoded */
|
|
|
|
} t2p_transcode_t;
|
|
|
|
|
|
|
|
/* This type is of information about the data samples of the input image. */
|
|
|
|
typedef enum{
|
|
|
|
T2P_SAMPLE_NOTHING=0x0000, /* The unencoded samples are normal for the output colorspace */
|
|
|
|
T2P_SAMPLE_ABGR_TO_RGB=0x0001, /* The unencoded samples are the result of ReadRGBAImage */
|
|
|
|
T2P_SAMPLE_RGBA_TO_RGB=0x0002, /* The unencoded samples are contiguous RGBA */
|
|
|
|
T2P_SAMPLE_RGBAA_TO_RGB=0x0004, /* The unencoded samples are RGBA with premultiplied alpha */
|
|
|
|
T2P_SAMPLE_YCBCR_TO_RGB=0x0008,
|
|
|
|
T2P_SAMPLE_YCBCR_TO_LAB=0x0010,
|
|
|
|
T2P_SAMPLE_REALIZE_PALETTE=0x0020, /* The unencoded samples are indexes into the color map */
|
|
|
|
T2P_SAMPLE_SIGNED_TO_UNSIGNED=0x0040, /* The unencoded samples are signed instead of unsignd */
|
|
|
|
T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED=0x0040, /* The L*a*b* samples have a* and b* signed */
|
|
|
|
T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG=0x0100 /* The unencoded samples are separate instead of contiguous */
|
|
|
|
} t2p_sample_t;
|
|
|
|
|
|
|
|
/* This type is of error status of the T2P struct. */
|
|
|
|
typedef enum{
|
|
|
|
T2P_ERR_OK = 0, /* This is the value of t2p->t2p_error when there is no error */
|
|
|
|
T2P_ERR_ERROR = 1 /* This is the value of t2p->t2p_error when there was an error */
|
|
|
|
} t2p_err_t;
|
|
|
|
|
|
|
|
/* This struct defines a logical page of a TIFF. */
|
|
|
|
typedef struct {
|
|
|
|
tdir_t page_directory;
|
|
|
|
uint32 page_number;
|
|
|
|
ttile_t page_tilecount;
|
|
|
|
uint32 page_extra;
|
|
|
|
} T2P_PAGE;
|
|
|
|
|
|
|
|
/* This struct defines a PDF rectangle's coordinates. */
|
|
|
|
typedef struct {
|
|
|
|
float x1;
|
|
|
|
float y1;
|
|
|
|
float x2;
|
|
|
|
float y2;
|
|
|
|
float mat[9];
|
|
|
|
} T2P_BOX;
|
|
|
|
|
|
|
|
/* This struct defines a tile of a PDF. */
|
|
|
|
typedef struct {
|
|
|
|
T2P_BOX tile_box;
|
|
|
|
} T2P_TILE;
|
|
|
|
|
|
|
|
/* This struct defines information about the tiles on a PDF page. */
|
|
|
|
typedef struct {
|
|
|
|
ttile_t tiles_tilecount;
|
|
|
|
uint32 tiles_tilewidth;
|
|
|
|
uint32 tiles_tilelength;
|
|
|
|
uint32 tiles_tilecountx;
|
|
|
|
uint32 tiles_tilecounty;
|
|
|
|
uint32 tiles_edgetilewidth;
|
|
|
|
uint32 tiles_edgetilelength;
|
|
|
|
T2P_TILE* tiles_tiles;
|
|
|
|
} T2P_TILES;
|
|
|
|
|
|
|
|
/* This struct is the context of a function to generate PDF from a TIFF. */
|
|
|
|
typedef struct {
|
|
|
|
t2p_err_t t2p_error;
|
|
|
|
T2P_PAGE* tiff_pages;
|
|
|
|
T2P_TILES* tiff_tiles;
|
|
|
|
tdir_t tiff_pagecount;
|
|
|
|
uint16 tiff_compression;
|
|
|
|
uint16 tiff_photometric;
|
|
|
|
uint16 tiff_fillorder;
|
|
|
|
uint16 tiff_bitspersample;
|
|
|
|
uint16 tiff_samplesperpixel;
|
|
|
|
uint16 tiff_planar;
|
|
|
|
uint32 tiff_width;
|
|
|
|
uint32 tiff_length;
|
|
|
|
float tiff_xres;
|
|
|
|
float tiff_yres;
|
|
|
|
uint16 tiff_orientation;
|
|
|
|
toff_t tiff_dataoffset;
|
|
|
|
tsize_t tiff_datasize;
|
2020-03-21 10:30:43 -04:00
|
|
|
tsize_t tiff_maxdatasize;
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 tiff_resunit;
|
|
|
|
uint16 pdf_centimeters;
|
|
|
|
uint16 pdf_overrideres;
|
|
|
|
uint16 pdf_overridepagesize;
|
|
|
|
float pdf_defaultxres;
|
|
|
|
float pdf_defaultyres;
|
|
|
|
float pdf_xres;
|
|
|
|
float pdf_yres;
|
|
|
|
float pdf_defaultpagewidth;
|
|
|
|
float pdf_defaultpagelength;
|
|
|
|
float pdf_pagewidth;
|
|
|
|
float pdf_pagelength;
|
|
|
|
float pdf_imagewidth;
|
|
|
|
float pdf_imagelength;
|
2010-12-11 17:47:49 -05:00
|
|
|
int pdf_image_fillpage; /* 0 (default: no scaling, 1:scale imagesize to pagesize */
|
2003-11-25 11:39:22 -05:00
|
|
|
T2P_BOX pdf_mediabox;
|
|
|
|
T2P_BOX pdf_imagebox;
|
|
|
|
uint16 pdf_majorversion;
|
|
|
|
uint16 pdf_minorversion;
|
|
|
|
uint32 pdf_catalog;
|
|
|
|
uint32 pdf_pages;
|
|
|
|
uint32 pdf_info;
|
|
|
|
uint32 pdf_palettecs;
|
|
|
|
uint16 pdf_fitwindow;
|
|
|
|
uint32 pdf_startxref;
|
2010-06-30 12:04:50 -04:00
|
|
|
#define TIFF2PDF_FILEID_SIZE 33
|
|
|
|
char pdf_fileid[TIFF2PDF_FILEID_SIZE];
|
2010-06-30 10:12:03 -04:00
|
|
|
#define TIFF2PDF_DATETIME_SIZE 17
|
|
|
|
char pdf_datetime[TIFF2PDF_DATETIME_SIZE];
|
|
|
|
#define TIFF2PDF_CREATOR_SIZE 512
|
|
|
|
char pdf_creator[TIFF2PDF_CREATOR_SIZE];
|
2020-03-20 20:05:41 -04:00
|
|
|
int pdf_creator_set;
|
2010-06-30 10:12:03 -04:00
|
|
|
#define TIFF2PDF_AUTHOR_SIZE 512
|
|
|
|
char pdf_author[TIFF2PDF_AUTHOR_SIZE];
|
2020-03-20 20:05:41 -04:00
|
|
|
int pdf_author_set;
|
2010-06-30 10:12:03 -04:00
|
|
|
#define TIFF2PDF_TITLE_SIZE 512
|
|
|
|
char pdf_title[TIFF2PDF_TITLE_SIZE];
|
2020-03-20 20:05:41 -04:00
|
|
|
int pdf_title_set;
|
2010-06-30 10:12:03 -04:00
|
|
|
#define TIFF2PDF_SUBJECT_SIZE 512
|
|
|
|
char pdf_subject[TIFF2PDF_SUBJECT_SIZE];
|
2020-03-20 20:05:41 -04:00
|
|
|
int pdf_subject_set;
|
2010-06-30 10:12:03 -04:00
|
|
|
#define TIFF2PDF_KEYWORDS_SIZE 512
|
|
|
|
char pdf_keywords[TIFF2PDF_KEYWORDS_SIZE];
|
2020-03-20 20:05:41 -04:00
|
|
|
int pdf_keywords_set;
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p_cs_t pdf_colorspace;
|
|
|
|
uint16 pdf_colorspace_invert;
|
|
|
|
uint16 pdf_switchdecode;
|
|
|
|
uint16 pdf_palettesize;
|
|
|
|
unsigned char* pdf_palette;
|
|
|
|
int pdf_labrange[4];
|
|
|
|
t2p_compress_t pdf_defaultcompression;
|
|
|
|
uint16 pdf_defaultcompressionquality;
|
|
|
|
t2p_compress_t pdf_compression;
|
2020-03-26 19:31:59 -04:00
|
|
|
uint16 pdf_compressionquality; /* for deflate : 100 * zipquality + predictor */
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 pdf_nopassthrough;
|
|
|
|
t2p_transcode_t pdf_transcode;
|
|
|
|
t2p_sample_t pdf_sample;
|
|
|
|
uint32* pdf_xrefoffsets;
|
|
|
|
uint32 pdf_xrefcount;
|
|
|
|
tdir_t pdf_page;
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
tdata_t pdf_ojpegdata;
|
|
|
|
uint32 pdf_ojpegdatalength;
|
|
|
|
uint32 pdf_ojpegiflength;
|
|
|
|
#endif
|
|
|
|
float tiff_whitechromaticities[2];
|
|
|
|
float tiff_primarychromaticities[6];
|
|
|
|
float tiff_referenceblackwhite[2];
|
2017-12-06 15:49:20 -05:00
|
|
|
uint16* tiff_transferfunction[3];
|
2005-05-05 16:52:57 -04:00
|
|
|
int pdf_image_interpolate; /* 0 (default) : do not interpolate,
|
|
|
|
1 : interpolate */
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 tiff_transferfunctioncount;
|
|
|
|
uint32 pdf_icccs;
|
|
|
|
uint32 tiff_iccprofilelength;
|
|
|
|
tdata_t tiff_iccprofile;
|
2007-07-03 11:47:05 -04:00
|
|
|
|
|
|
|
/* fields for custom read/write procedures */
|
|
|
|
FILE *outputfile;
|
|
|
|
int outputdisable;
|
|
|
|
tsize_t outputwritten;
|
2003-11-25 11:39:22 -05:00
|
|
|
} T2P;
|
|
|
|
|
|
|
|
/* These functions are called by main. */
|
|
|
|
|
2020-03-07 10:06:40 -05:00
|
|
|
static void tiff2pdf_usage(int);
|
2003-11-25 11:39:22 -05:00
|
|
|
int tiff2pdf_match_paper_size(float*, float*, char*);
|
|
|
|
|
|
|
|
/* These functions are used to generate a PDF from a TIFF. */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
T2P* t2p_init(void);
|
|
|
|
void t2p_validate(T2P*);
|
|
|
|
tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*);
|
|
|
|
void t2p_free(T2P*);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void t2p_read_tiff_init(T2P*, TIFF*);
|
|
|
|
int t2p_cmp_t2p_page(const void*, const void*);
|
|
|
|
void t2p_read_tiff_data(T2P*, TIFF*);
|
|
|
|
void t2p_read_tiff_size(T2P*, TIFF*);
|
|
|
|
void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t);
|
|
|
|
int t2p_tile_is_right_edge(T2P_TILES, ttile_t);
|
|
|
|
int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t);
|
2003-11-29 10:32:40 -05:00
|
|
|
int t2p_tile_is_edge(T2P_TILES, ttile_t);
|
|
|
|
int t2p_tile_is_corner_edge(T2P_TILES, ttile_t);
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*);
|
|
|
|
tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t);
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
int t2p_process_ojpeg_tables(T2P*, TIFF*);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
2016-09-23 18:12:18 -04:00
|
|
|
int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t, tsize_t*, tstrip_t, uint32);
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
|
|
|
void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32);
|
|
|
|
void t2p_write_advance_directory(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t);
|
|
|
|
tsize_t t2p_sample_realize_palette(T2P*, unsigned char*);
|
|
|
|
tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32);
|
|
|
|
tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32);
|
|
|
|
tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32);
|
|
|
|
tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32);
|
|
|
|
tsize_t t2p_write_pdf_header(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_obj_start(uint32, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_obj_end(TIFF*);
|
2020-03-20 20:05:41 -04:00
|
|
|
tsize_t t2p_write_pdf_name(const unsigned char*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_string(const char*, TIFF*);
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_start(TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_end(TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_dict_start(TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_dict_end(TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_catalog(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*);
|
|
|
|
void t2p_pdf_currenttime(T2P*);
|
|
|
|
void t2p_pdf_tifftime(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_pages(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*);
|
|
|
|
void t2p_compose_pdf_page(T2P*);
|
|
|
|
void t2p_compose_pdf_page_orient(T2P_BOX*, uint16);
|
|
|
|
void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16);
|
|
|
|
tsize_t t2p_write_pdf_page_content(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_transfer(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16);
|
|
|
|
tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16);
|
|
|
|
tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_cs_stream(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*);
|
|
|
|
tsize_t t2p_write_pdf_trailer(T2P*, TIFF*);
|
|
|
|
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
#define check_snprintf_ret(t2p, rv, buf) do { \
|
|
|
|
if ((rv) < 0) rv = 0; \
|
|
|
|
else if((rv) >= (int)sizeof(buf)) (rv) = sizeof(buf) - 1; \
|
|
|
|
else break; \
|
|
|
|
if ((t2p) != NULL) (t2p)->t2p_error = T2P_ERR_ERROR; \
|
|
|
|
} while(0)
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
static void
|
|
|
|
t2p_disable(TIFF *tif)
|
|
|
|
{
|
|
|
|
T2P *t2p = (T2P*) TIFFClientdata(tif);
|
|
|
|
t2p->outputdisable = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
t2p_enable(TIFF *tif)
|
|
|
|
{
|
|
|
|
T2P *t2p = (T2P*) TIFFClientdata(tif);
|
|
|
|
t2p->outputdisable = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Procs for TIFFClientOpen
|
|
|
|
*/
|
|
|
|
|
2015-09-06 14:24:27 -04:00
|
|
|
#ifdef OJPEG_SUPPORT
|
2007-07-03 11:47:05 -04:00
|
|
|
static tmsize_t
|
|
|
|
t2pReadFile(TIFF *tif, tdata_t data, tmsize_t size)
|
|
|
|
{
|
|
|
|
thandle_t client = TIFFClientdata(tif);
|
|
|
|
TIFFReadWriteProc proc = TIFFGetReadProc(tif);
|
|
|
|
if (proc)
|
|
|
|
return proc(client, data, size);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-09-06 14:24:27 -04:00
|
|
|
#endif /* OJPEG_SUPPORT */
|
2007-07-03 11:47:05 -04:00
|
|
|
|
|
|
|
static tmsize_t
|
|
|
|
t2pWriteFile(TIFF *tif, tdata_t data, tmsize_t size)
|
|
|
|
{
|
|
|
|
thandle_t client = TIFFClientdata(tif);
|
|
|
|
TIFFReadWriteProc proc = TIFFGetWriteProc(tif);
|
|
|
|
if (proc)
|
|
|
|
return proc(client, data, size);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64
|
|
|
|
t2pSeekFile(TIFF *tif, toff_t offset, int whence)
|
|
|
|
{
|
|
|
|
thandle_t client = TIFFClientdata(tif);
|
|
|
|
TIFFSeekProc proc = TIFFGetSeekProc(tif);
|
|
|
|
if (proc)
|
|
|
|
return proc(client, offset, whence);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tmsize_t
|
|
|
|
t2p_readproc(thandle_t handle, tdata_t data, tmsize_t size)
|
|
|
|
{
|
|
|
|
(void) handle, (void) data, (void) size;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tmsize_t
|
|
|
|
t2p_writeproc(thandle_t handle, tdata_t data, tmsize_t size)
|
|
|
|
{
|
|
|
|
T2P *t2p = (T2P*) handle;
|
|
|
|
if (t2p->outputdisable <= 0 && t2p->outputfile) {
|
|
|
|
tsize_t written = fwrite(data, 1, size, t2p->outputfile);
|
|
|
|
t2p->outputwritten += written;
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64
|
|
|
|
t2p_seekproc(thandle_t handle, uint64 offset, int whence)
|
|
|
|
{
|
|
|
|
T2P *t2p = (T2P*) handle;
|
|
|
|
if (t2p->outputdisable <= 0 && t2p->outputfile)
|
2015-08-18 22:31:04 -04:00
|
|
|
return _TIFF_fseek_f(t2p->outputfile, (_TIFF_off_t) offset, whence);
|
2007-07-03 11:47:05 -04:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
t2p_closeproc(thandle_t handle)
|
|
|
|
{
|
2014-11-20 11:47:21 -05:00
|
|
|
T2P *t2p = (T2P*) handle;
|
|
|
|
return fclose(t2p->outputfile);
|
2007-07-03 11:47:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static uint64
|
|
|
|
t2p_sizeproc(thandle_t handle)
|
|
|
|
{
|
|
|
|
(void) handle;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2007-07-12 13:32:53 -04:00
|
|
|
t2p_mapproc(thandle_t handle, void **data, toff_t *offset)
|
2007-07-03 11:47:05 -04:00
|
|
|
{
|
|
|
|
(void) handle, (void) data, (void) offset;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-07-12 13:32:53 -04:00
|
|
|
t2p_unmapproc(thandle_t handle, void *data, toff_t offset)
|
2007-07-03 11:47:05 -04:00
|
|
|
{
|
|
|
|
(void) handle, (void) data, (void) offset;
|
|
|
|
}
|
|
|
|
|
2015-09-06 14:24:27 -04:00
|
|
|
#if defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT)
|
2012-06-15 17:44:31 -04:00
|
|
|
static uint64
|
|
|
|
checkAdd64(uint64 summand1, uint64 summand2, T2P* t2p)
|
|
|
|
{
|
|
|
|
uint64 bytes = summand1 + summand2;
|
|
|
|
|
2015-01-05 14:03:11 -05:00
|
|
|
if (bytes < summand1) {
|
2012-06-15 17:44:31 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
bytes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
2015-09-06 14:24:27 -04:00
|
|
|
#endif /* defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) */
|
2012-06-15 17:44:31 -04:00
|
|
|
|
|
|
|
static uint64
|
|
|
|
checkMultiply64(uint64 first, uint64 second, T2P* t2p)
|
|
|
|
{
|
|
|
|
uint64 bytes = first * second;
|
|
|
|
|
|
|
|
if (second && bytes / second != first) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
bytes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
/*
|
|
|
|
|
|
|
|
This is the main function.
|
|
|
|
|
|
|
|
The program converts one TIFF file to one PDF file, including multiple page
|
|
|
|
TIFF files, tiled TIFF files, black and white. grayscale, and color TIFF
|
|
|
|
files that contain data of TIFF photometric interpretations of bilevel,
|
|
|
|
grayscale, RGB, YCbCr, CMYK separation, and ICC L*a*b* as supported by
|
|
|
|
libtiff and PDF.
|
|
|
|
|
|
|
|
If you have multiple TIFF files to convert into one PDF file then use tiffcp
|
|
|
|
or other program to concatenate the files into a multiple page TIFF file.
|
|
|
|
If the input TIFF file is of huge dimensions (greater than 10000 pixels height
|
|
|
|
or width) convert the input image to a tiled TIFF if it is not already.
|
|
|
|
|
|
|
|
The standard output is standard output. Set the output file name with the
|
|
|
|
"-o output.pdf" option.
|
|
|
|
|
|
|
|
All black and white files are compressed into a single strip CCITT G4 Fax
|
|
|
|
compressed PDF, unless tiled, where tiled black and white images are
|
|
|
|
compressed into tiled CCITT G4 Fax compressed PDF, libtiff CCITT support
|
|
|
|
is assumed.
|
|
|
|
|
|
|
|
Color and grayscale data can be compressed using either JPEG compression,
|
|
|
|
ITU-T T.81, or Zip/Deflate LZ77 compression, per PNG 1.2 and RFC 1951. Set
|
|
|
|
the compression type using the -j or -z options. JPEG compression support
|
|
|
|
requires that libtiff be configured with JPEG support, and Zip/Deflate
|
|
|
|
compression support requires that libtiff is configured with Zip support,
|
|
|
|
in tiffconf.h. Use only one or the other of -j and -z. The -q option
|
|
|
|
sets the image compression quality, that is 1-100 with libjpeg JPEG
|
|
|
|
compression and one of 1, 10, 11, 12, 13, 14, or 15 for PNG group compression
|
|
|
|
predictor methods, add 100, 200, ..., 900 to set zlib compression quality 1-9.
|
|
|
|
PNG Group differencing predictor methods are not currently implemented.
|
|
|
|
|
|
|
|
If the input TIFF contains single strip CCITT G4 Fax compressed information,
|
|
|
|
then that is written to the PDF file without transcoding, unless the options
|
|
|
|
of no compression and no passthrough are set, -d and -n.
|
|
|
|
|
|
|
|
If the input TIFF contains JPEG or single strip Zip/Deflate compressed
|
|
|
|
information, and they are configured, then that is written to the PDF file
|
|
|
|
without transcoding, unless the options of no compression and no passthrough
|
|
|
|
are set.
|
|
|
|
|
|
|
|
The default page size upon which the TIFF image is placed is determined by
|
|
|
|
the resolution and extent of the image data. Default values for the TIFF
|
|
|
|
image resolution can be set using the -x and -y options. The page size can
|
|
|
|
be set using the -p option for paper size, or -w and -l for paper width and
|
|
|
|
length, then each page of the TIFF image is centered on its page. The
|
|
|
|
distance unit for default resolution and page width and length can be set
|
|
|
|
by the -u option, the default unit is inch.
|
|
|
|
|
|
|
|
Various items of the output document information can be set with the -e, -c,
|
|
|
|
-a, -t, -s, and -k tags. Setting the argument of the option to "" for these
|
|
|
|
tags causes the relevant document information field to be not written. Some
|
|
|
|
of the document information values otherwise get their information from the
|
|
|
|
input TIFF image, the software, author, document name, and image description.
|
|
|
|
|
|
|
|
The output PDF file conforms to the PDF 1.1 specification or PDF 1.2 if using
|
|
|
|
Zip/Deflate compression.
|
|
|
|
|
|
|
|
The Portable Document Format (PDF) specification is copyrighted by Adobe
|
|
|
|
Systems, Incorporated. Todos derechos reservados.
|
|
|
|
|
|
|
|
Here is a listing of the usage example and the options to the tiff2pdf
|
|
|
|
program that is part of the libtiff distribution. Options followed by
|
|
|
|
a colon have a required argument.
|
|
|
|
|
|
|
|
usage: tiff2pdf [options] input.tif
|
|
|
|
|
|
|
|
options:
|
|
|
|
-o: output to file name
|
|
|
|
|
2006-04-20 08:04:35 -04:00
|
|
|
-j: compress with JPEG (requires libjpeg configured with libtiff)
|
|
|
|
-z: compress with Zip/Deflate (requires zlib configured with libtiff)
|
2003-11-25 11:39:22 -05:00
|
|
|
-q: compression quality
|
2006-04-20 08:04:35 -04:00
|
|
|
-n: no compressed data passthrough
|
|
|
|
-d: do not compress (decompress)
|
|
|
|
-i: invert colors
|
2003-11-25 11:39:22 -05:00
|
|
|
-u: set distance unit, 'i' for inch, 'm' for centimeter
|
|
|
|
-x: set x resolution default
|
|
|
|
-y: set y resolution default
|
|
|
|
-w: width in units
|
|
|
|
-l: length in units
|
|
|
|
-r: 'd' for resolution default, 'o' for resolution override
|
2006-04-20 08:04:35 -04:00
|
|
|
-p: paper size, eg "letter", "legal", "a4"
|
2010-12-11 17:47:49 -05:00
|
|
|
-F: make the tiff fill the PDF page
|
2006-04-20 08:04:35 -04:00
|
|
|
-f: set pdf "fit window" user preference
|
|
|
|
-b: set PDF "Interpolate" user preference
|
2003-11-25 11:39:22 -05:00
|
|
|
-e: date, overrides image or current date/time default, YYYYMMDDHHMMSS
|
|
|
|
-c: creator, overrides image software default
|
|
|
|
-a: author, overrides image artist default
|
|
|
|
-t: title, overrides image document name default
|
|
|
|
-s: subject, overrides image image description default
|
|
|
|
-k: keywords
|
|
|
|
|
2006-04-20 08:04:35 -04:00
|
|
|
-h: usage
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
examples:
|
|
|
|
|
|
|
|
tiff2pdf -o output.pdf input.tiff
|
|
|
|
|
|
|
|
The above example would generate the file output.pdf from input.tiff.
|
|
|
|
|
|
|
|
tiff2pdf input.tiff
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
The above example would generate PDF output from input.tiff and write it
|
2003-11-25 11:39:22 -05:00
|
|
|
to standard output.
|
|
|
|
|
|
|
|
tiff2pdf -j -p letter -o output.pdf input.tiff
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
The above example would generate the file output.pdf from input.tiff,
|
|
|
|
putting the image pages on a letter sized page, compressing the output
|
2003-11-25 11:39:22 -05:00
|
|
|
with JPEG.
|
|
|
|
|
|
|
|
Please report bugs through:
|
2010-06-30 10:12:03 -04:00
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
http://bugzilla.remotesensing.org/buglist.cgi?product=libtiff
|
|
|
|
|
|
|
|
See also libtiff.3t, tiffcp.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int main(int argc, char** argv){
|
2015-06-20 21:09:09 -04:00
|
|
|
#if !HAVE_DECL_OPTARG
|
2006-02-15 08:33:59 -05:00
|
|
|
extern char *optarg;
|
2007-07-12 13:25:12 -04:00
|
|
|
extern int optind;
|
2015-06-20 21:09:09 -04:00
|
|
|
#endif
|
2007-07-03 11:47:05 -04:00
|
|
|
const char *outfilename = NULL;
|
2006-02-15 08:33:59 -05:00
|
|
|
T2P *t2p = NULL;
|
|
|
|
TIFF *input = NULL, *output = NULL;
|
2010-06-30 10:12:03 -04:00
|
|
|
int c, ret = EXIT_SUCCESS;
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p = t2p_init();
|
|
|
|
|
|
|
|
if (t2p == NULL){
|
2007-07-03 11:47:05 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE, "Can't initialize context");
|
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
while (argv &&
|
|
|
|
(c = getopt(argc, argv,
|
2020-03-21 10:30:43 -04:00
|
|
|
"m:o:q:u:x:y:w:l:r:p:e:c:a:t:s:k:jzndifbhF")) != -1){
|
2003-11-25 11:39:22 -05:00
|
|
|
switch (c) {
|
2020-03-21 10:30:43 -04:00
|
|
|
case 'm':
|
|
|
|
t2p->tiff_maxdatasize = (tsize_t)strtoul(optarg, NULL, 0) << 20;
|
|
|
|
break;
|
2006-02-15 08:33:59 -05:00
|
|
|
case 'o':
|
|
|
|
outfilename = optarg;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
case 'j':
|
|
|
|
t2p->pdf_defaultcompression=T2P_COMPRESS_JPEG;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifndef JPEG_SUPPORT
|
|
|
|
case 'j':
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"JPEG support in libtiff required for JPEG compression, ignoring option");
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
case 'z':
|
|
|
|
t2p->pdf_defaultcompression=T2P_COMPRESS_ZIP;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifndef ZIP_SUPPORT
|
|
|
|
case 'z':
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Zip support in libtiff required for Zip compression, ignoring option");
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 'q':
|
|
|
|
t2p->pdf_defaultcompressionquality=atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
t2p->pdf_nopassthrough=1;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
t2p->pdf_defaultcompression=T2P_COMPRESS_NONE;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
if(optarg[0]=='m'){
|
|
|
|
t2p->pdf_centimeters=1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
t2p->pdf_defaultxres =
|
2004-05-26 05:24:07 -04:00
|
|
|
(float)atof(optarg) / (t2p->pdf_centimeters?2.54F:1.0F);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
t2p->pdf_defaultyres =
|
2004-05-26 05:24:07 -04:00
|
|
|
(float)atof(optarg) / (t2p->pdf_centimeters?2.54F:1.0F);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
t2p->pdf_overridepagesize=1;
|
|
|
|
t2p->pdf_defaultpagewidth =
|
2007-02-24 11:28:48 -05:00
|
|
|
((float)atof(optarg) * PS_UNIT_SIZE) / (t2p->pdf_centimeters?2.54F:1.0F);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
t2p->pdf_overridepagesize=1;
|
|
|
|
t2p->pdf_defaultpagelength =
|
2007-02-24 11:28:48 -05:00
|
|
|
((float)atof(optarg) * PS_UNIT_SIZE) / (t2p->pdf_centimeters?2.54F:1.0F);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if(optarg[0]=='o'){
|
|
|
|
t2p->pdf_overrideres=1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
if(tiff2pdf_match_paper_size(
|
|
|
|
&(t2p->pdf_defaultpagewidth),
|
|
|
|
&(t2p->pdf_defaultpagelength),
|
|
|
|
optarg)){
|
|
|
|
t2p->pdf_overridepagesize=1;
|
|
|
|
} else {
|
2006-02-15 08:33:59 -05:00
|
|
|
TIFFWarning(TIFF2PDF_MODULE,
|
|
|
|
"Unknown paper size %s, ignoring option",
|
2003-11-25 11:39:22 -05:00
|
|
|
optarg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
t2p->pdf_colorspace_invert=1;
|
2005-09-20 07:19:38 -04:00
|
|
|
break;
|
2010-12-11 17:47:49 -05:00
|
|
|
case 'F':
|
|
|
|
t2p->pdf_image_fillpage = 1;
|
|
|
|
break;
|
2003-11-25 11:39:22 -05:00
|
|
|
case 'f':
|
|
|
|
t2p->pdf_fitwindow=1;
|
|
|
|
break;
|
|
|
|
case 'e':
|
2010-06-30 10:12:03 -04:00
|
|
|
if (strlen(optarg) == 0) {
|
|
|
|
t2p->pdf_datetime[0] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->pdf_datetime[0] = 'D';
|
|
|
|
t2p->pdf_datetime[1] = ':';
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_datetime + 2, optarg,
|
|
|
|
sizeof(t2p->pdf_datetime) - 3);
|
|
|
|
t2p->pdf_datetime[sizeof(t2p->pdf_datetime) - 1] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_creator, optarg, sizeof(t2p->pdf_creator) - 1);
|
|
|
|
t2p->pdf_creator[sizeof(t2p->pdf_creator) - 1] = '\0';
|
2020-03-20 20:05:41 -04:00
|
|
|
t2p->pdf_creator_set = 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'a':
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_author, optarg, sizeof(t2p->pdf_author) - 1);
|
|
|
|
t2p->pdf_author[sizeof(t2p->pdf_author) - 1] = '\0';
|
2020-03-20 20:05:41 -04:00
|
|
|
t2p->pdf_author_set = 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 't':
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_title, optarg, sizeof(t2p->pdf_title) - 1);
|
|
|
|
t2p->pdf_title[sizeof(t2p->pdf_title) - 1] = '\0';
|
2020-03-20 20:05:41 -04:00
|
|
|
t2p->pdf_title_set = 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 's':
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_subject, optarg, sizeof(t2p->pdf_subject) - 1);
|
|
|
|
t2p->pdf_subject[sizeof(t2p->pdf_subject) - 1] = '\0';
|
2020-03-20 20:05:41 -04:00
|
|
|
t2p->pdf_subject_set = 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 'k':
|
2010-06-30 10:12:03 -04:00
|
|
|
strncpy(t2p->pdf_keywords, optarg, sizeof(t2p->pdf_keywords) - 1);
|
|
|
|
t2p->pdf_keywords[sizeof(t2p->pdf_keywords) - 1] = '\0';
|
2020-03-20 20:05:41 -04:00
|
|
|
t2p->pdf_keywords_set = 1;
|
2010-06-30 10:12:03 -04:00
|
|
|
break;
|
2005-05-05 16:52:57 -04:00
|
|
|
case 'b':
|
|
|
|
t2p->pdf_image_interpolate = 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
2020-03-07 10:06:40 -05:00
|
|
|
case 'h':
|
|
|
|
tiff2pdf_usage(EXIT_SUCCESS);
|
2007-07-03 11:47:05 -04:00
|
|
|
goto success;
|
2020-03-07 10:06:40 -05:00
|
|
|
case '?':
|
|
|
|
tiff2pdf_usage(EXIT_FAILURE);
|
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
/*
|
|
|
|
* Input
|
|
|
|
*/
|
|
|
|
if(argc > optind) {
|
2003-11-25 11:39:22 -05:00
|
|
|
input = TIFFOpen(argv[optind++], "r");
|
2007-07-03 11:47:05 -04:00
|
|
|
if (input==NULL) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't open input file %s for reading",
|
|
|
|
argv[optind-1]);
|
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE, "No input file specified");
|
2020-03-07 10:06:40 -05:00
|
|
|
tiff2pdf_usage(EXIT_FAILURE);
|
2007-07-03 11:47:05 -04:00
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
if(argc > optind) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"No support for multiple input files");
|
2020-03-07 10:06:40 -05:00
|
|
|
tiff2pdf_usage(EXIT_FAILURE);
|
2007-07-03 11:47:05 -04:00
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
/*
|
|
|
|
* Output
|
|
|
|
*/
|
2015-06-13 01:32:13 -04:00
|
|
|
t2p->outputdisable = 1;
|
2006-02-15 08:33:59 -05:00
|
|
|
if (outfilename) {
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p->outputfile = fopen(outfilename, "wb");
|
|
|
|
if (t2p->outputfile == NULL) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't open output file %s for writing",
|
|
|
|
outfilename);
|
|
|
|
goto fail;
|
2006-02-15 08:33:59 -05:00
|
|
|
}
|
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
outfilename = "-";
|
|
|
|
t2p->outputfile = stdout;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
output = TIFFClientOpen(outfilename, "w", (thandle_t) t2p,
|
|
|
|
t2p_readproc, t2p_writeproc, t2p_seekproc,
|
|
|
|
t2p_closeproc, t2p_sizeproc,
|
|
|
|
t2p_mapproc, t2p_unmapproc);
|
2015-06-13 01:32:13 -04:00
|
|
|
t2p->outputdisable = 0;
|
2007-07-03 11:47:05 -04:00
|
|
|
if (output == NULL) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't initialize output descriptor");
|
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate
|
|
|
|
*/
|
|
|
|
t2p_validate(t2p);
|
|
|
|
t2pSeekFile(output, (toff_t) 0, SEEK_SET);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
/*
|
|
|
|
* Write
|
|
|
|
*/
|
2011-05-31 12:57:10 -04:00
|
|
|
t2p_write_pdf(t2p, input, output);
|
2007-07-03 11:47:05 -04:00
|
|
|
if (t2p->t2p_error != 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"An error occurred creating output PDF file");
|
|
|
|
goto fail;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
|
2010-11-28 10:35:12 -05:00
|
|
|
goto success;
|
2007-07-03 11:47:05 -04:00
|
|
|
fail:
|
2010-06-30 10:12:03 -04:00
|
|
|
ret = EXIT_FAILURE;
|
|
|
|
success:
|
2007-07-03 11:47:05 -04:00
|
|
|
if(input != NULL)
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFClose(input);
|
2007-07-03 11:47:05 -04:00
|
|
|
if (output != NULL)
|
|
|
|
TIFFClose(output);
|
|
|
|
if (t2p != NULL)
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p_free(t2p);
|
2010-06-30 10:12:03 -04:00
|
|
|
return ret;
|
2007-07-03 11:47:05 -04:00
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2020-03-07 10:06:40 -05:00
|
|
|
static void tiff2pdf_usage(int code) {
|
|
|
|
static const char* lines[]={
|
2003-11-25 11:39:22 -05:00
|
|
|
"usage: tiff2pdf [options] input.tiff",
|
|
|
|
"options:",
|
|
|
|
" -o: output to file name",
|
|
|
|
#ifdef JPEG_SUPPORT
|
2006-04-20 08:04:35 -04:00
|
|
|
" -j: compress with JPEG",
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
2006-04-20 08:04:35 -04:00
|
|
|
" -z: compress with Zip/Deflate",
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
|
|
|
" -q: compression quality",
|
2006-04-20 08:04:35 -04:00
|
|
|
" -n: no compressed data passthrough",
|
|
|
|
" -d: do not compress (decompress)",
|
|
|
|
" -i: invert colors",
|
2003-11-25 11:39:22 -05:00
|
|
|
" -u: set distance unit, 'i' for inch, 'm' for centimeter",
|
|
|
|
" -x: set x resolution default in dots per unit",
|
|
|
|
" -y: set y resolution default in dots per unit",
|
|
|
|
" -w: width in units",
|
|
|
|
" -l: length in units",
|
|
|
|
" -r: 'd' for resolution default, 'o' for resolution override",
|
|
|
|
" -p: paper size, eg \"letter\", \"legal\", \"A4\"",
|
2020-03-07 10:06:40 -05:00
|
|
|
" -F: make the tiff fill the PDF page",
|
2006-04-20 08:04:35 -04:00
|
|
|
" -f: set PDF \"Fit Window\" user preference",
|
2003-11-25 11:39:22 -05:00
|
|
|
" -e: date, overrides image or current date/time default, YYYYMMDDHHMMSS",
|
|
|
|
" -c: sets document creator, overrides image software default",
|
|
|
|
" -a: sets document author, overrides image artist default",
|
|
|
|
" -t: sets document title, overrides image document name default",
|
|
|
|
" -s: sets document subject, overrides image image description default",
|
|
|
|
" -k: sets document keywords",
|
2006-04-20 08:04:35 -04:00
|
|
|
" -b: set PDF \"Interpolate\" user preference",
|
2020-03-21 10:30:43 -04:00
|
|
|
" -m: set memory allocation limit (in MiB). set to 0 to disable limit",
|
2006-04-20 08:04:35 -04:00
|
|
|
" -h: usage",
|
2003-11-25 11:39:22 -05:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
int i=0;
|
2020-03-07 10:06:40 -05:00
|
|
|
FILE * out = (code == EXIT_SUCCESS) ? stdout : stderr;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2020-03-07 10:06:40 -05:00
|
|
|
fprintf(out, "%s\n\n", TIFFGetVersion());
|
2003-11-25 11:39:22 -05:00
|
|
|
for (i=0;lines[i]!=NULL;i++){
|
2020-03-07 10:06:40 -05:00
|
|
|
fprintf(out, "%s\n", lines[i]);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){
|
|
|
|
|
2008-09-03 03:35:25 -04:00
|
|
|
size_t i, len;
|
2003-11-25 11:39:22 -05:00
|
|
|
const char* sizes[]={
|
|
|
|
"LETTER", "A4", "LEGAL",
|
|
|
|
"EXECUTIVE", "LETTER", "LEGAL", "LEDGER", "TABLOID",
|
|
|
|
"A", "B", "C", "D", "E", "F", "G", "H", "J", "K",
|
|
|
|
"A10", "A9", "A8", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0",
|
|
|
|
"2A0", "4A0", "2A", "4A",
|
|
|
|
"B10", "B9", "B8", "B7", "B6", "B5", "B4", "B3", "B2", "B1", "B0",
|
|
|
|
"JISB10", "JISB9", "JISB8", "JISB7", "JISB6", "JISB5", "JISB4",
|
|
|
|
"JISB3", "JISB2", "JISB1", "JISB0",
|
|
|
|
"C10", "C9", "C8", "C7", "C6", "C5", "C4", "C3", "C2", "C1", "C0",
|
|
|
|
"RA2", "RA1", "RA0", "SRA4", "SRA3", "SRA2", "SRA1", "SRA0",
|
|
|
|
"A3EXTRA", "A4EXTRA",
|
|
|
|
"STATEMENT", "FOLIO", "QUARTO",
|
|
|
|
NULL
|
|
|
|
} ;
|
|
|
|
const int widths[]={
|
|
|
|
612, 595, 612,
|
|
|
|
522, 612,612,792,792,
|
|
|
|
612,792,1224,1584,2448,2016,792,2016,2448,2880,
|
|
|
|
74,105,147,210,298,420,595,842,1191,1684,2384,3370,4768,3370,4768,
|
|
|
|
88,125,176,249,354,499,709,1001,1417,2004,2835,
|
|
|
|
91,128,181,258,363,516,729,1032,1460,2064,2920,
|
|
|
|
79,113,162,230,323,459,649,918,1298,1298,2599,
|
|
|
|
1219,1729,2438,638,907,1276,1814,2551,
|
|
|
|
914,667,
|
|
|
|
396, 612, 609,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
const int lengths[]={
|
|
|
|
792,842,1008,
|
|
|
|
756,792,1008,1224,1224,
|
|
|
|
792,1224,1584,2448,3168,2880,6480,10296,12672,10296,
|
|
|
|
105,147,210,298,420,595,842,1191,1684,2384,3370,4768,6741,4768,6741,
|
|
|
|
125,176,249,354,499,709,1001,1417,2004,2835,4008,
|
|
|
|
128,181,258,363,516,729,1032,1460,2064,2920,4127,
|
|
|
|
113,162,230,323,459,649,918,1298,1837,1837,3677,
|
|
|
|
1729,2438,3458,907,1276,1814,2551,3628,
|
|
|
|
1262,914,
|
|
|
|
612, 936, 780,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
len=strlen(papersize);
|
|
|
|
for(i=0;i<len;i++){
|
2015-06-20 21:09:09 -04:00
|
|
|
papersize[i]=toupper((int) papersize[i]);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
for(i=0;sizes[i]!=NULL; i++){
|
|
|
|
if (strcmp( (const char*)papersize, sizes[i])==0){
|
|
|
|
*width=(float)widths[i];
|
|
|
|
*length=(float)lengths[i];
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-30 10:12:03 -04:00
|
|
|
* This function allocates and initializes a T2P context struct pointer.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
T2P* t2p_init()
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
T2P* t2p = (T2P*) _TIFFmalloc(sizeof(T2P));
|
|
|
|
if(t2p==NULL){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory for t2p_init",
|
|
|
|
(unsigned long) sizeof(T2P));
|
2003-11-25 11:39:22 -05:00
|
|
|
return( (T2P*) NULL );
|
|
|
|
}
|
2004-10-10 07:38:34 -04:00
|
|
|
_TIFFmemset(t2p, 0x00, sizeof(T2P));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_majorversion=1;
|
|
|
|
t2p->pdf_minorversion=1;
|
|
|
|
t2p->pdf_defaultxres=300.0;
|
|
|
|
t2p->pdf_defaultyres=300.0;
|
|
|
|
t2p->pdf_defaultpagewidth=612.0;
|
|
|
|
t2p->pdf_defaultpagelength=792.0;
|
|
|
|
t2p->pdf_xrefcount=3; /* Catalog, Info, Pages */
|
2020-03-21 10:30:43 -04:00
|
|
|
t2p->tiff_maxdatasize = DEFAULT_MAX_MALLOC;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(t2p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-30 10:12:03 -04:00
|
|
|
* This function frees a T2P context struct pointer and any allocated data fields of it.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
void t2p_free(T2P* t2p)
|
|
|
|
{
|
|
|
|
int i = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
if (t2p != NULL) {
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_xrefoffsets != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->pdf_xrefoffsets);
|
|
|
|
}
|
|
|
|
if(t2p->tiff_pages != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->tiff_pages);
|
|
|
|
}
|
|
|
|
for(i=0;i<t2p->tiff_pagecount;i++){
|
|
|
|
if(t2p->tiff_tiles[i].tiles_tiles != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->tiff_tiles[i].tiles_tiles);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->tiff_tiles != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->tiff_tiles);
|
|
|
|
}
|
|
|
|
if(t2p->pdf_palette != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->pdf_palette);
|
|
|
|
}
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->pdf_ojpegdata != NULL){
|
|
|
|
_TIFFfree( (tdata_t) t2p->pdf_ojpegdata);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
_TIFFfree( (tdata_t) t2p );
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-25 09:43:14 -04:00
|
|
|
This function validates the values of a T2P context struct pointer
|
|
|
|
before calling t2p_write_pdf with it.
|
2003-11-25 11:39:22 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_validate(T2P* t2p){
|
|
|
|
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){
|
2006-06-19 16:12:07 -04:00
|
|
|
if(t2p->pdf_defaultcompressionquality>100 ||
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_defaultcompressionquality<1){
|
|
|
|
t2p->pdf_defaultcompressionquality=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
if(t2p->pdf_defaultcompression==T2P_COMPRESS_ZIP){
|
2020-04-04 18:13:13 -04:00
|
|
|
uint16 m=t2p->pdf_defaultcompressionquality%100;
|
|
|
|
if(t2p->pdf_defaultcompressionquality/100 > 9 ||
|
|
|
|
(m>1 && m<10) || m>15){
|
|
|
|
t2p->pdf_defaultcompressionquality=0;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->pdf_defaultcompressionquality%100 !=0){
|
2020-04-04 18:13:13 -04:00
|
|
|
t2p->pdf_defaultcompressionquality/=100;
|
|
|
|
t2p->pdf_defaultcompressionquality*=100;
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2006-06-19 16:12:07 -04:00
|
|
|
"PNG Group predictor differencing not implemented, assuming compression quality %u",
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_defaultcompressionquality);
|
|
|
|
}
|
|
|
|
t2p->pdf_defaultcompressionquality%=100;
|
|
|
|
if(t2p->pdf_minorversion<2){t2p->pdf_minorversion=2;}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
(void)0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2004-08-23 08:00:30 -04:00
|
|
|
This function scans the input TIFF file for pages. It attempts
|
|
|
|
to determine which IFD's of the TIFF file contain image document
|
|
|
|
pages. For each, it gathers some information that has to do
|
|
|
|
with the output of the PDF document as a whole.
|
2003-11-25 11:39:22 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_read_tiff_init(T2P* t2p, TIFF* input){
|
|
|
|
|
|
|
|
tdir_t directorycount=0;
|
|
|
|
tdir_t i=0;
|
|
|
|
uint16 pagen=0;
|
|
|
|
uint16 paged=0;
|
|
|
|
uint16 xuint16=0;
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
uint16 tiff_transferfunctioncount=0;
|
2017-12-06 15:49:20 -05:00
|
|
|
uint16* tiff_transferfunction[3];
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
directorycount=TIFFNumberOfDirectories(input);
|
2018-02-06 10:13:57 -05:00
|
|
|
if(directorycount > TIFF_DIR_MAX) {
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"TIFF contains too many directories, %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2014-12-09 21:53:30 -05:00
|
|
|
t2p->tiff_pages = (T2P_PAGE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_PAGE)));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->tiff_pages==NULL){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2015-06-20 21:09:09 -04:00
|
|
|
"Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_pages array, %s",
|
|
|
|
(TIFF_SIZE_T) directorycount * sizeof(T2P_PAGE),
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_TIFFmemset( t2p->tiff_pages, 0x00, directorycount * sizeof(T2P_PAGE));
|
2014-12-09 21:53:30 -05:00
|
|
|
t2p->tiff_tiles = (T2P_TILES*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_TILES)));
|
2004-08-23 08:00:30 -04:00
|
|
|
if(t2p->tiff_tiles==NULL){
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2015-06-20 21:09:09 -04:00
|
|
|
"Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_tiles array, %s",
|
|
|
|
(TIFF_SIZE_T) directorycount * sizeof(T2P_TILES),
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_TIFFmemset( t2p->tiff_tiles, 0x00, directorycount * sizeof(T2P_TILES));
|
|
|
|
for(i=0;i<directorycount;i++){
|
2004-04-20 10:54:05 -04:00
|
|
|
uint32 subfiletype = 0;
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
if(!TIFFSetDirectory(input, i)){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Can't set directory %u of input file %s",
|
|
|
|
i,
|
|
|
|
TIFFFileName(input));
|
2012-07-18 11:07:55 -04:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
2004-08-24 03:48:36 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_PAGENUMBER, &pagen, &paged)){
|
2003-11-25 11:39:22 -05:00
|
|
|
if((pagen>paged) && (paged != 0)){
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->tiff_pagecount].page_number =
|
2003-11-25 11:39:22 -05:00
|
|
|
paged;
|
|
|
|
} else {
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->tiff_pagecount].page_number =
|
2003-11-25 11:39:22 -05:00
|
|
|
pagen;
|
|
|
|
}
|
|
|
|
goto ispage2;
|
|
|
|
}
|
2004-04-20 10:54:05 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_SUBFILETYPE, &subfiletype)){
|
|
|
|
if ( ((subfiletype & FILETYPE_PAGE) != 0)
|
|
|
|
|| (subfiletype == 0)){
|
2003-11-25 11:39:22 -05:00
|
|
|
goto ispage;
|
|
|
|
} else {
|
|
|
|
goto isnotpage;
|
|
|
|
}
|
|
|
|
}
|
2004-04-20 10:54:05 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_OSUBFILETYPE, &subfiletype)){
|
|
|
|
if ((subfiletype == OFILETYPE_IMAGE)
|
|
|
|
|| (subfiletype == OFILETYPE_PAGE)
|
|
|
|
|| (subfiletype == 0) ){
|
2003-11-25 11:39:22 -05:00
|
|
|
goto ispage;
|
|
|
|
} else {
|
|
|
|
goto isnotpage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ispage:
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->tiff_pagecount].page_number=t2p->tiff_pagecount;
|
2003-11-25 11:39:22 -05:00
|
|
|
ispage2:
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->tiff_pagecount].page_directory=i;
|
2003-11-25 11:39:22 -05:00
|
|
|
if(TIFFIsTiled(input)){
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->tiff_pagecount].page_tilecount =
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFNumberOfTiles(input);
|
|
|
|
}
|
|
|
|
t2p->tiff_pagecount++;
|
|
|
|
isnotpage:
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
|
2004-08-23 08:00:30 -04:00
|
|
|
qsort((void*) t2p->tiff_pages, t2p->tiff_pagecount,
|
|
|
|
sizeof(T2P_PAGE), t2p_cmp_t2p_page);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
for(i=0;i<t2p->tiff_pagecount;i++){
|
|
|
|
t2p->pdf_xrefcount += 5;
|
2003-12-01 05:51:39 -05:00
|
|
|
TIFFSetDirectory(input, t2p->tiff_pages[i].page_directory );
|
2004-08-23 08:00:30 -04:00
|
|
|
if((TIFFGetField(input, TIFFTAG_PHOTOMETRIC, &xuint16)
|
|
|
|
&& (xuint16==PHOTOMETRIC_PALETTE))
|
|
|
|
|| TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)) {
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[i].page_extra++;
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xrefcount++;
|
|
|
|
}
|
|
|
|
#ifdef ZIP_SUPPORT
|
2004-08-23 08:00:30 -04:00
|
|
|
if (TIFFGetField(input, TIFFTAG_COMPRESSION, &xuint16)) {
|
|
|
|
if( (xuint16== COMPRESSION_DEFLATE ||
|
|
|
|
xuint16== COMPRESSION_ADOBE_DEFLATE) &&
|
|
|
|
((t2p->tiff_pages[i].page_tilecount != 0)
|
|
|
|
|| TIFFNumberOfStrips(input)==1) &&
|
|
|
|
(t2p->pdf_nopassthrough==0) ){
|
|
|
|
if(t2p->pdf_minorversion<2){t2p->pdf_minorversion=2;}
|
|
|
|
}
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
#endif
|
2004-09-10 07:50:57 -04:00
|
|
|
if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION,
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
&(tiff_transferfunction[0]),
|
|
|
|
&(tiff_transferfunction[1]),
|
|
|
|
&(tiff_transferfunction[2]))) {
|
|
|
|
|
2017-12-06 15:49:20 -05:00
|
|
|
if((tiff_transferfunction[1] != (uint16*) NULL) &&
|
|
|
|
(tiff_transferfunction[2] != (uint16*) NULL)
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
) {
|
|
|
|
tiff_transferfunctioncount=3;
|
|
|
|
} else {
|
|
|
|
tiff_transferfunctioncount=1;
|
|
|
|
}
|
2004-10-09 10:15:07 -04:00
|
|
|
} else {
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
tiff_transferfunctioncount=0;
|
2004-10-09 10:15:07 -04:00
|
|
|
}
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
|
|
|
|
if (i > 0){
|
|
|
|
if (tiff_transferfunctioncount != t2p->tiff_transferfunctioncount){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Different transfer function on page %d",
|
|
|
|
i);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t2p->tiff_transferfunctioncount = tiff_transferfunctioncount;
|
|
|
|
t2p->tiff_transferfunction[0] = tiff_transferfunction[0];
|
|
|
|
t2p->tiff_transferfunction[1] = tiff_transferfunction[1];
|
|
|
|
t2p->tiff_transferfunction[2] = tiff_transferfunction[2];
|
|
|
|
if(tiff_transferfunctioncount == 3){
|
|
|
|
t2p->tiff_pages[i].page_extra += 4;
|
|
|
|
t2p->pdf_xrefcount += 4;
|
|
|
|
if(t2p->pdf_minorversion < 2)
|
|
|
|
t2p->pdf_minorversion = 2;
|
|
|
|
} else if (tiff_transferfunctioncount == 1){
|
|
|
|
t2p->tiff_pages[i].page_extra += 2;
|
|
|
|
t2p->pdf_xrefcount += 2;
|
|
|
|
if(t2p->pdf_minorversion < 2)
|
|
|
|
t2p->pdf_minorversion = 2;
|
|
|
|
}
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
if( TIFFGetField(
|
|
|
|
input,
|
|
|
|
TIFFTAG_ICCPROFILE,
|
|
|
|
&(t2p->tiff_iccprofilelength),
|
|
|
|
&(t2p->tiff_iccprofile)) != 0){
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[i].page_extra++;
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xrefcount++;
|
|
|
|
if(t2p->pdf_minorversion<3){t2p->pdf_minorversion=3;}
|
|
|
|
}
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_tiles[i].tiles_tilecount=
|
|
|
|
t2p->tiff_pages[i].page_tilecount;
|
2003-11-25 11:39:22 -05:00
|
|
|
if( (TIFFGetField(input, TIFFTAG_PLANARCONFIG, &xuint16) != 0)
|
|
|
|
&& (xuint16 == PLANARCONFIG_SEPARATE ) ){
|
2014-12-21 12:36:36 -05:00
|
|
|
if( !TIFFGetField(input, TIFFTAG_SAMPLESPERPIXEL, &xuint16) )
|
|
|
|
{
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Missing SamplesPerPixel, %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2014-12-21 10:15:31 -05:00
|
|
|
if( (t2p->tiff_tiles[i].tiles_tilecount % xuint16) != 0 )
|
|
|
|
{
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Invalid tile count, %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_tiles[i].tiles_tilecount/= xuint16;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2003-12-01 05:51:39 -05:00
|
|
|
if( t2p->tiff_tiles[i].tiles_tilecount > 0){
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xrefcount +=
|
2003-12-01 05:51:39 -05:00
|
|
|
(t2p->tiff_tiles[i].tiles_tilecount -1)*2;
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFGetField(input,
|
|
|
|
TIFFTAG_TILEWIDTH,
|
2003-12-01 05:51:39 -05:00
|
|
|
&( t2p->tiff_tiles[i].tiles_tilewidth) );
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFGetField(input,
|
|
|
|
TIFFTAG_TILELENGTH,
|
2003-12-01 05:51:39 -05:00
|
|
|
&( t2p->tiff_tiles[i].tiles_tilelength) );
|
|
|
|
t2p->tiff_tiles[i].tiles_tiles =
|
2014-12-09 21:53:30 -05:00
|
|
|
(T2P_TILE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->tiff_tiles[i].tiles_tilecount,
|
|
|
|
sizeof(T2P_TILE)) );
|
2003-12-01 05:51:39 -05:00
|
|
|
if( t2p->tiff_tiles[i].tiles_tiles == NULL){
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2015-06-20 21:09:09 -04:00
|
|
|
"Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for t2p_read_tiff_init, %s",
|
|
|
|
(TIFF_SIZE_T) t2p->tiff_tiles[i].tiles_tilecount * sizeof(T2P_TILE),
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-02-24 11:28:48 -05:00
|
|
|
* This function is used by qsort to sort a T2P_PAGE* array of page structures
|
2014-10-20 13:52:05 -04:00
|
|
|
* by page number. If the page numbers are the same, we fall back to comparing
|
|
|
|
* directory numbers to preserve the order of the input file.
|
2007-02-24 11:28:48 -05:00
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
int t2p_cmp_t2p_page(const void* e1, const void* e2){
|
|
|
|
|
2014-10-20 13:52:05 -04:00
|
|
|
int d;
|
|
|
|
d = (int32)(((T2P_PAGE*)e1)->page_number) - (int32)(((T2P_PAGE*)e2)->page_number);
|
|
|
|
if(d == 0){
|
|
|
|
d = (int32)(((T2P_PAGE*)e1)->page_directory) - (int32)(((T2P_PAGE*)e2)->page_directory);
|
|
|
|
}
|
|
|
|
return d;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-23 08:00:30 -04:00
|
|
|
This function sets the input directory to the directory of a given
|
|
|
|
page and determines information about the image. It checks
|
|
|
|
the image characteristics to determine if it is possible to convert
|
|
|
|
the image data into a page of PDF output, setting values of the T2P
|
|
|
|
struct for this page. It determines what color space is used in
|
|
|
|
the output PDF to represent the image.
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2004-08-23 08:00:30 -04:00
|
|
|
It determines if the image can be converted as raw data without
|
|
|
|
requiring transcoding of the image data.
|
2003-11-25 11:39:22 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_read_tiff_data(T2P* t2p, TIFF* input){
|
|
|
|
|
|
|
|
int i=0;
|
2019-02-11 17:39:42 -05:00
|
|
|
uint16* r = NULL;
|
|
|
|
uint16* g = NULL;
|
|
|
|
uint16* b = NULL;
|
|
|
|
uint16* a = NULL;
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 xuint16;
|
|
|
|
uint16* xuint16p;
|
|
|
|
float* xfloatp;
|
|
|
|
|
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_ENCODE;
|
|
|
|
t2p->pdf_sample = T2P_SAMPLE_NOTHING;
|
2004-08-24 03:48:36 -04:00
|
|
|
t2p->pdf_switchdecode = t2p->pdf_colorspace_invert;
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
TIFFSetDirectory(input, t2p->tiff_pages[t2p->pdf_page].page_directory);
|
|
|
|
|
|
|
|
TIFFGetField(input, TIFFTAG_IMAGEWIDTH, &(t2p->tiff_width));
|
|
|
|
if(t2p->tiff_width == 0){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with zero width",
|
|
|
|
TIFFFileName(input) );
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TIFFGetField(input, TIFFTAG_IMAGELENGTH, &(t2p->tiff_length));
|
|
|
|
if(t2p->tiff_length == 0){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with zero length",
|
|
|
|
TIFFFileName(input) );
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-08-21 04:09:49 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_COMPRESSION, &(t2p->tiff_compression)) == 0){
|
2004-08-20 15:23:25 -04:00
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"No support for %s with no compression tag",
|
|
|
|
TIFFFileName(input) );
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
if( TIFFIsCODECConfigured(t2p->tiff_compression) == 0){
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with compression type %u: not configured",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_compression
|
|
|
|
);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TIFFGetFieldDefaulted(input, TIFFTAG_BITSPERSAMPLE, &(t2p->tiff_bitspersample));
|
|
|
|
switch(t2p->tiff_bitspersample){
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 4:
|
|
|
|
case 8:
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Image %s has 0 bits per sample, assuming 1",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->tiff_bitspersample=1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with %u bits per sample",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TIFFGetFieldDefaulted(input, TIFFTAG_SAMPLESPERPIXEL, &(t2p->tiff_samplesperpixel));
|
|
|
|
if(t2p->tiff_samplesperpixel>4){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with %u samples per pixel",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_samplesperpixel==0){
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Image %s has 0 samples per pixel, assuming 1",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->tiff_samplesperpixel=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(TIFFGetField(input, TIFFTAG_SAMPLEFORMAT, &xuint16) != 0 ){
|
|
|
|
switch(xuint16){
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 4:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with sample format %u",
|
|
|
|
TIFFFileName(input),
|
|
|
|
xuint16);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-23 08:00:30 -04:00
|
|
|
TIFFGetFieldDefaulted(input, TIFFTAG_FILLORDER, &(t2p->tiff_fillorder));
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2004-08-20 15:23:25 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_PHOTOMETRIC, &(t2p->tiff_photometric)) == 0){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"No support for %s with no photometric interpretation tag",
|
|
|
|
TIFFFileName(input) );
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
2004-08-24 03:48:36 -04:00
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
switch(t2p->tiff_photometric){
|
|
|
|
case PHOTOMETRIC_MINISWHITE:
|
|
|
|
case PHOTOMETRIC_MINISBLACK:
|
|
|
|
if (t2p->tiff_bitspersample==1){
|
|
|
|
t2p->pdf_colorspace=T2P_CS_BILEVEL;
|
|
|
|
if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){
|
2004-08-24 03:48:36 -04:00
|
|
|
t2p->pdf_switchdecode ^= 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t2p->pdf_colorspace=T2P_CS_GRAY;
|
|
|
|
if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){
|
2004-08-24 03:48:36 -04:00
|
|
|
t2p->pdf_switchdecode ^= 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_RGB:
|
|
|
|
t2p->pdf_colorspace=T2P_CS_RGB;
|
2005-03-18 04:47:34 -05:00
|
|
|
if(t2p->tiff_samplesperpixel == 3){
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)){
|
2005-03-18 04:47:34 -05:00
|
|
|
if(xuint16==1)
|
|
|
|
goto photometric_palette;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_samplesperpixel > 3) {
|
|
|
|
if(t2p->tiff_samplesperpixel == 4) {
|
|
|
|
t2p->pdf_colorspace = T2P_CS_RGB;
|
|
|
|
if(TIFFGetField(input,
|
|
|
|
TIFFTAG_EXTRASAMPLES,
|
|
|
|
&xuint16, &xuint16p)
|
|
|
|
&& xuint16 == 1) {
|
|
|
|
if(xuint16p[0] == EXTRASAMPLE_ASSOCALPHA){
|
2015-01-22 04:58:49 -05:00
|
|
|
if( t2p->tiff_bitspersample != 8 )
|
|
|
|
{
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"No support for BitsPerSample=%d for RGBA",
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_sample=T2P_SAMPLE_RGBAA_TO_RGB;
|
|
|
|
break;
|
|
|
|
}
|
2005-03-18 04:47:34 -05:00
|
|
|
if(xuint16p[0] == EXTRASAMPLE_UNASSALPHA){
|
2015-01-22 04:58:49 -05:00
|
|
|
if( t2p->tiff_bitspersample != 8 )
|
|
|
|
{
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"No support for BitsPerSample=%d for RGBA",
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_sample=T2P_SAMPLE_RGBA_TO_RGB;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"RGB image %s has 4 samples per pixel, assuming RGBA",
|
|
|
|
TIFFFileName(input));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
t2p->pdf_colorspace=T2P_CS_CMYK;
|
2004-08-24 03:48:36 -04:00
|
|
|
t2p->pdf_switchdecode ^= 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"RGB image %s has 4 samples per pixel, assuming inverse CMYK",
|
|
|
|
TIFFFileName(input));
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for RGB image %s with %u samples per pixel",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for RGB image %s with %u samples per pixel",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PHOTOMETRIC_PALETTE:
|
|
|
|
photometric_palette:
|
|
|
|
if(t2p->tiff_samplesperpixel!=1){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for palettized image %s with not one sample per pixel",
|
2008-12-31 18:48:01 -05:00
|
|
|
TIFFFileName(input));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
t2p->pdf_colorspace=T2P_CS_RGB | T2P_CS_PALETTE;
|
|
|
|
t2p->pdf_palettesize=0x0001<<t2p->tiff_bitspersample;
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_COLORMAP, &r, &g, &b)){
|
|
|
|
TIFFError(
|
2019-02-11 17:39:42 -05:00
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Palettized image %s has no color map",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
2019-02-11 17:39:42 -05:00
|
|
|
}
|
|
|
|
if(r == NULL || g == NULL || b == NULL){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Error getting 3 components from color map");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_palette != NULL){
|
|
|
|
_TIFFfree(t2p->pdf_palette);
|
|
|
|
t2p->pdf_palette=NULL;
|
|
|
|
}
|
2004-08-20 15:23:25 -04:00
|
|
|
t2p->pdf_palette = (unsigned char*)
|
2014-12-09 21:53:30 -05:00
|
|
|
_TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,3));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_palette==NULL){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Can't allocate %u bytes of memory for t2p_read_tiff_image, %s",
|
|
|
|
t2p->pdf_palettesize,
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(i=0;i<t2p->pdf_palettesize;i++){
|
|
|
|
t2p->pdf_palette[(i*3)] = (unsigned char) (r[i]>>8);
|
|
|
|
t2p->pdf_palette[(i*3)+1]= (unsigned char) (g[i]>>8);
|
|
|
|
t2p->pdf_palette[(i*3)+2]= (unsigned char) (b[i]>>8);
|
|
|
|
}
|
|
|
|
t2p->pdf_palettesize *= 3;
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_SEPARATED:
|
|
|
|
if(TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)){
|
|
|
|
if(xuint16==1){
|
|
|
|
goto photometric_palette_cmyk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( TIFFGetField(input, TIFFTAG_INKSET, &xuint16) ){
|
|
|
|
if(xuint16 != INKSET_CMYK){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s because its inkset is not CMYK",
|
|
|
|
TIFFFileName(input) );
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->tiff_samplesperpixel==4){
|
|
|
|
t2p->pdf_colorspace=T2P_CS_CMYK;
|
|
|
|
} else {
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s because it has %u samples per pixel",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
photometric_palette_cmyk:
|
|
|
|
if(t2p->tiff_samplesperpixel!=1){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for palettized CMYK image %s with not one sample per pixel",
|
2008-12-31 18:48:01 -05:00
|
|
|
TIFFFileName(input));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
t2p->pdf_colorspace=T2P_CS_CMYK | T2P_CS_PALETTE;
|
|
|
|
t2p->pdf_palettesize=0x0001<<t2p->tiff_bitspersample;
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_COLORMAP, &r, &g, &b, &a)){
|
|
|
|
TIFFError(
|
2019-02-11 17:39:42 -05:00
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Palettized image %s has no color map",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
2019-02-11 17:39:42 -05:00
|
|
|
}
|
|
|
|
if(r == NULL || g == NULL || b == NULL || a == NULL){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Error getting 4 components from color map");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_palette != NULL){
|
|
|
|
_TIFFfree(t2p->pdf_palette);
|
|
|
|
t2p->pdf_palette=NULL;
|
|
|
|
}
|
2004-08-20 15:23:25 -04:00
|
|
|
t2p->pdf_palette = (unsigned char*)
|
2014-12-09 21:53:30 -05:00
|
|
|
_TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,4));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_palette==NULL){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Can't allocate %u bytes of memory for t2p_read_tiff_image, %s",
|
|
|
|
t2p->pdf_palettesize,
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(i=0;i<t2p->pdf_palettesize;i++){
|
|
|
|
t2p->pdf_palette[(i*4)] = (unsigned char) (r[i]>>8);
|
|
|
|
t2p->pdf_palette[(i*4)+1]= (unsigned char) (g[i]>>8);
|
|
|
|
t2p->pdf_palette[(i*4)+2]= (unsigned char) (b[i]>>8);
|
2007-10-05 12:30:18 -04:00
|
|
|
t2p->pdf_palette[(i*4)+3]= (unsigned char) (a[i]>>8);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
t2p->pdf_palettesize *= 4;
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_YCBCR:
|
|
|
|
t2p->pdf_colorspace=T2P_CS_RGB;
|
|
|
|
if(t2p->tiff_samplesperpixel==1){
|
|
|
|
t2p->pdf_colorspace=T2P_CS_GRAY;
|
|
|
|
t2p->tiff_photometric=PHOTOMETRIC_MINISBLACK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
t2p->pdf_sample=T2P_SAMPLE_YCBCR_TO_RGB;
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){
|
|
|
|
t2p->pdf_sample=T2P_SAMPLE_NOTHING;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_CIELAB:
|
2014-12-21 10:15:31 -05:00
|
|
|
if( t2p->tiff_samplesperpixel != 3){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Unsupported samplesperpixel = %d for CIELAB",
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( t2p->tiff_bitspersample != 8){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Invalid bitspersample = %d for CIELAB",
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_labrange[0]= -127;
|
|
|
|
t2p->pdf_labrange[1]= 127;
|
|
|
|
t2p->pdf_labrange[2]= -127;
|
|
|
|
t2p->pdf_labrange[3]= 127;
|
|
|
|
t2p->pdf_sample=T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED;
|
|
|
|
t2p->pdf_colorspace=T2P_CS_LAB;
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_ICCLAB:
|
|
|
|
t2p->pdf_labrange[0]= 0;
|
|
|
|
t2p->pdf_labrange[1]= 255;
|
|
|
|
t2p->pdf_labrange[2]= 0;
|
|
|
|
t2p->pdf_labrange[3]= 255;
|
|
|
|
t2p->pdf_colorspace=T2P_CS_LAB;
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_ITULAB:
|
2014-12-21 10:15:31 -05:00
|
|
|
if( t2p->tiff_samplesperpixel != 3){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Unsupported samplesperpixel = %d for ITULAB",
|
|
|
|
t2p->tiff_samplesperpixel);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( t2p->tiff_bitspersample != 8){
|
|
|
|
TIFFError(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Invalid bitspersample = %d for ITULAB",
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_labrange[0]=-85;
|
|
|
|
t2p->pdf_labrange[1]=85;
|
|
|
|
t2p->pdf_labrange[2]=-75;
|
|
|
|
t2p->pdf_labrange[3]=124;
|
|
|
|
t2p->pdf_sample=T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED;
|
|
|
|
t2p->pdf_colorspace=T2P_CS_LAB;
|
|
|
|
break;
|
|
|
|
case PHOTOMETRIC_LOGL:
|
|
|
|
case PHOTOMETRIC_LOGLUV:
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with photometric interpretation LogL/LogLuv",
|
2008-12-31 18:48:01 -05:00
|
|
|
TIFFFileName(input));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with photometric interpretation %u",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_photometric);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(TIFFGetField(input, TIFFTAG_PLANARCONFIG, &(t2p->tiff_planar))){
|
|
|
|
switch(t2p->tiff_planar){
|
|
|
|
case 0:
|
|
|
|
TIFFWarning(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Image %s has planar configuration 0, assuming 1",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->tiff_planar=PLANARCONFIG_CONTIG;
|
|
|
|
case PLANARCONFIG_CONTIG:
|
|
|
|
break;
|
|
|
|
case PLANARCONFIG_SEPARATE:
|
|
|
|
t2p->pdf_sample=T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG;
|
|
|
|
if(t2p->tiff_bitspersample!=8){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with separated planar configuration and %u bits per sample",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_bitspersample);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with planar configuration %u",
|
|
|
|
TIFFFileName(input),
|
|
|
|
t2p->tiff_planar);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-23 08:00:30 -04:00
|
|
|
TIFFGetFieldDefaulted(input, TIFFTAG_ORIENTATION,
|
|
|
|
&(t2p->tiff_orientation));
|
|
|
|
if(t2p->tiff_orientation>8){
|
|
|
|
TIFFWarning(TIFF2PDF_MODULE,
|
|
|
|
"Image %s has orientation %u, assuming 0",
|
|
|
|
TIFFFileName(input), t2p->tiff_orientation);
|
2004-08-20 15:23:25 -04:00
|
|
|
t2p->tiff_orientation=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(TIFFGetField(input, TIFFTAG_XRESOLUTION, &(t2p->tiff_xres) ) == 0){
|
|
|
|
t2p->tiff_xres=0.0;
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_YRESOLUTION, &(t2p->tiff_yres) ) == 0){
|
|
|
|
t2p->tiff_yres=0.0;
|
|
|
|
}
|
2007-02-24 11:28:48 -05:00
|
|
|
TIFFGetFieldDefaulted(input, TIFFTAG_RESOLUTIONUNIT,
|
|
|
|
&(t2p->tiff_resunit));
|
|
|
|
if(t2p->tiff_resunit == RESUNIT_CENTIMETER) {
|
|
|
|
t2p->tiff_xres *= 2.54F;
|
|
|
|
t2p->tiff_yres *= 2.54F;
|
|
|
|
} else if (t2p->tiff_resunit != RESUNIT_INCH
|
|
|
|
&& t2p->pdf_centimeters != 0) {
|
|
|
|
t2p->tiff_xres *= 2.54F;
|
|
|
|
t2p->tiff_yres *= 2.54F;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
t2p_compose_pdf_page(t2p);
|
2015-01-22 04:58:49 -05:00
|
|
|
if( t2p->t2p_error == T2P_ERR_ERROR )
|
|
|
|
return;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_ENCODE;
|
2017-07-15 07:13:46 -04:00
|
|
|
/* It seems that T2P_TRANSCODE_RAW mode doesn't support separate->contig */
|
|
|
|
/* conversion. At least t2p_read_tiff_size and t2p_read_tiff_size_tile */
|
|
|
|
/* do not take into account the number of samples, and thus */
|
|
|
|
/* that can cause heap buffer overflows such as in */
|
|
|
|
/* http://bugzilla.maptools.org/show_bug.cgi?id=2715 */
|
|
|
|
if(t2p->pdf_nopassthrough==0 && t2p->tiff_planar!=PLANARCONFIG_SEPARATE){
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_CCITTFAX4
|
|
|
|
){
|
|
|
|
if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){
|
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_RAW;
|
|
|
|
t2p->pdf_compression=T2P_COMPRESS_G4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
if(t2p->tiff_compression== COMPRESSION_ADOBE_DEFLATE
|
|
|
|
|| t2p->tiff_compression==COMPRESSION_DEFLATE){
|
|
|
|
if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){
|
2020-03-26 19:31:59 -04:00
|
|
|
uint16 predictor;
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_RAW;
|
|
|
|
t2p->pdf_compression=T2P_COMPRESS_ZIP;
|
2020-03-26 19:31:59 -04:00
|
|
|
TIFFGetField(input, TIFFTAG_PREDICTOR, &predictor);
|
|
|
|
t2p->pdf_compressionquality = predictor;
|
|
|
|
/* TIFFTAG_ZIPQUALITY is always Z_DEFAULT_COMPRESSION on reading */
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_OJPEG){
|
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_RAW;
|
|
|
|
t2p->pdf_compression=T2P_COMPRESS_JPEG;
|
|
|
|
t2p_process_ojpeg_tables(t2p, input);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_JPEG){
|
|
|
|
t2p->pdf_transcode = T2P_TRANSCODE_RAW;
|
|
|
|
t2p->pdf_compression=T2P_COMPRESS_JPEG;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_transcode!=T2P_TRANSCODE_RAW){
|
|
|
|
t2p->pdf_compression = t2p->pdf_defaultcompression;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_PALETTE){
|
|
|
|
t2p->pdf_sample|=T2P_SAMPLE_REALIZE_PALETTE;
|
2003-11-29 10:32:40 -05:00
|
|
|
t2p->pdf_colorspace ^= T2P_CS_PALETTE;
|
2003-12-01 05:51:39 -05:00
|
|
|
t2p->tiff_pages[t2p->pdf_page].page_extra--;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_JPEG){
|
|
|
|
if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with JPEG compression and separated planar configuration",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_OJPEG){
|
|
|
|
if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"No support for %s with OJPEG compression and separated planar configuration",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_REALIZE_PALETTE){
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CMYK){
|
|
|
|
t2p->tiff_samplesperpixel=4;
|
|
|
|
t2p->tiff_photometric=PHOTOMETRIC_SEPARATED;
|
|
|
|
} else {
|
|
|
|
t2p->tiff_samplesperpixel=3;
|
|
|
|
t2p->tiff_photometric=PHOTOMETRIC_RGB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-10 07:50:57 -04:00
|
|
|
if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION,
|
|
|
|
&(t2p->tiff_transferfunction[0]),
|
|
|
|
&(t2p->tiff_transferfunction[1]),
|
|
|
|
&(t2p->tiff_transferfunction[2]))) {
|
2017-12-06 15:49:20 -05:00
|
|
|
if((t2p->tiff_transferfunction[1] != (uint16*) NULL) &&
|
|
|
|
(t2p->tiff_transferfunction[2] != (uint16*) NULL)
|
tiff2pdf: Fix CVE-2017-9935
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
This vulnerability - at least for the supplied test case - is because we
assume that a tiff will only have one transfer function that is the same
for all pages. This is not required by the TIFF standards.
We than read the transfer function for every page. Depending on the
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
We allocate this memory after we read in the transfer function for the
page.
For the first exploit - POC1, this file has 3 pages. For the first page
we allocate 2 extra extra XREF entries. Then for the next page 2 more
entries. Then for the last page the transfer function changes and we
allocate 4 more entries.
When we read the file into memory, we assume we have 4 bytes extra for
each and every page (as per the last transfer function we read). Which
is not correct, we only have 2 bytes extra for the first 2 pages. As a
result, we end up writing past the end of the buffer.
There are also some related issues that this also fixes. For example,
TIFFGetField can return uninitalized pointer values, and the logic to
detect a N=3 vs N=1 transfer function seemed rather strange.
It is also strange that we declare the transfer functions to be of type
float, when the standard says they are unsigned 16 bit values. This is
fixed in another patch.
This patch will check to ensure that the N value for every transfer
function is the same for every page. If this changes, we abort with an
error. In theory, we should perhaps check that the transfer function
itself is identical for every page, however we don't do that due to the
confusion of the type of the data in the transfer function.
2017-12-06 15:46:47 -05:00
|
|
|
) {
|
2004-09-10 07:50:57 -04:00
|
|
|
t2p->tiff_transferfunctioncount=3;
|
2004-10-09 10:15:07 -04:00
|
|
|
} else {
|
|
|
|
t2p->tiff_transferfunctioncount=1;
|
2004-09-10 07:50:57 -04:00
|
|
|
}
|
2004-10-09 10:15:07 -04:00
|
|
|
} else {
|
|
|
|
t2p->tiff_transferfunctioncount=0;
|
2004-09-10 07:50:57 -04:00
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if(TIFFGetField(input, TIFFTAG_WHITEPOINT, &xfloatp)!=0){
|
|
|
|
t2p->tiff_whitechromaticities[0]=xfloatp[0];
|
|
|
|
t2p->tiff_whitechromaticities[1]=xfloatp[1];
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_GRAY){
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_CALGRAY;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_RGB){
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_CALRGB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_PRIMARYCHROMATICITIES, &xfloatp)!=0){
|
|
|
|
t2p->tiff_primarychromaticities[0]=xfloatp[0];
|
|
|
|
t2p->tiff_primarychromaticities[1]=xfloatp[1];
|
|
|
|
t2p->tiff_primarychromaticities[2]=xfloatp[2];
|
|
|
|
t2p->tiff_primarychromaticities[3]=xfloatp[3];
|
|
|
|
t2p->tiff_primarychromaticities[4]=xfloatp[4];
|
|
|
|
t2p->tiff_primarychromaticities[5]=xfloatp[5];
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_RGB){
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_CALRGB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_LAB){
|
|
|
|
if(TIFFGetField(input, TIFFTAG_WHITEPOINT, &xfloatp) != 0){
|
|
|
|
t2p->tiff_whitechromaticities[0]=xfloatp[0];
|
|
|
|
t2p->tiff_whitechromaticities[1]=xfloatp[1];
|
|
|
|
} else {
|
2004-05-26 05:24:07 -04:00
|
|
|
t2p->tiff_whitechromaticities[0]=0.3457F; /* 0.3127F; */
|
|
|
|
t2p->tiff_whitechromaticities[1]=0.3585F; /* 0.3290F; */
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input,
|
|
|
|
TIFFTAG_ICCPROFILE,
|
|
|
|
&(t2p->tiff_iccprofilelength),
|
|
|
|
&(t2p->tiff_iccprofile))!=0){
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_ICCBASED;
|
|
|
|
} else {
|
|
|
|
t2p->tiff_iccprofilelength=0;
|
|
|
|
t2p->tiff_iccprofile=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
if( t2p->tiff_bitspersample==1 &&
|
|
|
|
t2p->tiff_samplesperpixel==1){
|
|
|
|
t2p->pdf_compression = T2P_COMPRESS_G4;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function returns the necessary size of a data buffer to contain the raw or
|
|
|
|
uncompressed image data from the input TIFF for a page.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_read_tiff_size(T2P* t2p, TIFF* input){
|
|
|
|
|
2008-12-30 22:06:27 -05:00
|
|
|
uint64* sbc=NULL;
|
2003-11-25 11:39:22 -05:00
|
|
|
#if defined(JPEG_SUPPORT) || defined (OJPEG_SUPPORT)
|
|
|
|
unsigned char* jpt=NULL;
|
|
|
|
tstrip_t i=0;
|
|
|
|
tstrip_t stripcount=0;
|
|
|
|
#endif
|
2012-06-15 17:44:31 -04:00
|
|
|
uint64 k = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_G4 ){
|
|
|
|
TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc);
|
2016-11-11 16:15:25 -05:00
|
|
|
if (sbc[0] != (uint64)(tmsize_t)sbc[0]) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2009-01-22 16:12:45 -05:00
|
|
|
t2p->tiff_datasize=(tmsize_t)sbc[0];
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_ZIP){
|
|
|
|
TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc);
|
2016-11-11 16:15:25 -05:00
|
|
|
if (sbc[0] != (uint64)(tmsize_t)sbc[0]) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2009-01-22 16:12:45 -05:00
|
|
|
t2p->tiff_datasize=(tmsize_t)sbc[0];
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression == COMPRESSION_OJPEG){
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Input file %s missing field: TIFFTAG_STRIPBYTECOUNTS",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
for(i=0;i<stripcount;i++){
|
2012-06-15 17:44:31 -04:00
|
|
|
k = checkAdd64(k, sbc[i], t2p);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_JPEGIFOFFSET, &(t2p->tiff_dataoffset))){
|
|
|
|
if(t2p->tiff_dataoffset != 0){
|
|
|
|
if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){
|
2012-06-15 17:44:31 -04:00
|
|
|
if((uint64)t2p->tiff_datasize < k) {
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFWarning(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Input file %s has short JPEG interchange file byte count",
|
|
|
|
TIFFFileName(input));
|
2012-06-15 17:44:31 -04:00
|
|
|
t2p->pdf_ojpegiflength=t2p->tiff_datasize;
|
|
|
|
k = checkAdd64(k, t2p->tiff_datasize, t2p);
|
|
|
|
k = checkAdd64(k, 6, t2p);
|
|
|
|
k = checkAdd64(k, stripcount, t2p);
|
|
|
|
k = checkAdd64(k, stripcount, t2p);
|
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}else {
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Input file %s missing field: TIFFTAG_JPEGIFBYTECOUNT",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-15 17:44:31 -04:00
|
|
|
k = checkAdd64(k, stripcount, t2p);
|
|
|
|
k = checkAdd64(k, stripcount, t2p);
|
|
|
|
k = checkAdd64(k, 2048, t2p);
|
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
2007-07-03 11:47:05 -04:00
|
|
|
if(t2p->tiff_compression == COMPRESSION_JPEG) {
|
|
|
|
uint32 count = 0;
|
|
|
|
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0 ){
|
|
|
|
if(count > 4){
|
2012-06-15 17:44:31 -04:00
|
|
|
k += count;
|
|
|
|
k -= 2; /* don't use EOI of header */
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
} else {
|
2012-06-15 17:44:31 -04:00
|
|
|
k = 2; /* SOI for first strip */
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Input file %s missing field: TIFFTAG_STRIPBYTECOUNTS",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(i=0;i<stripcount;i++){
|
2012-06-15 17:44:31 -04:00
|
|
|
k = checkAdd64(k, sbc[i], t2p);
|
2014-12-24 11:32:28 -05:00
|
|
|
k -=2; /* don't use EOI of strip */
|
|
|
|
k +=2; /* add space for restart marker */
|
2012-06-15 17:44:31 -04:00
|
|
|
}
|
|
|
|
k = checkAdd64(k, 2, t2p); /* use EOI of last strip */
|
2014-12-24 11:32:28 -05:00
|
|
|
k = checkAdd64(k, 6, t2p); /* for DRI marker of first strip */
|
2012-06-15 17:44:31 -04:00
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2010-06-13 15:25:54 -04:00
|
|
|
return;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
(void) 0;
|
|
|
|
}
|
2020-11-14 07:53:01 -05:00
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_JPEG
|
|
|
|
&& t2p->tiff_photometric == PHOTOMETRIC_YCBCR) {
|
|
|
|
k = checkMultiply64(TIFFNumberOfStrips(input), TIFFStripSize(input), t2p);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
k = checkMultiply64(TIFFScanlineSize(input), t2p->tiff_length, t2p);
|
|
|
|
if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
|
|
|
|
k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
|
|
|
|
}
|
2012-06-15 17:44:31 -04:00
|
|
|
}
|
|
|
|
if (k == 0) {
|
|
|
|
/* Assume we had overflow inside TIFFScanlineSize */
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function returns the necessary size of a data buffer to contain the raw or
|
|
|
|
uncompressed image data from the input TIFF for a tile of a page.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){
|
|
|
|
|
2008-12-30 22:06:27 -05:00
|
|
|
uint64* tbc = NULL;
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 edge=0;
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
unsigned char* jpt;
|
|
|
|
#endif
|
2012-06-15 17:44:31 -04:00
|
|
|
uint64 k;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
|
|
|
|
edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
|
|
|
|
|
|
|
|
if(t2p->pdf_transcode==T2P_TRANSCODE_RAW){
|
|
|
|
if(edge
|
|
|
|
#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT)
|
|
|
|
&& !(t2p->pdf_compression==T2P_COMPRESS_JPEG)
|
|
|
|
#endif
|
|
|
|
){
|
|
|
|
t2p->tiff_datasize=TIFFTileSize(input);
|
2012-06-15 17:44:31 -04:00
|
|
|
if (t2p->tiff_datasize == 0) {
|
|
|
|
/* Assume we had overflow inside TIFFTileSize */
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
TIFFGetField(input, TIFFTAG_TILEBYTECOUNTS, &tbc);
|
2012-06-15 17:44:31 -04:00
|
|
|
k=tbc[tile];
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression==COMPRESSION_OJPEG){
|
2020-04-04 18:13:13 -04:00
|
|
|
k = checkAdd64(k, 2048, t2p);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
2007-07-03 11:47:05 -04:00
|
|
|
if(t2p->tiff_compression==COMPRESSION_JPEG) {
|
|
|
|
uint32 count = 0;
|
|
|
|
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){
|
|
|
|
if(count > 4){
|
2012-06-15 17:44:31 -04:00
|
|
|
k = checkAdd64(k, count, t2p);
|
|
|
|
k -= 2; /* don't use EOI of header or SOI of tile */
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2012-06-15 17:44:31 -04:00
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2012-06-15 17:44:31 -04:00
|
|
|
k = TIFFTileSize(input);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
|
2012-06-15 17:44:31 -04:00
|
|
|
k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
|
|
|
|
}
|
|
|
|
if (k == 0) {
|
|
|
|
/* Assume we had overflow inside TIFFTileSize */
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
t2p->tiff_datasize = (tsize_t) k;
|
|
|
|
if ((uint64) t2p->tiff_datasize != k) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-04-18 04:46:33 -04:00
|
|
|
* This functions returns a non-zero value when the tile is on the right edge
|
|
|
|
* and does not have full imaged tile width.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){
|
|
|
|
|
|
|
|
if( ((tile+1) % tiles.tiles_tilecountx == 0)
|
|
|
|
&& (tiles.tiles_edgetilewidth != 0) ){
|
|
|
|
return(1);
|
|
|
|
} else {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-29 10:32:40 -05:00
|
|
|
/*
|
2007-04-18 04:46:33 -04:00
|
|
|
* This functions returns a non-zero value when the tile is on the bottom edge
|
|
|
|
* and does not have full imaged tile length.
|
|
|
|
*/
|
2003-11-29 10:32:40 -05:00
|
|
|
|
|
|
|
int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){
|
|
|
|
|
|
|
|
if( ((tile+1) > (tiles.tiles_tilecount-tiles.tiles_tilecountx) )
|
|
|
|
&& (tiles.tiles_edgetilelength != 0) ){
|
|
|
|
return(1);
|
|
|
|
} else {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
/*
|
2007-04-18 04:46:33 -04:00
|
|
|
* This function returns a non-zero value when the tile is a right edge tile
|
|
|
|
* or a bottom edge tile.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
int t2p_tile_is_edge(T2P_TILES tiles, ttile_t tile){
|
|
|
|
|
|
|
|
return(t2p_tile_is_right_edge(tiles, tile) | t2p_tile_is_bottom_edge(tiles, tile) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function returns a non-zero value when the tile is a right edge tile and a bottom
|
|
|
|
edge tile.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int t2p_tile_is_corner_edge(T2P_TILES tiles, ttile_t tile){
|
|
|
|
|
|
|
|
return(t2p_tile_is_right_edge(tiles, tile) & t2p_tile_is_bottom_edge(tiles, tile) );
|
|
|
|
}
|
|
|
|
|
2020-11-09 20:35:13 -05:00
|
|
|
#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT)
|
|
|
|
static const unsigned char jpeg_eof_marker[] = { 0xff, 0xd9 };
|
|
|
|
#endif
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
This function reads the raster image data from the input TIFF for an image and writes
|
|
|
|
the data to the output PDF XObject image dictionary stream. It returns the amount written
|
|
|
|
or zero on error.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
unsigned char* buffer=NULL;
|
|
|
|
unsigned char* samplebuffer=NULL;
|
|
|
|
tsize_t bufferoffset=0;
|
|
|
|
tsize_t samplebufferoffset=0;
|
|
|
|
tsize_t read=0;
|
|
|
|
tstrip_t i=0;
|
|
|
|
tstrip_t j=0;
|
|
|
|
tstrip_t stripcount=0;
|
|
|
|
tsize_t stripsize=0;
|
|
|
|
tsize_t sepstripcount=0;
|
|
|
|
tsize_t sepstripsize=0;
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
toff_t inputoffset=0;
|
|
|
|
uint16 h_samp=1;
|
|
|
|
uint16 v_samp=1;
|
|
|
|
uint16 ri=1;
|
|
|
|
uint32 rows=0;
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef OJPEG_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
unsigned char* jpt;
|
|
|
|
float* xfloatp;
|
2008-12-30 22:06:27 -05:00
|
|
|
uint64* sbc;
|
2003-11-25 11:39:22 -05:00
|
|
|
unsigned char* stripbuffer;
|
2004-08-20 15:23:25 -04:00
|
|
|
tsize_t striplength=0;
|
2003-11-25 11:39:22 -05:00
|
|
|
uint32 max_striplength=0;
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef JPEG_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2012-06-15 17:44:31 -04:00
|
|
|
/* Fail if prior error (in particular, can't trust tiff_datasize) */
|
|
|
|
if (t2p->t2p_error != T2P_ERR_OK)
|
|
|
|
return(0);
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_G4){
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if (buffer == NULL) {
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for "
|
|
|
|
"t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (TIFFReadRawStrip(input, 0, (tdata_t) buffer,
|
|
|
|
t2p->tiff_datasize) < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"TIFFReadRawStrip() failed");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){
|
2006-06-08 07:27:11 -04:00
|
|
|
/*
|
|
|
|
* make sure is lsb-to-msb
|
|
|
|
* bit-endianness fill order
|
|
|
|
*/
|
|
|
|
TIFFReverseBits(buffer,
|
|
|
|
t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(t2p->tiff_datasize);
|
|
|
|
}
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef CCITT_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef ZIP_SUPPORT
|
2006-06-08 07:27:11 -04:00
|
|
|
if (t2p->pdf_compression == T2P_COMPRESS_ZIP) {
|
|
|
|
buffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer == NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (TIFFReadRawStrip(input, 0, (tdata_t) buffer,
|
|
|
|
t2p->tiff_datasize) < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"TIFFReadRawStrip() failed");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(0);
|
|
|
|
}
|
2006-06-08 07:27:11 -04:00
|
|
|
if (t2p->tiff_fillorder==FILLORDER_LSB2MSB) {
|
|
|
|
TIFFReverseBits(buffer,
|
|
|
|
t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(t2p->tiff_datasize);
|
|
|
|
}
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef ZIP_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef OJPEG_SUPPORT
|
2006-06-08 07:27:11 -04:00
|
|
|
if(t2p->tiff_compression == COMPRESSION_OJPEG) {
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2006-06-08 07:27:11 -04:00
|
|
|
if(t2p->tiff_dataoffset != 0) {
|
|
|
|
buffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer == NULL) {
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_ojpegiflength==0){
|
2007-07-03 11:47:05 -04:00
|
|
|
inputoffset=t2pSeekFile(input, 0,
|
2006-06-08 07:27:11 -04:00
|
|
|
SEEK_CUR);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pSeekFile(input,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_dataoffset,
|
|
|
|
SEEK_SET);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pReadFile(input, (tdata_t) buffer,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_datasize);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pSeekFile(input, inputoffset,
|
2006-06-08 07:27:11 -04:00
|
|
|
SEEK_SET);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(t2p->tiff_datasize);
|
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
inputoffset=t2pSeekFile(input, 0,
|
2006-06-08 07:27:11 -04:00
|
|
|
SEEK_CUR);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pSeekFile(input,
|
2006-06-08 07:27:11 -04:00
|
|
|
t2p->tiff_dataoffset,
|
|
|
|
SEEK_SET);
|
2007-07-03 11:47:05 -04:00
|
|
|
bufferoffset = t2pReadFile(input,
|
2006-06-08 07:27:11 -04:00
|
|
|
(tdata_t) buffer,
|
|
|
|
t2p->pdf_ojpegiflength);
|
|
|
|
t2p->pdf_ojpegiflength = 0;
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pSeekFile(input, inputoffset,
|
2006-06-08 07:27:11 -04:00
|
|
|
SEEK_SET);
|
|
|
|
TIFFGetField(input,
|
|
|
|
TIFFTAG_YCBCRSUBSAMPLING,
|
|
|
|
&h_samp, &v_samp);
|
2003-11-25 11:39:22 -05:00
|
|
|
buffer[bufferoffset++]= 0xff;
|
|
|
|
buffer[bufferoffset++]= 0xdd;
|
|
|
|
buffer[bufferoffset++]= 0x00;
|
|
|
|
buffer[bufferoffset++]= 0x04;
|
|
|
|
h_samp*=8;
|
|
|
|
v_samp*=8;
|
|
|
|
ri=(t2p->tiff_width+h_samp-1) / h_samp;
|
2006-06-08 07:27:11 -04:00
|
|
|
TIFFGetField(input,
|
|
|
|
TIFFTAG_ROWSPERSTRIP,
|
|
|
|
&rows);
|
2003-11-25 11:39:22 -05:00
|
|
|
ri*=(rows+v_samp-1)/v_samp;
|
|
|
|
buffer[bufferoffset++]= (ri>>8) & 0xff;
|
|
|
|
buffer[bufferoffset++]= ri & 0xff;
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
if(i != 0 ){
|
|
|
|
buffer[bufferoffset++]=0xff;
|
|
|
|
buffer[bufferoffset++]=(0xd0 | ((i-1)%8));
|
|
|
|
}
|
|
|
|
bufferoffset+=TIFFReadRawStrip(input,
|
|
|
|
i,
|
|
|
|
(tdata_t) &(((unsigned char*)buffer)[bufferoffset]),
|
|
|
|
-1);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, bufferoffset);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(bufferoffset);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(! t2p->pdf_ojpegdata){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"No support for OJPEG image %s with bad tables",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFmemcpy(buffer, t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength);
|
|
|
|
bufferoffset=t2p->pdf_ojpegdatalength;
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
for(i=0;i<stripcount;i++){
|
2020-04-19 17:39:59 -04:00
|
|
|
tsize_t retTIFFReadRawStrip;
|
2003-11-25 11:39:22 -05:00
|
|
|
if(i != 0){
|
|
|
|
buffer[bufferoffset++]=0xff;
|
|
|
|
buffer[bufferoffset++]=(0xd0 | ((i-1)%8));
|
|
|
|
}
|
2020-04-19 17:39:59 -04:00
|
|
|
retTIFFReadRawStrip = TIFFReadRawStrip(input,
|
2003-11-25 11:39:22 -05:00
|
|
|
i,
|
|
|
|
(tdata_t) &(((unsigned char*)buffer)[bufferoffset]),
|
|
|
|
-1);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (retTIFFReadRawStrip < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "TIFFReadRawStrip()");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
bufferoffset += retTIFFReadRawStrip;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2020-11-09 20:35:13 -05:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, bufferoffset);
|
2003-11-25 11:39:22 -05:00
|
|
|
if( ! ( (buffer[bufferoffset-1]==0xd9) && (buffer[bufferoffset-2]==0xff) ) ){
|
2020-11-09 20:35:13 -05:00
|
|
|
t2pWriteFile(output, (tdata_t) jpeg_eof_marker, sizeof(jpeg_eof_marker));
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(bufferoffset);
|
2015-05-30 13:07:53 -04:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
This hunk of code removed code is clearly
|
|
|
|
mis-placed and we are not sure where it
|
|
|
|
should be (if anywhere)
|
|
|
|
*/
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2006-06-08 07:27:11 -04:00
|
|
|
"No support for OJPEG image %s with no JPEG File Interchange offset",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef OJPEG_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef JPEG_SUPPORT
|
2007-07-03 11:47:05 -04:00
|
|
|
if(t2p->tiff_compression == COMPRESSION_JPEG) {
|
|
|
|
uint32 count = 0;
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2007-07-03 11:47:05 -04:00
|
|
|
if (TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) {
|
|
|
|
if(count > 4) {
|
|
|
|
_TIFFmemcpy(buffer, jpt, count);
|
|
|
|
bufferoffset += count - 2;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc);
|
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
if(sbc[i]>max_striplength) max_striplength=sbc[i];
|
|
|
|
}
|
2006-06-08 07:27:11 -04:00
|
|
|
stripbuffer = (unsigned char*)
|
|
|
|
_TIFFmalloc(max_striplength);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(stripbuffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
max_striplength,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(stripbuffer, 0, max_striplength);
|
2003-11-25 11:39:22 -05:00
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
striplength=TIFFReadRawStrip(input, i, (tdata_t) stripbuffer, -1);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (striplength < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "TIFFReadRawStrip() failed");
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if(!t2p_process_jpeg_strip(
|
|
|
|
stripbuffer,
|
|
|
|
&striplength,
|
2016-09-23 18:12:18 -04:00
|
|
|
buffer,
|
|
|
|
t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
&bufferoffset,
|
|
|
|
i,
|
|
|
|
t2p->tiff_length)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2006-06-08 07:27:11 -04:00
|
|
|
"Can't process JPEG data in input file %s",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, bufferoffset);
|
2020-11-09 20:35:13 -05:00
|
|
|
t2pWriteFile(output, (tdata_t) jpeg_eof_marker, sizeof(jpeg_eof_marker));
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(stripbuffer);
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(bufferoffset);
|
|
|
|
}
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef JPEG_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample==T2P_SAMPLE_NOTHING){
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
stripsize=TIFFStripSize(input);
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
read =
|
|
|
|
TIFFReadEncodedStrip(input,
|
|
|
|
i,
|
|
|
|
(tdata_t) &buffer[bufferoffset],
|
2014-12-24 10:38:11 -05:00
|
|
|
TIFFmin(stripsize, t2p->tiff_datasize - bufferoffset));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(read==-1){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Error on decoding strip %u of %s",
|
|
|
|
i,
|
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
bufferoffset+=read;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
|
|
|
|
|
|
|
|
sepstripsize=TIFFStripSize(input);
|
|
|
|
sepstripcount=TIFFNumberOfStrips(input);
|
|
|
|
|
|
|
|
stripsize=sepstripsize*t2p->tiff_samplesperpixel;
|
|
|
|
stripcount=sepstripcount/t2p->tiff_samplesperpixel;
|
|
|
|
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
samplebuffer = (unsigned char*) _TIFFmalloc(stripsize);
|
|
|
|
if(samplebuffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2015-05-30 11:33:54 -04:00
|
|
|
_TIFFfree(buffer);
|
2003-11-25 11:39:22 -05:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
samplebufferoffset=0;
|
|
|
|
for(j=0;j<t2p->tiff_samplesperpixel;j++){
|
|
|
|
read =
|
|
|
|
TIFFReadEncodedStrip(input,
|
|
|
|
i + j*stripcount,
|
|
|
|
(tdata_t) &(samplebuffer[samplebufferoffset]),
|
2014-12-24 10:38:11 -05:00
|
|
|
TIFFmin(sepstripsize, stripsize - samplebufferoffset));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(read==-1){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Error on decoding strip %u of %s",
|
|
|
|
i + j*stripcount,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
samplebufferoffset+=read;
|
|
|
|
}
|
|
|
|
t2p_sample_planar_separate_to_contig(
|
|
|
|
t2p,
|
|
|
|
&(buffer[bufferoffset]),
|
|
|
|
samplebuffer,
|
|
|
|
samplebufferoffset);
|
|
|
|
bufferoffset+=samplebufferoffset;
|
|
|
|
}
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
goto dataready;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
stripsize=TIFFStripSize(input);
|
|
|
|
stripcount=TIFFNumberOfStrips(input);
|
|
|
|
for(i=0;i<stripcount;i++){
|
|
|
|
read =
|
|
|
|
TIFFReadEncodedStrip(input,
|
|
|
|
i,
|
|
|
|
(tdata_t) &buffer[bufferoffset],
|
2014-12-24 10:38:11 -05:00
|
|
|
TIFFmin(stripsize, t2p->tiff_datasize - bufferoffset));
|
2003-11-25 11:39:22 -05:00
|
|
|
if(read==-1){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Error on decoding strip %u of %s",
|
|
|
|
i,
|
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
bufferoffset+=read;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_REALIZE_PALETTE){
|
2011-05-31 13:00:03 -04:00
|
|
|
// FIXME: overflow?
|
2003-11-25 11:39:22 -05:00
|
|
|
samplebuffer=(unsigned char*)_TIFFrealloc(
|
|
|
|
(tdata_t) buffer,
|
|
|
|
t2p->tiff_datasize * t2p->tiff_samplesperpixel);
|
|
|
|
if(samplebuffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2013-08-14 01:11:36 -04:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(0);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
buffer=samplebuffer;
|
|
|
|
t2p->tiff_datasize *= t2p->tiff_samplesperpixel;
|
|
|
|
}
|
|
|
|
t2p_sample_realize_palette(t2p, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB){
|
|
|
|
t2p->tiff_datasize=t2p_sample_rgba_to_rgb(
|
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_width*t2p->tiff_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB){
|
|
|
|
t2p->tiff_datasize=t2p_sample_rgbaa_to_rgb(
|
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_width*t2p->tiff_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){
|
2004-08-20 15:23:25 -04:00
|
|
|
samplebuffer=(unsigned char*)_TIFFrealloc(
|
2003-11-25 11:39:22 -05:00
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_width*t2p->tiff_length*4);
|
|
|
|
if(samplebuffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(0);
|
|
|
|
} else {
|
|
|
|
buffer=samplebuffer;
|
|
|
|
}
|
|
|
|
if(!TIFFReadRGBAImageOriented(
|
|
|
|
input,
|
|
|
|
t2p->tiff_width,
|
|
|
|
t2p->tiff_length,
|
|
|
|
(uint32*)buffer,
|
|
|
|
ORIENTATION_TOPLEFT,
|
|
|
|
0)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2006-06-08 07:27:11 -04:00
|
|
|
"Can't use TIFFReadRGBAImageOriented to extract RGB image from %s",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
t2p->tiff_datasize=t2p_sample_abgr_to_rgb(
|
|
|
|
(tdata_t) buffer,
|
|
|
|
t2p->tiff_width*t2p->tiff_length);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED){
|
|
|
|
t2p->tiff_datasize=t2p_sample_lab_signed_to_unsigned(
|
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_width*t2p->tiff_length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
dataready:
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p_disable(output);
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFSetField(output, TIFFTAG_PHOTOMETRIC, t2p->tiff_photometric);
|
|
|
|
TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, t2p->tiff_bitspersample);
|
|
|
|
TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, t2p->tiff_samplesperpixel);
|
|
|
|
TIFFSetField(output, TIFFTAG_IMAGEWIDTH, t2p->tiff_width);
|
|
|
|
TIFFSetField(output, TIFFTAG_IMAGELENGTH, t2p->tiff_length);
|
|
|
|
TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, t2p->tiff_length);
|
|
|
|
TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
|
|
|
TIFFSetField(output, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
|
|
|
|
|
|
|
|
switch(t2p->pdf_compression){
|
|
|
|
case T2P_COMPRESS_NONE:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
|
|
|
|
break;
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
case T2P_COMPRESS_G4:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
|
|
|
|
break;
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef CCITT_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
case T2P_COMPRESS_JPEG:
|
2007-07-03 11:47:05 -04:00
|
|
|
if(t2p->tiff_photometric==PHOTOMETRIC_YCBCR) {
|
|
|
|
uint16 hor = 0, ver = 0;
|
|
|
|
if (TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &hor, &ver) !=0 ) {
|
|
|
|
if(hor != 0 && ver != 0){
|
|
|
|
TIFFSetField(output, TIFFTAG_YCBCRSUBSAMPLING, hor, ver);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_REFERENCEBLACKWHITE, &xfloatp)!=0){
|
|
|
|
TIFFSetField(output, TIFFTAG_REFERENCEBLACKWHITE, xfloatp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_JPEG)==0){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2006-06-08 07:27:11 -04:00
|
|
|
"Unable to use JPEG compression for input %s and output %s",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input),
|
|
|
|
TIFFFileName(output));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGTABLESMODE, 0);
|
|
|
|
|
|
|
|
if(t2p->pdf_colorspace & (T2P_CS_RGB | T2P_CS_LAB)){
|
|
|
|
TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
|
|
|
|
if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR){
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
|
|
|
} else {
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_GRAY){
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CMYK){
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_defaultcompressionquality != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_JPEGQUALITY,
|
|
|
|
t2p->pdf_defaultcompressionquality);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef JPEG_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
case T2P_COMPRESS_ZIP:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
|
|
|
|
if(t2p->pdf_defaultcompressionquality%100 != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_PREDICTOR,
|
|
|
|
t2p->pdf_defaultcompressionquality % 100);
|
|
|
|
}
|
|
|
|
if(t2p->pdf_defaultcompressionquality/100 != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_ZIPQUALITY,
|
|
|
|
(t2p->pdf_defaultcompressionquality / 100));
|
|
|
|
}
|
|
|
|
break;
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef ZIP_SUPPORT */
|
2003-11-25 11:39:22 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
|
|
|
|
t2p_enable(output);
|
|
|
|
t2p->outputwritten = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
#ifdef JPEG_SUPPORT
|
2007-07-03 11:47:05 -04:00
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_JPEG
|
|
|
|
&& t2p->tiff_photometric == PHOTOMETRIC_YCBCR){
|
|
|
|
bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0,
|
|
|
|
buffer,
|
|
|
|
stripsize * stripcount);
|
2007-07-05 21:25:11 -04:00
|
|
|
} else
|
2015-05-30 13:07:53 -04:00
|
|
|
#endif /* ifdef JPEG_SUPPORT */
|
2007-07-05 21:25:11 -04:00
|
|
|
{
|
2007-07-03 11:47:05 -04:00
|
|
|
bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0,
|
|
|
|
buffer,
|
|
|
|
t2p->tiff_datasize);
|
|
|
|
}
|
|
|
|
if (buffer != NULL) {
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
buffer=NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
if (bufferoffset == (tsize_t)-1) {
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2007-07-03 11:47:05 -04:00
|
|
|
"Error writing encoded strip to output PDF %s",
|
|
|
|
TIFFFileName(output));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written = t2p->outputwritten;
|
2003-11-25 11:39:22 -05:00
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-07-03 11:47:05 -04:00
|
|
|
* This function reads the raster image data from the input TIFF for an image
|
|
|
|
* tile and writes the data to the output PDF XObject image dictionary stream
|
|
|
|
* for the tile. It returns the amount written or zero on error.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){
|
|
|
|
|
|
|
|
uint16 edge=0;
|
|
|
|
tsize_t written=0;
|
|
|
|
unsigned char* buffer=NULL;
|
|
|
|
tsize_t bufferoffset=0;
|
|
|
|
unsigned char* samplebuffer=NULL;
|
|
|
|
tsize_t samplebufferoffset=0;
|
|
|
|
tsize_t read=0;
|
|
|
|
uint16 i=0;
|
|
|
|
ttile_t tilecount=0;
|
2014-12-07 14:32:25 -05:00
|
|
|
/* tsize_t tilesize=0; */
|
2003-11-25 11:39:22 -05:00
|
|
|
ttile_t septilecount=0;
|
|
|
|
tsize_t septilesize=0;
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
unsigned char* jpt;
|
|
|
|
float* xfloatp;
|
|
|
|
uint32 xuint32=0;
|
|
|
|
#endif
|
|
|
|
|
2012-06-15 17:44:31 -04:00
|
|
|
/* Fail if prior error (in particular, can't trust tiff_datasize) */
|
|
|
|
if (t2p->t2p_error != T2P_ERR_OK)
|
|
|
|
return(0);
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
|
|
|
|
edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
|
|
|
|
|
|
|
|
if( (t2p->pdf_transcode == T2P_TRANSCODE_RAW) && ((edge == 0)
|
|
|
|
#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT)
|
|
|
|
|| (t2p->pdf_compression == T2P_COMPRESS_JPEG)
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
){
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_G4){
|
|
|
|
buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2004-04-20 10:54:05 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
2008-12-31 18:48:01 -05:00
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (TIFFReadRawTile(input, tile, (tdata_t) buffer, t2p->tiff_datasize) < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"TIFFReadRawTile() failed");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){
|
|
|
|
TIFFReverseBits(buffer, t2p->tiff_datasize);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(t2p->tiff_datasize);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
if(t2p->pdf_compression == T2P_COMPRESS_ZIP){
|
|
|
|
buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2004-04-20 10:54:05 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
2008-12-31 18:48:01 -05:00
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (TIFFReadRawTile(input, tile, (tdata_t) buffer, t2p->tiff_datasize) < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"TIFFReadRawTile() failed");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){
|
|
|
|
TIFFReverseBits(buffer, t2p->tiff_datasize);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(t2p->tiff_datasize);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression == COMPRESSION_OJPEG){
|
2020-04-19 17:39:59 -04:00
|
|
|
tsize_t retTIFFReadRawTile;
|
2003-11-25 11:39:22 -05:00
|
|
|
if(! t2p->pdf_ojpegdata){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2004-04-20 10:54:05 -04:00
|
|
|
"No support for OJPEG image %s with "
|
|
|
|
"bad tables",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
buffer=(unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2004-04-20 10:54:05 -04:00
|
|
|
"for t2p_readwrite_pdf_image, %s",
|
2008-12-31 18:48:01 -05:00
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFmemcpy(buffer, t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength);
|
|
|
|
if(edge!=0){
|
|
|
|
if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile)){
|
|
|
|
buffer[7]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength >> 8) & 0xff;
|
|
|
|
buffer[8]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength ) & 0xff;
|
|
|
|
}
|
|
|
|
if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile)){
|
|
|
|
buffer[9]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth >> 8) & 0xff;
|
|
|
|
buffer[10]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth ) & 0xff;
|
|
|
|
}
|
|
|
|
}
|
2020-04-19 17:39:59 -04:00
|
|
|
bufferoffset = t2p->pdf_ojpegdatalength;
|
|
|
|
retTIFFReadRawTile = TIFFReadRawTile(input,
|
2003-11-25 11:39:22 -05:00
|
|
|
tile,
|
|
|
|
(tdata_t) &(((unsigned char*)buffer)[bufferoffset]),
|
|
|
|
-1);
|
2020-04-19 17:39:59 -04:00
|
|
|
if (retTIFFReadRawTile < 0) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "TIFFReadRawTile() failed");
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
bufferoffset += retTIFFReadRawTile;
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, bufferoffset);
|
2020-11-09 20:35:13 -05:00
|
|
|
t2pWriteFile(output, (tdata_t) jpeg_eof_marker, sizeof(jpeg_eof_marker));
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(bufferoffset);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
if(t2p->tiff_compression == COMPRESSION_JPEG){
|
2005-09-13 09:40:48 -04:00
|
|
|
unsigned char table_end[2];
|
2007-07-03 11:47:05 -04:00
|
|
|
uint32 count = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2015-06-20 21:09:09 -04:00
|
|
|
"Can't allocate " TIFF_SIZE_FORMAT " bytes of memory "
|
2004-04-20 10:54:05 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
2015-06-20 21:09:09 -04:00
|
|
|
(TIFF_SIZE_T) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2007-07-03 11:47:05 -04:00
|
|
|
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) {
|
2016-12-20 12:28:17 -05:00
|
|
|
if (count > 4) {
|
2020-04-19 17:39:59 -04:00
|
|
|
tsize_t retTIFFReadRawTile;
|
2016-10-09 07:03:36 -04:00
|
|
|
/* Ignore EOI marker of JpegTables */
|
|
|
|
_TIFFmemcpy(buffer, jpt, count - 2);
|
2007-07-03 11:47:05 -04:00
|
|
|
bufferoffset += count - 2;
|
2016-10-09 07:03:36 -04:00
|
|
|
/* Store last 2 bytes of the JpegTables */
|
2005-09-13 09:40:48 -04:00
|
|
|
table_end[0] = buffer[bufferoffset-2];
|
|
|
|
table_end[1] = buffer[bufferoffset-1];
|
|
|
|
xuint32 = bufferoffset;
|
2016-12-20 12:24:35 -05:00
|
|
|
bufferoffset -= 2;
|
2020-04-19 17:39:59 -04:00
|
|
|
retTIFFReadRawTile = TIFFReadRawTile(
|
2005-09-13 09:40:48 -04:00
|
|
|
input,
|
|
|
|
tile,
|
2016-10-09 07:03:36 -04:00
|
|
|
(tdata_t) &(((unsigned char*)buffer)[bufferoffset]),
|
2005-09-13 09:40:48 -04:00
|
|
|
-1);
|
2016-12-20 12:24:35 -05:00
|
|
|
if( retTIFFReadRawTile < 0 )
|
|
|
|
{
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
bufferoffset += retTIFFReadRawTile;
|
2016-10-09 07:03:36 -04:00
|
|
|
/* Overwrite SOI marker of image scan with previously */
|
|
|
|
/* saved end of JpegTables */
|
|
|
|
buffer[xuint32-2]=table_end[0];
|
|
|
|
buffer[xuint32-1]=table_end[1];
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pWriteFile(output, (tdata_t) buffer, bufferoffset);
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
|
|
|
return(bufferoffset);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample==T2P_SAMPLE_NOTHING){
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory for "
|
2004-04-20 10:54:05 -04:00
|
|
|
"t2p_readwrite_pdf_image_tile, %s",
|
2008-12-31 18:48:01 -05:00
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
read = TIFFReadEncodedTile(
|
|
|
|
input,
|
|
|
|
tile,
|
|
|
|
(tdata_t) &buffer[bufferoffset],
|
|
|
|
t2p->tiff_datasize);
|
|
|
|
if(read==-1){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Error on decoding tile %u of %s",
|
|
|
|
tile,
|
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if(t2p->pdf_sample == T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
|
|
|
|
septilesize=TIFFTileSize(input);
|
|
|
|
septilecount=TIFFNumberOfTiles(input);
|
2014-12-07 14:32:25 -05:00
|
|
|
/* tilesize=septilesize*t2p->tiff_samplesperpixel; */
|
2003-11-25 11:39:22 -05:00
|
|
|
tilecount=septilecount/t2p->tiff_samplesperpixel;
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2020-04-04 18:13:13 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
samplebuffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(samplebuffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2020-04-04 18:13:13 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
2018-10-31 06:50:48 -04:00
|
|
|
_TIFFfree(buffer);
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(samplebuffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
samplebufferoffset=0;
|
|
|
|
for(i=0;i<t2p->tiff_samplesperpixel;i++){
|
|
|
|
read =
|
|
|
|
TIFFReadEncodedTile(input,
|
|
|
|
tile + i*tilecount,
|
|
|
|
(tdata_t) &(samplebuffer[samplebufferoffset]),
|
|
|
|
septilesize);
|
|
|
|
if(read==-1){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Error on decoding tile %u of %s",
|
|
|
|
tile + i*tilecount,
|
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
samplebufferoffset+=read;
|
|
|
|
}
|
|
|
|
t2p_sample_planar_separate_to_contig(
|
|
|
|
t2p,
|
|
|
|
&(buffer[bufferoffset]),
|
|
|
|
samplebuffer,
|
|
|
|
samplebufferoffset);
|
|
|
|
bufferoffset+=samplebufferoffset;
|
|
|
|
_TIFFfree(samplebuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(buffer==NULL){
|
|
|
|
buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize);
|
|
|
|
if(buffer==NULL){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %lu bytes of memory "
|
2020-04-04 18:13:13 -04:00
|
|
|
"for t2p_readwrite_pdf_image_tile, %s",
|
|
|
|
(unsigned long) t2p->tiff_datasize,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2020-04-04 18:01:59 -04:00
|
|
|
memset(buffer, 0, t2p->tiff_datasize);
|
2003-11-25 11:39:22 -05:00
|
|
|
read = TIFFReadEncodedTile(
|
|
|
|
input,
|
|
|
|
tile,
|
|
|
|
(tdata_t) &buffer[bufferoffset],
|
|
|
|
t2p->tiff_datasize);
|
|
|
|
if(read==-1){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Error on decoding tile %u of %s",
|
|
|
|
tile,
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error=T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB){
|
|
|
|
t2p->tiff_datasize=t2p_sample_rgba_to_rgb(
|
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth
|
|
|
|
*t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB){
|
|
|
|
t2p->tiff_datasize=t2p_sample_rgbaa_to_rgb(
|
|
|
|
(tdata_t)buffer,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth
|
|
|
|
*t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"No support for YCbCr to RGB in tile for %s",
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFFileName(input));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED){
|
|
|
|
t2p->tiff_datasize=t2p_sample_lab_signed_to_unsigned(
|
2019-02-13 09:13:21 -05:00
|
|
|
(tdata_t)buffer,
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth
|
|
|
|
*t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile) != 0){
|
2019-02-13 09:13:21 -05:00
|
|
|
if ((uint64)t2p->tiff_datasize < (uint64)TIFFTileRowSize(input) * (uint64)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength) {
|
|
|
|
/* we don't know how to handle PLANARCONFIG_CONTIG, PHOTOMETRIC_YCBCR with 3 samples per pixel */
|
|
|
|
TIFFWarning(
|
|
|
|
TIFF2PDF_MODULE,
|
|
|
|
"Don't know how to collapse tile to the left");
|
|
|
|
} else {
|
|
|
|
t2p_tile_collapse_left(
|
|
|
|
buffer,
|
|
|
|
TIFFTileRowSize(input),
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p_disable(output);
|
2003-11-25 11:39:22 -05:00
|
|
|
TIFFSetField(output, TIFFTAG_PHOTOMETRIC, t2p->tiff_photometric);
|
|
|
|
TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, t2p->tiff_bitspersample);
|
|
|
|
TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, t2p->tiff_samplesperpixel);
|
|
|
|
if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile) == 0){
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_IMAGEWIDTH,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth);
|
|
|
|
} else {
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_IMAGEWIDTH,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth);
|
|
|
|
}
|
|
|
|
if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile) == 0){
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_IMAGELENGTH,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_ROWSPERSTRIP,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
|
|
|
} else {
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_IMAGELENGTH,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength);
|
|
|
|
TIFFSetField(
|
|
|
|
output,
|
|
|
|
TIFFTAG_ROWSPERSTRIP,
|
|
|
|
t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength);
|
|
|
|
}
|
|
|
|
TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
|
|
|
TIFFSetField(output, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
|
|
|
|
|
|
|
|
switch(t2p->pdf_compression){
|
|
|
|
case T2P_COMPRESS_NONE:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
|
|
|
|
break;
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
case T2P_COMPRESS_G4:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
case T2P_COMPRESS_JPEG:
|
2007-07-03 11:47:05 -04:00
|
|
|
if (t2p->tiff_photometric==PHOTOMETRIC_YCBCR) {
|
|
|
|
uint16 hor = 0, ver = 0;
|
|
|
|
if (TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &hor, &ver)!=0) {
|
|
|
|
if (hor != 0 && ver != 0) {
|
|
|
|
TIFFSetField(output, TIFFTAG_YCBCRSUBSAMPLING, hor, ver);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFGetField(input, TIFFTAG_REFERENCEBLACKWHITE, &xfloatp)!=0){
|
|
|
|
TIFFSetField(output, TIFFTAG_REFERENCEBLACKWHITE, xfloatp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGTABLESMODE, 0); /* JPEGTABLESMODE_NONE */
|
|
|
|
if(t2p->pdf_colorspace & (T2P_CS_RGB | T2P_CS_LAB)){
|
|
|
|
TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
|
|
|
|
if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR){
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
|
|
|
} else {
|
|
|
|
TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_GRAY){
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CMYK){
|
|
|
|
(void)0;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_defaultcompressionquality != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_JPEGQUALITY,
|
|
|
|
t2p->pdf_defaultcompressionquality);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
case T2P_COMPRESS_ZIP:
|
|
|
|
TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
|
|
|
|
if(t2p->pdf_defaultcompressionquality%100 != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_PREDICTOR,
|
|
|
|
t2p->pdf_defaultcompressionquality % 100);
|
|
|
|
}
|
|
|
|
if(t2p->pdf_defaultcompressionquality/100 != 0){
|
|
|
|
TIFFSetField(output,
|
|
|
|
TIFFTAG_ZIPQUALITY,
|
|
|
|
(t2p->pdf_defaultcompressionquality / 100));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
|
2020-11-17 19:21:23 -05:00
|
|
|
if (TIFFStripSize(output) > t2p->tiff_datasize) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Size mismatch input %ld, output %ld",
|
|
|
|
t2p->tiff_datasize, TIFFStripSize(output));
|
|
|
|
_TIFFfree(buffer);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p_enable(output);
|
|
|
|
t2p->outputwritten = 0;
|
2006-06-08 07:27:11 -04:00
|
|
|
bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t) 0, buffer,
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFStripSize(output));
|
2007-07-03 11:47:05 -04:00
|
|
|
if (buffer != NULL) {
|
2003-11-25 11:39:22 -05:00
|
|
|
_TIFFfree(buffer);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer = NULL;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
if (bufferoffset == -1) {
|
2020-04-04 18:13:13 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Error writing encoded tile to output PDF %s",
|
|
|
|
TIFFFileName(output));
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written = t2p->outputwritten;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef OJPEG_SUPPORT
|
|
|
|
int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){
|
|
|
|
uint16 proc=0;
|
|
|
|
void* q;
|
|
|
|
uint32 q_length=0;
|
|
|
|
void* dc;
|
|
|
|
uint32 dc_length=0;
|
|
|
|
void* ac;
|
|
|
|
uint32 ac_length=0;
|
|
|
|
uint16* lp;
|
|
|
|
uint16* pt;
|
|
|
|
uint16 h_samp=1;
|
|
|
|
uint16 v_samp=1;
|
|
|
|
unsigned char* ojpegdata;
|
|
|
|
uint16 table_count;
|
|
|
|
uint32 offset_table;
|
|
|
|
uint32 offset_ms_l;
|
|
|
|
uint32 code_count;
|
|
|
|
uint32 i=0;
|
|
|
|
uint32 dest=0;
|
|
|
|
uint16 ri=0;
|
|
|
|
uint32 rows=0;
|
|
|
|
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGPROC, &proc)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGProc field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(proc!=JPEGPROC_BASELINE && proc!=JPEGPROC_LOSSLESS){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Bad JPEGProc field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGQTABLES, &q_length, &q)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGQTables field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
2006-03-20 10:29:53 -05:00
|
|
|
if(q_length < (64U * t2p->tiff_samplesperpixel)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Bad JPEGQTables field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGDCTABLES, &dc_length, &dc)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGDCTables field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGACTABLES, &ac_length, &ac)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGACTables field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGLOSSLESSPREDICTORS, &lp)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGLosslessPredictors field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_JPEGPOINTTRANSFORM, &pt)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Missing JPEGPointTransform field in OJPEG image %s",
|
|
|
|
TIFFFileName(input));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &h_samp, &v_samp)){
|
|
|
|
h_samp=1;
|
|
|
|
v_samp=1;
|
|
|
|
}
|
|
|
|
if(t2p->pdf_ojpegdata != NULL){
|
|
|
|
_TIFFfree(t2p->pdf_ojpegdata);
|
|
|
|
t2p->pdf_ojpegdata=NULL;
|
|
|
|
}
|
|
|
|
t2p->pdf_ojpegdata = _TIFFmalloc(2048);
|
|
|
|
if(t2p->pdf_ojpegdata == NULL){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Can't allocate %u bytes of memory for t2p_process_ojpeg_tables, %s",
|
|
|
|
2048,
|
|
|
|
TIFFFileName(input));
|
2012-07-19 11:43:41 -04:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
_TIFFmemset(t2p->pdf_ojpegdata, 0x00, 2048);
|
|
|
|
t2p->pdf_ojpegdatalength = 0;
|
|
|
|
table_count=t2p->tiff_samplesperpixel;
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
if(table_count>2) table_count=2;
|
|
|
|
}
|
|
|
|
ojpegdata=(unsigned char*)t2p->pdf_ojpegdata;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xd8;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xc0;
|
|
|
|
} else {
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xc3;
|
|
|
|
}
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x00;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=(8 + 3*t2p->tiff_samplesperpixel);
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=(t2p->tiff_bitspersample & 0xff);
|
|
|
|
if(TIFFIsTiled(input)){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength >> 8) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength ) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth >> 8) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth ) & 0xff;
|
|
|
|
} else {
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_length >> 8) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_length ) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_width >> 8) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=
|
|
|
|
(t2p->tiff_width ) & 0xff;
|
|
|
|
}
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=(t2p->tiff_samplesperpixel & 0xff);
|
|
|
|
for(i=0;i<t2p->tiff_samplesperpixel;i++){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=i;
|
|
|
|
if(i==0){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength] |= h_samp<<4 & 0xf0;;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++] |= v_samp & 0x0f;
|
|
|
|
} else {
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= 0x11;
|
|
|
|
}
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=i;
|
|
|
|
}
|
|
|
|
for(dest=0;dest<t2p->tiff_samplesperpixel;dest++){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xdb;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x00;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x43;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=dest;
|
|
|
|
_TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength++]),
|
|
|
|
&(((unsigned char*)q)[64*dest]), 64);
|
|
|
|
t2p->pdf_ojpegdatalength+=64;
|
|
|
|
}
|
|
|
|
offset_table=0;
|
|
|
|
for(dest=0;dest<table_count;dest++){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xc4;
|
|
|
|
offset_ms_l=t2p->pdf_ojpegdatalength;
|
|
|
|
t2p->pdf_ojpegdatalength+=2;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=dest & 0x0f;
|
|
|
|
_TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]),
|
|
|
|
&(((unsigned char*)dc)[offset_table]), 16);
|
|
|
|
code_count=0;
|
|
|
|
offset_table+=16;
|
|
|
|
for(i=0;i<16;i++){
|
|
|
|
code_count+=ojpegdata[t2p->pdf_ojpegdatalength++];
|
|
|
|
}
|
|
|
|
ojpegdata[offset_ms_l]=((19+code_count)>>8) & 0xff;
|
|
|
|
ojpegdata[offset_ms_l+1]=(19+code_count) & 0xff;
|
|
|
|
_TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]),
|
|
|
|
&(((unsigned char*)dc)[offset_table]), code_count);
|
|
|
|
offset_table+=code_count;
|
|
|
|
t2p->pdf_ojpegdatalength+=code_count;
|
|
|
|
}
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
offset_table=0;
|
|
|
|
for(dest=0;dest<table_count;dest++){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xc4;
|
|
|
|
offset_ms_l=t2p->pdf_ojpegdatalength;
|
|
|
|
t2p->pdf_ojpegdatalength+=2;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength] |= 0x10;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++] |=dest & 0x0f;
|
|
|
|
_TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]),
|
|
|
|
&(((unsigned char*)ac)[offset_table]), 16);
|
|
|
|
code_count=0;
|
|
|
|
offset_table+=16;
|
|
|
|
for(i=0;i<16;i++){
|
|
|
|
code_count+=ojpegdata[t2p->pdf_ojpegdatalength++];
|
|
|
|
}
|
|
|
|
ojpegdata[offset_ms_l]=((19+code_count)>>8) & 0xff;
|
|
|
|
ojpegdata[offset_ms_l+1]=(19+code_count) & 0xff;
|
|
|
|
_TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]),
|
|
|
|
&(((unsigned char*)ac)[offset_table]), code_count);
|
|
|
|
offset_table+=code_count;
|
|
|
|
t2p->pdf_ojpegdatalength+=code_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TIFFNumberOfStrips(input)>1){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xdd;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x00;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x04;
|
|
|
|
h_samp*=8;
|
|
|
|
v_samp*=8;
|
|
|
|
ri=(t2p->tiff_width+h_samp-1) / h_samp;
|
|
|
|
TIFFGetField(input, TIFFTAG_ROWSPERSTRIP, &rows);
|
|
|
|
ri*=(rows+v_samp-1)/v_samp;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= (ri>>8) & 0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= ri & 0xff;
|
|
|
|
}
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0xda;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x00;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=(6 + 2*t2p->tiff_samplesperpixel);
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=t2p->tiff_samplesperpixel & 0xff;
|
|
|
|
for(i=0;i<t2p->tiff_samplesperpixel;i++){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= i & 0xff;
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength] |=
|
2006-03-20 10:29:53 -05:00
|
|
|
( ( (i>(table_count-1U)) ? (table_count-1U) : i) << 4U) & 0xf0;
|
2003-11-25 11:39:22 -05:00
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++] |=
|
2006-03-20 10:29:53 -05:00
|
|
|
( (i>(table_count-1U)) ? (table_count-1U) : i) & 0x0f;
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++] = (i << 4) & 0xf0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(proc==JPEGPROC_BASELINE){
|
|
|
|
t2p->pdf_ojpegdatalength++;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]=0x3f;
|
|
|
|
t2p->pdf_ojpegdatalength++;
|
|
|
|
} else {
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= (lp[0] & 0xff);
|
|
|
|
t2p->pdf_ojpegdatalength++;
|
|
|
|
ojpegdata[t2p->pdf_ojpegdatalength++]= (pt[0] & 0x0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
int t2p_process_jpeg_strip(
|
|
|
|
unsigned char* strip,
|
|
|
|
tsize_t* striplength,
|
|
|
|
unsigned char* buffer,
|
2016-09-23 18:12:18 -04:00
|
|
|
tsize_t buffersize,
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t* bufferoffset,
|
|
|
|
tstrip_t no,
|
|
|
|
uint32 height){
|
|
|
|
|
|
|
|
tsize_t i=0;
|
2013-05-02 10:54:08 -04:00
|
|
|
|
|
|
|
while (i < *striplength) {
|
|
|
|
tsize_t datalen;
|
|
|
|
uint16 ri;
|
|
|
|
uint16 v_samp;
|
|
|
|
uint16 h_samp;
|
|
|
|
int j;
|
|
|
|
int ncomp;
|
|
|
|
|
|
|
|
/* marker header: one or more FFs */
|
|
|
|
if (strip[i] != 0xff)
|
|
|
|
return(0);
|
|
|
|
i++;
|
|
|
|
while (i < *striplength && strip[i] == 0xff)
|
|
|
|
i++;
|
|
|
|
if (i >= *striplength)
|
|
|
|
return(0);
|
|
|
|
/* SOI is the only pre-SOS marker without a length word */
|
|
|
|
if (strip[i] == 0xd8)
|
|
|
|
datalen = 0;
|
|
|
|
else {
|
|
|
|
if ((*striplength - i) <= 2)
|
|
|
|
return(0);
|
|
|
|
datalen = (strip[i+1] << 8) | strip[i+2];
|
|
|
|
if (datalen < 2 || datalen >= (*striplength - i))
|
|
|
|
return(0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
switch( strip[i] ){
|
2013-05-02 10:54:08 -04:00
|
|
|
case 0xd8: /* SOI - start of image */
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + 2 > buffersize )
|
|
|
|
return(0);
|
2010-02-22 14:10:07 -05:00
|
|
|
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), 2);
|
|
|
|
*bufferoffset+=2;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
2013-05-02 10:54:08 -04:00
|
|
|
case 0xc0: /* SOF0 */
|
|
|
|
case 0xc1: /* SOF1 */
|
|
|
|
case 0xc3: /* SOF3 */
|
|
|
|
case 0xc9: /* SOF9 */
|
|
|
|
case 0xca: /* SOF10 */
|
2003-11-25 11:39:22 -05:00
|
|
|
if(no==0){
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + datalen + 2 + 6 > buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + 9 >= buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
ncomp = buffer[*bufferoffset+9];
|
|
|
|
if (ncomp < 1 || ncomp > 4)
|
|
|
|
return(0);
|
|
|
|
v_samp=1;
|
|
|
|
h_samp=1;
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + 11 + 3*(ncomp-1) >= buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
for(j=0;j<ncomp;j++){
|
|
|
|
uint16 samp = buffer[*bufferoffset+11+(3*j)];
|
|
|
|
if( (samp>>4) > h_samp)
|
|
|
|
h_samp = (samp>>4);
|
|
|
|
if( (samp & 0x0f) > v_samp)
|
|
|
|
v_samp = (samp & 0x0f);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
v_samp*=8;
|
|
|
|
h_samp*=8;
|
|
|
|
ri=((( ((uint16)(buffer[*bufferoffset+5])<<8) |
|
|
|
|
(uint16)(buffer[*bufferoffset+6]) )+v_samp-1)/
|
|
|
|
v_samp);
|
|
|
|
ri*=((( ((uint16)(buffer[*bufferoffset+7])<<8) |
|
|
|
|
(uint16)(buffer[*bufferoffset+8]) )+h_samp-1)/
|
|
|
|
h_samp);
|
2004-10-28 09:32:28 -04:00
|
|
|
buffer[*bufferoffset+5]=
|
|
|
|
(unsigned char) ((height>>8) & 0xff);
|
|
|
|
buffer[*bufferoffset+6]=
|
|
|
|
(unsigned char) (height & 0xff);
|
2013-05-02 10:54:08 -04:00
|
|
|
*bufferoffset+=datalen+2;
|
|
|
|
/* insert a DRI marker */
|
2003-11-25 11:39:22 -05:00
|
|
|
buffer[(*bufferoffset)++]=0xff;
|
|
|
|
buffer[(*bufferoffset)++]=0xdd;
|
|
|
|
buffer[(*bufferoffset)++]=0x00;
|
|
|
|
buffer[(*bufferoffset)++]=0x04;
|
|
|
|
buffer[(*bufferoffset)++]=(ri >> 8) & 0xff;
|
|
|
|
buffer[(*bufferoffset)++]= ri & 0xff;
|
|
|
|
}
|
|
|
|
break;
|
2013-05-02 10:54:08 -04:00
|
|
|
case 0xc4: /* DHT */
|
|
|
|
case 0xdb: /* DQT */
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + datalen + 2 > buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
|
|
|
*bufferoffset+=datalen+2;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
2013-05-02 10:54:08 -04:00
|
|
|
case 0xda: /* SOS */
|
2003-11-25 11:39:22 -05:00
|
|
|
if(no==0){
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + datalen + 2 > buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2);
|
|
|
|
*bufferoffset+=datalen+2;
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + 2 > buffersize )
|
|
|
|
return(0);
|
2003-11-25 11:39:22 -05:00
|
|
|
buffer[(*bufferoffset)++]=0xff;
|
2004-10-28 09:32:28 -04:00
|
|
|
buffer[(*bufferoffset)++]=
|
|
|
|
(unsigned char)(0xd0 | ((no-1)%8));
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2013-05-02 10:54:08 -04:00
|
|
|
i += datalen + 1;
|
|
|
|
/* copy remainder of strip */
|
2016-09-23 18:12:18 -04:00
|
|
|
if( *bufferoffset + *striplength - i > buffersize )
|
|
|
|
return(0);
|
2013-05-02 10:54:08 -04:00
|
|
|
_TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i]), *striplength - i);
|
|
|
|
*bufferoffset+= *striplength - i;
|
2003-11-25 11:39:22 -05:00
|
|
|
return(1);
|
|
|
|
default:
|
2013-05-02 10:54:08 -04:00
|
|
|
/* ignore any other marker */
|
|
|
|
break;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2013-05-02 10:54:08 -04:00
|
|
|
i += datalen + 1;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2013-05-02 10:54:08 -04:00
|
|
|
/* failed to find SOS marker */
|
2003-11-25 11:39:22 -05:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-11-29 10:32:40 -05:00
|
|
|
/*
|
|
|
|
This functions converts a tilewidth x tilelength buffer of samples into an edgetilewidth x
|
|
|
|
tilelength buffer of samples.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
void t2p_tile_collapse_left(
|
|
|
|
tdata_t buffer,
|
|
|
|
tsize_t scanwidth,
|
|
|
|
uint32 tilewidth,
|
|
|
|
uint32 edgetilewidth,
|
|
|
|
uint32 tilelength){
|
|
|
|
|
2012-06-15 17:51:54 -04:00
|
|
|
uint32 i;
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t edgescanwidth=0;
|
|
|
|
|
2005-05-05 16:52:57 -04:00
|
|
|
edgescanwidth = (scanwidth * edgetilewidth + (tilewidth - 1))/ tilewidth;
|
2012-06-15 17:51:54 -04:00
|
|
|
for(i=0;i<tilelength;i++){
|
2016-12-20 12:13:26 -05:00
|
|
|
/* We use memmove() since there can be overlaps in src and dst buffers for the first items */
|
|
|
|
memmove(
|
2003-11-25 11:39:22 -05:00
|
|
|
&(((char*)buffer)[edgescanwidth*i]),
|
|
|
|
&(((char*)buffer)[scanwidth*i]),
|
|
|
|
edgescanwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2007-07-03 11:47:05 -04:00
|
|
|
* This function calls TIFFWriteDirectory on the output after blanking its
|
|
|
|
* output by replacing the read, write, and seek procedures with empty
|
|
|
|
* implementations, then it replaces the original implementations.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
void
|
|
|
|
t2p_write_advance_directory(T2P* t2p, TIFF* output)
|
|
|
|
{
|
|
|
|
t2p_disable(output);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(!TIFFWriteDirectory(output)){
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
2003-11-25 11:39:22 -05:00
|
|
|
"Error writing virtual directory to output PDF %s",
|
|
|
|
TIFFFileName(output));
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p_enable(output);
|
2003-11-25 11:39:22 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_sample_planar_separate_to_contig(
|
|
|
|
T2P* t2p,
|
|
|
|
unsigned char* buffer,
|
|
|
|
unsigned char* samplebuffer,
|
|
|
|
tsize_t samplebuffersize){
|
|
|
|
|
|
|
|
tsize_t stride=0;
|
|
|
|
tsize_t i=0;
|
|
|
|
tsize_t j=0;
|
|
|
|
|
|
|
|
stride=samplebuffersize/t2p->tiff_samplesperpixel;
|
|
|
|
for(i=0;i<stride;i++){
|
|
|
|
for(j=0;j<t2p->tiff_samplesperpixel;j++){
|
|
|
|
buffer[i*t2p->tiff_samplesperpixel + j] = samplebuffer[i + j*stride];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(samplebuffersize);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_sample_realize_palette(T2P* t2p, unsigned char* buffer){
|
|
|
|
|
|
|
|
uint32 sample_count=0;
|
|
|
|
uint16 component_count=0;
|
|
|
|
uint32 palette_offset=0;
|
|
|
|
uint32 sample_offset=0;
|
|
|
|
uint32 i=0;
|
|
|
|
uint32 j=0;
|
2017-10-29 14:50:41 -04:00
|
|
|
size_t data_size;
|
2003-11-25 11:39:22 -05:00
|
|
|
sample_count=t2p->tiff_width*t2p->tiff_length;
|
|
|
|
component_count=t2p->tiff_samplesperpixel;
|
2017-10-29 14:50:41 -04:00
|
|
|
data_size=TIFFSafeMultiply(size_t,sample_count,component_count);
|
|
|
|
if( (data_size == 0U) || (t2p->tiff_datasize < 0) ||
|
|
|
|
(data_size > (size_t) t2p->tiff_datasize) )
|
2016-12-18 05:37:59 -05:00
|
|
|
{
|
2017-10-29 14:50:41 -04:00
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Error: sample_count * component_count > t2p->tiff_datasize");
|
2016-12-18 05:37:59 -05:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return 1;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
for(i=sample_count;i>0;i--){
|
|
|
|
palette_offset=buffer[i-1] * component_count;
|
|
|
|
sample_offset= (i-1) * component_count;
|
2020-02-08 07:27:51 -05:00
|
|
|
if(palette_offset + component_count > t2p->pdf_palettesize){
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Error: palette_offset + component_count > t2p->pdf_palettesize");
|
|
|
|
return 1;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
for(j=0;j<component_count;j++){
|
|
|
|
buffer[sample_offset+j]=t2p->pdf_palette[palette_offset+j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-05-26 05:24:07 -04:00
|
|
|
This functions converts in place a buffer of ABGR interleaved data
|
|
|
|
into RGB interleaved data, discarding A.
|
2003-11-25 11:39:22 -05:00
|
|
|
*/
|
|
|
|
|
2005-05-05 16:52:57 -04:00
|
|
|
tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32 samplecount)
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
uint32 i=0;
|
|
|
|
uint32 sample=0;
|
|
|
|
|
|
|
|
for(i=0;i<samplecount;i++){
|
|
|
|
sample=((uint32*)data)[i];
|
2004-06-04 09:46:25 -04:00
|
|
|
((char*)data)[i*3]= (char) (sample & 0xff);
|
|
|
|
((char*)data)[i*3+1]= (char) ((sample>>8) & 0xff);
|
|
|
|
((char*)data)[i*3+2]= (char) ((sample>>16) & 0xff);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return(i*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-03-18 04:47:34 -05:00
|
|
|
* This functions converts in place a buffer of RGBA interleaved data
|
|
|
|
* into RGB interleaved data, discarding A.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2005-03-18 04:47:34 -05:00
|
|
|
tsize_t
|
2006-02-26 12:55:42 -05:00
|
|
|
t2p_sample_rgbaa_to_rgb(tdata_t data, uint32 samplecount)
|
2005-03-18 04:47:34 -05:00
|
|
|
{
|
2005-05-05 16:52:57 -04:00
|
|
|
uint32 i;
|
2018-02-04 18:54:17 -05:00
|
|
|
|
|
|
|
/* For the 3 first samples, there is overlap between source and
|
|
|
|
* destination, so use memmove().
|
|
|
|
* See http://bugzilla.maptools.org/show_bug.cgi?id=2577
|
|
|
|
*/
|
|
|
|
for(i = 0; i < 3 && i < samplecount; i++)
|
|
|
|
memmove((uint8*)data + i * 3, (uint8*)data + i * 4, 3);
|
2016-11-11 16:22:50 -05:00
|
|
|
for(; i < samplecount; i++)
|
2005-03-18 04:47:34 -05:00
|
|
|
memcpy((uint8*)data + i * 3, (uint8*)data + i * 4, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2005-03-18 04:47:34 -05:00
|
|
|
return(i * 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-02-26 12:55:42 -05:00
|
|
|
* This functions converts in place a buffer of RGBA interleaved data
|
|
|
|
* into RGB interleaved data, adding 255-A to each component sample.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2006-02-26 12:55:42 -05:00
|
|
|
tsize_t
|
|
|
|
t2p_sample_rgba_to_rgb(tdata_t data, uint32 samplecount)
|
2005-05-05 16:52:57 -04:00
|
|
|
{
|
2006-02-26 12:55:42 -05:00
|
|
|
uint32 i = 0;
|
|
|
|
uint32 sample = 0;
|
|
|
|
uint8 alpha = 0;
|
2015-01-22 04:58:49 -05:00
|
|
|
|
2006-02-26 12:55:42 -05:00
|
|
|
for (i = 0; i < samplecount; i++) {
|
2003-11-25 11:39:22 -05:00
|
|
|
sample=((uint32*)data)[i];
|
2010-12-13 00:41:38 -05:00
|
|
|
alpha=(uint8)((255 - ((sample >> 24) & 0xff)));
|
|
|
|
((uint8 *)data)[i * 3] = (uint8) ((sample >> 16) & 0xff) + alpha;
|
|
|
|
((uint8 *)data)[i * 3 + 1] = (uint8) ((sample >> 8) & 0xff) + alpha;
|
|
|
|
((uint8 *)data)[i * 3 + 2] = (uint8) (sample & 0xff) + alpha;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2006-02-26 12:55:42 -05:00
|
|
|
return (i * 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-03-18 04:47:34 -05:00
|
|
|
This function converts the a and b samples of Lab data from signed
|
|
|
|
to unsigned.
|
2003-11-25 11:39:22 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32 samplecount){
|
|
|
|
|
|
|
|
uint32 i=0;
|
|
|
|
|
|
|
|
for(i=0;i<samplecount;i++){
|
|
|
|
if( (((unsigned char*)buffer)[(i*3)+1] & 0x80) !=0){
|
2005-03-18 04:47:34 -05:00
|
|
|
((unsigned char*)buffer)[(i*3)+1] =
|
|
|
|
(unsigned char)(0x80 + ((char*)buffer)[(i*3)+1]);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
((unsigned char*)buffer)[(i*3)+1] |= 0x80;
|
|
|
|
}
|
|
|
|
if( (((unsigned char*)buffer)[(i*3)+2] & 0x80) !=0){
|
2005-03-18 04:47:34 -05:00
|
|
|
((unsigned char*)buffer)[(i*3)+2] =
|
|
|
|
(unsigned char)(0x80 + ((char*)buffer)[(i*3)+2]);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
((unsigned char*)buffer)[(i*3)+2] |= 0x80;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return(samplecount*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the PDF header to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_header(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
char buffer[16];
|
|
|
|
int buflen=0;
|
|
|
|
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%%PDF-%u.%u ",
|
|
|
|
t2p->pdf_majorversion&0xff,
|
|
|
|
t2p->pdf_minorversion&0xff);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t)"\n%\342\343\317\323\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the beginning of a PDF object to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_obj_start(uint32 number, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret((T2P*)NULL, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 obj\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the end of a PDF object to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_obj_end(TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "endobj\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF name object to output.
|
|
|
|
*/
|
|
|
|
|
2020-03-20 20:05:41 -04:00
|
|
|
tsize_t t2p_write_pdf_name(const unsigned char* name, TIFF* output){
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
uint32 i=0;
|
2006-06-08 07:27:11 -04:00
|
|
|
char buffer[64];
|
2003-11-25 11:39:22 -05:00
|
|
|
uint16 nextchar=0;
|
2008-01-01 10:49:00 -05:00
|
|
|
size_t namelen=0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2006-06-08 07:27:11 -04:00
|
|
|
namelen = strlen((char *)name);
|
2003-11-25 11:39:22 -05:00
|
|
|
if (namelen>126) {
|
|
|
|
namelen=126;
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
for (i=0;i<namelen;i++){
|
|
|
|
if ( ((unsigned char)name[i]) < 0x21){
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
nextchar=1;
|
|
|
|
}
|
|
|
|
if ( ((unsigned char)name[i]) > 0x7E){
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
nextchar=1;
|
|
|
|
}
|
|
|
|
if (nextchar==0){
|
|
|
|
switch (name[i]){
|
|
|
|
case 0x23:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x25:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x28:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x29:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x2F:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x3C:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x3E:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x5B:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x5D:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x7B:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x7D:
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "#%.2X", name[i]);
|
2006-06-08 07:27:11 -04:00
|
|
|
buffer[sizeof(buffer) - 1] = '\0';
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
default:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) &name[i], 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
nextchar=0;
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-30 10:12:03 -04:00
|
|
|
* This function writes a PDF string object to output.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2020-03-20 20:05:41 -04:00
|
|
|
tsize_t t2p_write_pdf_string(const char* pdfstr, TIFF* output)
|
2010-06-30 10:12:03 -04:00
|
|
|
{
|
2006-06-08 06:45:35 -04:00
|
|
|
tsize_t written = 0;
|
|
|
|
uint32 i = 0;
|
|
|
|
char buffer[64];
|
2008-01-01 10:49:00 -05:00
|
|
|
size_t len = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
len = strlen(pdfstr);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "(", 1);
|
2006-06-08 06:45:35 -04:00
|
|
|
for (i=0; i<len; i++) {
|
2003-11-25 11:39:22 -05:00
|
|
|
if((pdfstr[i]&0x80) || (pdfstr[i]==127) || (pdfstr[i]<32)){
|
2011-04-02 16:54:08 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "\\%.3o", ((unsigned char)pdfstr[i]));
|
2010-06-30 10:12:03 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t)buffer, 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
switch (pdfstr[i]){
|
|
|
|
case 0x08:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\b", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x09:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\t", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x0A:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\n", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x0C:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\f", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x0D:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\r", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x28:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\(", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x29:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\)", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 0x5C:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\\\\", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
default:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) &pdfstr[i], 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ") ", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a buffer of data to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream(tdata_t buffer, tsize_t len, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, len);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This functions writes the beginning of a PDF stream to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_start(TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "stream\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the end of a PDF stream to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_end(TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\nendstream\n", 11);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a stream dictionary for a PDF stream to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_dict(tsize_t len, uint32 number, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Length ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(len!=0){
|
|
|
|
written += t2p_write_pdf_stream_length(len, output);
|
|
|
|
} else {
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret((T2P*)NULL, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This functions writes the beginning of a PDF stream dictionary to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_dict_start(TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< \n", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the end of a PDF stream dictionary to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_dict_end(TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " >>\n", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a number to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_stream_length(tsize_t len, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)len);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret((T2P*)NULL, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-30 10:12:03 -04:00
|
|
|
* This function writes the PDF Catalog structure to output.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
tsize_t t2p_write_pdf_catalog(T2P* t2p, TIFF* output)
|
|
|
|
{
|
|
|
|
tsize_t written = 0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2010-06-30 10:12:03 -04:00
|
|
|
int buflen = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output,
|
2006-04-21 11:09:34 -04:00
|
|
|
(tdata_t)"<< \n/Type /Catalog \n/Pages ",
|
2003-11-25 11:39:22 -05:00
|
|
|
27);
|
2010-06-30 10:12:03 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2010-06-30 10:12:03 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer,
|
|
|
|
TIFFmin((size_t)buflen, sizeof(buffer) - 1));
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_fitwindow){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output,
|
2006-04-21 11:09:34 -04:00
|
|
|
(tdata_t) "/ViewerPreferences <</FitWindow true>>\n",
|
2003-11-25 11:39:22 -05:00
|
|
|
39);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t)">>\n", 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes the PDF Info structure to output.
|
|
|
|
*/
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output)
|
|
|
|
{
|
2006-06-08 07:27:11 -04:00
|
|
|
tsize_t written = 0;
|
2020-03-20 20:05:41 -04:00
|
|
|
const char* info;
|
2003-11-25 11:39:22 -05:00
|
|
|
char buffer[512];
|
2010-06-30 10:12:03 -04:00
|
|
|
|
|
|
|
if(t2p->pdf_datetime[0] == '\0')
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p_pdf_tifftime(t2p, input);
|
2010-06-30 10:12:03 -04:00
|
|
|
if (strlen(t2p->pdf_datetime) > 0) {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< \n/CreationDate ", 18);
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_string(t2p->pdf_datetime, output);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/ModDate ", 10);
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_string(t2p->pdf_datetime, output);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/Producer ", 11);
|
2010-06-30 10:12:03 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "libtiff / tiff2pdf - %d", TIFFLIB_VERSION);
|
|
|
|
written += t2p_write_pdf_string(buffer, output);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2020-03-20 20:05:41 -04:00
|
|
|
if (!t2p->pdf_creator_set) {
|
|
|
|
if (TIFFGetField(input, TIFFTAG_SOFTWARE, &info) != 0 && info) {
|
|
|
|
strncpy(t2p->pdf_creator, info, sizeof(t2p->pdf_creator) - 1);
|
|
|
|
t2p->pdf_creator[sizeof(t2p->pdf_creator) - 1] = '\0';
|
|
|
|
}
|
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
if (t2p->pdf_creator[0] != '\0') {
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Creator ", 9);
|
|
|
|
written += t2p_write_pdf_string(t2p->pdf_creator, output);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2020-03-20 20:05:41 -04:00
|
|
|
}
|
|
|
|
if (!t2p->pdf_author_set) {
|
|
|
|
if ((TIFFGetField(input, TIFFTAG_ARTIST, &info) != 0
|
|
|
|
|| TIFFGetField(input, TIFFTAG_COPYRIGHT, &info) != 0)
|
|
|
|
&& info) {
|
|
|
|
strncpy(t2p->pdf_author, info, sizeof(t2p->pdf_author) - 1);
|
|
|
|
t2p->pdf_author[sizeof(t2p->pdf_author) - 1] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
if (t2p->pdf_author[0] != '\0') {
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Author ", 8);
|
|
|
|
written += t2p_write_pdf_string(t2p->pdf_author, output);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2020-03-20 20:05:41 -04:00
|
|
|
}
|
|
|
|
if (!t2p->pdf_title_set) {
|
|
|
|
if (TIFFGetField(input, TIFFTAG_DOCUMENTNAME, &info) != 0 && info) {
|
|
|
|
strncpy(t2p->pdf_title, info, sizeof(t2p->pdf_title) - 1);
|
|
|
|
t2p->pdf_title[sizeof(t2p->pdf_title) - 1] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
}
|
|
|
|
if (t2p->pdf_title[0] != '\0') {
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Title ", 7);
|
|
|
|
written += t2p_write_pdf_string(t2p->pdf_title, output);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2020-03-20 20:05:41 -04:00
|
|
|
}
|
|
|
|
if (!t2p->pdf_subject_set) {
|
|
|
|
if (TIFFGetField(input, TIFFTAG_IMAGEDESCRIPTION, &info) != 0 && info) {
|
|
|
|
strncpy(t2p->pdf_subject, info, sizeof(t2p->pdf_subject) - 1);
|
|
|
|
t2p->pdf_subject[sizeof(t2p->pdf_subject) - 1] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
if (t2p->pdf_subject[0] != '\0') {
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Subject ", 9);
|
|
|
|
written += t2p_write_pdf_string(t2p->pdf_subject, output);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
if (t2p->pdf_keywords[0] != '\0') {
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Keywords ", 10);
|
|
|
|
written += t2p_write_pdf_string(t2p->pdf_keywords, output);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2010-06-30 10:12:03 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ">> \n", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-06-08 07:27:11 -04:00
|
|
|
* This function fills a string of a T2P struct with the current time as a PDF
|
|
|
|
* date string, it is called by t2p_pdf_tifftime.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2006-06-08 07:27:11 -04:00
|
|
|
void t2p_pdf_currenttime(T2P* t2p)
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
struct tm* currenttime;
|
|
|
|
time_t timenow;
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
if (time(&timenow) == (time_t) -1) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Can't get the current time: %s", strerror(errno));
|
|
|
|
timenow = (time_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
currenttime = localtime(&timenow);
|
|
|
|
snprintf(t2p->pdf_datetime, sizeof(t2p->pdf_datetime),
|
2018-11-03 14:27:20 -04:00
|
|
|
"D:%.4u%.2u%.2u%.2u%.2u%.2u",
|
|
|
|
TIFFmin((unsigned) currenttime->tm_year + 1900U,9999U),
|
|
|
|
TIFFmin((unsigned) currenttime->tm_mon + 1U,12U), /* 0-11 + 1 */
|
|
|
|
TIFFmin((unsigned) currenttime->tm_mday,31U), /* 1-31 */
|
|
|
|
TIFFmin((unsigned) currenttime->tm_hour,23U), /* 0-23 */
|
|
|
|
TIFFmin((unsigned) currenttime->tm_min,59U), /* 0-59 */
|
|
|
|
TIFFmin((unsigned) (currenttime->tm_sec),60U)); /* 0-60 */
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-06-08 07:27:11 -04:00
|
|
|
* This function fills a string of a T2P struct with the date and time of a
|
|
|
|
* TIFF file if it exists or the current time as a PDF date string.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
void t2p_pdf_tifftime(T2P* t2p, TIFF* input)
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
char* datetime;
|
|
|
|
|
2010-06-30 10:12:03 -04:00
|
|
|
if (TIFFGetField(input, TIFFTAG_DATETIME, &datetime) != 0
|
2006-06-08 07:27:11 -04:00
|
|
|
&& (strlen(datetime) >= 19) ){
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_datetime[0]='D';
|
|
|
|
t2p->pdf_datetime[1]=':';
|
|
|
|
t2p->pdf_datetime[2]=datetime[0];
|
|
|
|
t2p->pdf_datetime[3]=datetime[1];
|
|
|
|
t2p->pdf_datetime[4]=datetime[2];
|
|
|
|
t2p->pdf_datetime[5]=datetime[3];
|
|
|
|
t2p->pdf_datetime[6]=datetime[5];
|
|
|
|
t2p->pdf_datetime[7]=datetime[6];
|
|
|
|
t2p->pdf_datetime[8]=datetime[8];
|
|
|
|
t2p->pdf_datetime[9]=datetime[9];
|
|
|
|
t2p->pdf_datetime[10]=datetime[11];
|
|
|
|
t2p->pdf_datetime[11]=datetime[12];
|
|
|
|
t2p->pdf_datetime[12]=datetime[14];
|
|
|
|
t2p->pdf_datetime[13]=datetime[15];
|
|
|
|
t2p->pdf_datetime[14]=datetime[17];
|
|
|
|
t2p->pdf_datetime[15]=datetime[18];
|
2010-06-30 10:12:03 -04:00
|
|
|
t2p->pdf_datetime[16] = '\0';
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
t2p_pdf_currenttime(t2p);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-06-08 07:27:11 -04:00
|
|
|
* This function writes a PDF Pages Tree structure to output.
|
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2006-06-08 07:27:11 -04:00
|
|
|
tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output)
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t written=0;
|
|
|
|
tdir_t i=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
|
|
|
int page=0;
|
2010-06-30 10:12:03 -04:00
|
|
|
written += t2pWriteFile(output,
|
2006-06-08 07:27:11 -04:00
|
|
|
(tdata_t) "<< \n/Type /Pages \n/Kids [ ", 26);
|
2003-11-25 11:39:22 -05:00
|
|
|
page = t2p->pdf_pages+1;
|
|
|
|
for (i=0;i<t2p->tiff_pagecount;i++){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%d", page);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
if ( ((i+1)%8)==0 ) {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
page +=3;
|
2003-12-01 05:51:39 -05:00
|
|
|
page += t2p->tiff_pages[i].page_extra;
|
|
|
|
if(t2p->tiff_pages[i].page_tilecount>0){
|
|
|
|
page += (2 * t2p->tiff_pages[i].page_tilecount);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
page +=2;
|
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "] \n/Count ", 10);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%d", t2p->tiff_pagecount);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " \n>> \n", 6);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Page structure to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){
|
|
|
|
|
2004-05-26 05:24:07 -04:00
|
|
|
unsigned int i=0;
|
2003-11-25 11:39:22 -05:00
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[256];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
2010-06-30 10:12:03 -04:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<<\n/Type /Page \n/Parent ", 24);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/MediaBox [", 11);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x2);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y2);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "] \n", 3);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Contents ", 10);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object + 1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Resources << \n", 15);
|
2003-12-01 05:51:39 -05:00
|
|
|
if( t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount != 0 ){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12);
|
2003-12-01 05:51:39 -05:00
|
|
|
for(i=0;i<t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount;i++){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Im", 3);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "_", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%u", i+1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(i%4==3){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>\n", 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Im", 3);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>\n", 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2004-09-10 07:50:57 -04:00
|
|
|
if(t2p->tiff_transferfunctioncount != 0) {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/ExtGState <<", 13);
|
|
|
|
t2pWriteFile(output, (tdata_t) "/GS1 ", 5);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(object + 3));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) ">> \n", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/ProcSet [ ", 11);
|
2013-09-20 11:35:37 -04:00
|
|
|
if(t2p->pdf_colorspace & T2P_CS_BILEVEL
|
|
|
|
|| t2p->pdf_colorspace & T2P_CS_GRAY
|
2003-11-25 11:39:22 -05:00
|
|
|
){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/ImageB ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/ImageC ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_colorspace & T2P_CS_PALETTE){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/ImageI ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "]\n>>\n>>\n", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function composes the page size and image and tile locations on a page.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void t2p_compose_pdf_page(T2P* t2p){
|
|
|
|
|
|
|
|
uint32 i=0;
|
|
|
|
uint32 i2=0;
|
|
|
|
T2P_TILE* tiles=NULL;
|
|
|
|
T2P_BOX* boxp=NULL;
|
|
|
|
uint32 tilecountx=0;
|
|
|
|
uint32 tilecounty=0;
|
|
|
|
uint32 tilewidth=0;
|
|
|
|
uint32 tilelength=0;
|
|
|
|
int istiled=0;
|
|
|
|
float f=0;
|
2010-12-11 17:47:49 -05:00
|
|
|
float width_ratio=0;
|
|
|
|
float length_ratio=0;
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
t2p->pdf_xres = t2p->tiff_xres;
|
|
|
|
t2p->pdf_yres = t2p->tiff_yres;
|
2007-02-24 11:28:48 -05:00
|
|
|
if(t2p->pdf_overrideres) {
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xres = t2p->pdf_defaultxres;
|
|
|
|
t2p->pdf_yres = t2p->pdf_defaultyres;
|
|
|
|
}
|
2007-02-24 11:28:48 -05:00
|
|
|
if(t2p->pdf_xres == 0.0)
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xres = t2p->pdf_defaultxres;
|
2007-02-24 11:28:48 -05:00
|
|
|
if(t2p->pdf_yres == 0.0)
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_yres = t2p->pdf_defaultyres;
|
2010-12-11 17:47:49 -05:00
|
|
|
if (t2p->pdf_image_fillpage) {
|
|
|
|
width_ratio = t2p->pdf_defaultpagewidth/t2p->tiff_width;
|
|
|
|
length_ratio = t2p->pdf_defaultpagelength/t2p->tiff_length;
|
|
|
|
if (width_ratio < length_ratio ) {
|
|
|
|
t2p->pdf_imagewidth = t2p->pdf_defaultpagewidth;
|
|
|
|
t2p->pdf_imagelength = t2p->tiff_length * width_ratio;
|
|
|
|
} else {
|
|
|
|
t2p->pdf_imagewidth = t2p->tiff_width * length_ratio;
|
|
|
|
t2p->pdf_imagelength = t2p->pdf_defaultpagelength;
|
|
|
|
}
|
|
|
|
} else if (t2p->tiff_resunit != RESUNIT_CENTIMETER /* RESUNIT_NONE and */
|
|
|
|
&& t2p->tiff_resunit != RESUNIT_INCH) { /* other cases */
|
2007-02-24 11:28:48 -05:00
|
|
|
t2p->pdf_imagewidth = ((float)(t2p->tiff_width))/t2p->pdf_xres;
|
|
|
|
t2p->pdf_imagelength = ((float)(t2p->tiff_length))/t2p->pdf_yres;
|
|
|
|
} else {
|
|
|
|
t2p->pdf_imagewidth =
|
|
|
|
((float)(t2p->tiff_width))*PS_UNIT_SIZE/t2p->pdf_xres;
|
|
|
|
t2p->pdf_imagelength =
|
|
|
|
((float)(t2p->tiff_length))*PS_UNIT_SIZE/t2p->pdf_yres;
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-02-24 11:28:48 -05:00
|
|
|
if(t2p->pdf_overridepagesize != 0) {
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_pagewidth = t2p->pdf_defaultpagewidth;
|
|
|
|
t2p->pdf_pagelength = t2p->pdf_defaultpagelength;
|
|
|
|
} else {
|
|
|
|
t2p->pdf_pagewidth = t2p->pdf_imagewidth;
|
|
|
|
t2p->pdf_pagelength = t2p->pdf_imagelength;
|
|
|
|
}
|
|
|
|
t2p->pdf_mediabox.x1=0.0;
|
|
|
|
t2p->pdf_mediabox.y1=0.0;
|
|
|
|
t2p->pdf_mediabox.x2=t2p->pdf_pagewidth;
|
|
|
|
t2p->pdf_mediabox.y2=t2p->pdf_pagelength;
|
|
|
|
t2p->pdf_imagebox.x1=0.0;
|
|
|
|
t2p->pdf_imagebox.y1=0.0;
|
|
|
|
t2p->pdf_imagebox.x2=t2p->pdf_imagewidth;
|
|
|
|
t2p->pdf_imagebox.y2=t2p->pdf_imagelength;
|
|
|
|
if(t2p->pdf_overridepagesize!=0){
|
2004-05-26 05:24:07 -04:00
|
|
|
t2p->pdf_imagebox.x1+=((t2p->pdf_pagewidth-t2p->pdf_imagewidth)/2.0F);
|
|
|
|
t2p->pdf_imagebox.y1+=((t2p->pdf_pagelength-t2p->pdf_imagelength)/2.0F);
|
|
|
|
t2p->pdf_imagebox.x2+=((t2p->pdf_pagewidth-t2p->pdf_imagewidth)/2.0F);
|
|
|
|
t2p->pdf_imagebox.y2+=((t2p->pdf_pagelength-t2p->pdf_imagelength)/2.0F);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation > 4){
|
|
|
|
f=t2p->pdf_mediabox.x2;
|
|
|
|
t2p->pdf_mediabox.x2=t2p->pdf_mediabox.y2;
|
|
|
|
t2p->pdf_mediabox.y2=f;
|
|
|
|
}
|
|
|
|
istiled=((t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount==0) ? 0 : 1;
|
|
|
|
if(istiled==0){
|
|
|
|
t2p_compose_pdf_page_orient(&(t2p->pdf_imagebox), t2p->tiff_orientation);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
tilewidth=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilewidth;
|
|
|
|
tilelength=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilelength;
|
2015-01-22 04:58:49 -05:00
|
|
|
if( tilewidth > INT_MAX ||
|
|
|
|
tilelength > INT_MAX ||
|
|
|
|
t2p->tiff_width > INT_MAX - tilewidth ||
|
|
|
|
t2p->tiff_length > INT_MAX - tilelength )
|
|
|
|
{
|
|
|
|
TIFFError(TIFF2PDF_MODULE, "Integer overflow");
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return;
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
tilecountx=(t2p->tiff_width +
|
|
|
|
tilewidth -1)/
|
|
|
|
tilewidth;
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecountx=tilecountx;
|
|
|
|
tilecounty=(t2p->tiff_length +
|
|
|
|
tilelength -1)/
|
|
|
|
tilelength;
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecounty=tilecounty;
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page]).tiles_edgetilewidth=
|
|
|
|
t2p->tiff_width % tilewidth;
|
|
|
|
(t2p->tiff_tiles[t2p->pdf_page]).tiles_edgetilelength=
|
|
|
|
t2p->tiff_length % tilelength;
|
|
|
|
tiles=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tiles;
|
|
|
|
for(i2=0;i2<tilecounty-1;i2++){
|
|
|
|
for(i=0;i<tilecountx-1;i++){
|
|
|
|
boxp=&(tiles[i2*tilecountx+i].tile_box);
|
|
|
|
boxp->x1 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * i * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->x2 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * (i+1) * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->y1 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * (i2+1) * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
boxp->y2 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * i2 * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
}
|
|
|
|
boxp=&(tiles[i2*tilecountx+i].tile_box);
|
|
|
|
boxp->x1 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * i * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->x2 = t2p->pdf_imagebox.x2;
|
|
|
|
boxp->y1 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * (i2+1) * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
boxp->y2 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * i2 * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
}
|
|
|
|
for(i=0;i<tilecountx-1;i++){
|
|
|
|
boxp=&(tiles[i2*tilecountx+i].tile_box);
|
|
|
|
boxp->x1 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * i * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->x2 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * (i+1) * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->y1 = t2p->pdf_imagebox.y1;
|
|
|
|
boxp->y2 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * i2 * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
}
|
|
|
|
boxp=&(tiles[i2*tilecountx+i].tile_box);
|
|
|
|
boxp->x1 =
|
|
|
|
t2p->pdf_imagebox.x1
|
|
|
|
+ ((float)(t2p->pdf_imagewidth * i * tilewidth)
|
|
|
|
/ (float)t2p->tiff_width);
|
|
|
|
boxp->x2 = t2p->pdf_imagebox.x2;
|
|
|
|
boxp->y1 = t2p->pdf_imagebox.y1;
|
|
|
|
boxp->y2 =
|
|
|
|
t2p->pdf_imagebox.y2
|
|
|
|
- ((float)(t2p->pdf_imagelength * i2 * tilelength)
|
|
|
|
/ (float)t2p->tiff_length);
|
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation==0 || t2p->tiff_orientation==1){
|
|
|
|
for(i=0;i<(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount;i++){
|
|
|
|
t2p_compose_pdf_page_orient( &(tiles[i].tile_box) , 0);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(i=0;i<(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount;i++){
|
|
|
|
boxp=&(tiles[i].tile_box);
|
|
|
|
boxp->x1 -= t2p->pdf_imagebox.x1;
|
|
|
|
boxp->x2 -= t2p->pdf_imagebox.x1;
|
|
|
|
boxp->y1 -= t2p->pdf_imagebox.y1;
|
|
|
|
boxp->y2 -= t2p->pdf_imagebox.y1;
|
|
|
|
if(t2p->tiff_orientation==2 || t2p->tiff_orientation==3){
|
|
|
|
boxp->x1 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x1;
|
|
|
|
boxp->x2 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x2;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation==3 || t2p->tiff_orientation==4){
|
|
|
|
boxp->y1 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y1;
|
|
|
|
boxp->y2 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y2;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation==8 || t2p->tiff_orientation==5){
|
|
|
|
boxp->y1 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y1;
|
|
|
|
boxp->y2 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y2;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation==5 || t2p->tiff_orientation==6){
|
|
|
|
boxp->x1 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x1;
|
|
|
|
boxp->x2 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x2;
|
|
|
|
}
|
|
|
|
if(t2p->tiff_orientation > 4){
|
|
|
|
f=boxp->x1;
|
|
|
|
boxp->x1 = boxp->y1;
|
|
|
|
boxp->y1 = f;
|
|
|
|
f=boxp->x2;
|
|
|
|
boxp->x2 = boxp->y2;
|
|
|
|
boxp->y2 = f;
|
|
|
|
t2p_compose_pdf_page_orient_flip(boxp, t2p->tiff_orientation);
|
|
|
|
} else {
|
|
|
|
t2p_compose_pdf_page_orient(boxp, t2p->tiff_orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){
|
|
|
|
|
|
|
|
float m1[9];
|
|
|
|
float f=0.0;
|
|
|
|
|
|
|
|
if( boxp->x1 > boxp->x2){
|
|
|
|
f=boxp->x1;
|
|
|
|
boxp->x1=boxp->x2;
|
|
|
|
boxp->x2 = f;
|
|
|
|
}
|
|
|
|
if( boxp->y1 > boxp->y2){
|
|
|
|
f=boxp->y1;
|
|
|
|
boxp->y1=boxp->y2;
|
|
|
|
boxp->y2 = f;
|
|
|
|
}
|
|
|
|
boxp->mat[0]=m1[0]=boxp->x2-boxp->x1;
|
|
|
|
boxp->mat[1]=m1[1]=0.0;
|
|
|
|
boxp->mat[2]=m1[2]=0.0;
|
|
|
|
boxp->mat[3]=m1[3]=0.0;
|
|
|
|
boxp->mat[4]=m1[4]=boxp->y2-boxp->y1;
|
|
|
|
boxp->mat[5]=m1[5]=0.0;
|
|
|
|
boxp->mat[6]=m1[6]=boxp->x1;
|
|
|
|
boxp->mat[7]=m1[7]=boxp->y1;
|
|
|
|
boxp->mat[8]=m1[8]=1.0;
|
|
|
|
switch(orientation){
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
case 2:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F-m1[0];
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[0];
|
|
|
|
break;
|
|
|
|
case 3:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F-m1[0];
|
|
|
|
boxp->mat[4]=0.0F-m1[4];
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[0];
|
|
|
|
boxp->mat[7]+=m1[4];
|
|
|
|
break;
|
|
|
|
case 4:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[4]=0.0F-m1[4];
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[7]+=m1[4];
|
|
|
|
break;
|
|
|
|
case 5:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
|
|
|
boxp->mat[1]=0.0F-m1[0];
|
|
|
|
boxp->mat[3]=0.0F-m1[4];
|
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[4];
|
|
|
|
boxp->mat[7]+=m1[0];
|
|
|
|
break;
|
|
|
|
case 6:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
|
|
|
boxp->mat[1]=0.0F-m1[0];
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[3]=m1[4];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[7]+=m1[0];
|
|
|
|
break;
|
|
|
|
case 7:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[1]=m1[0];
|
|
|
|
boxp->mat[3]=m1[4];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 8:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[1]=m1[0];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[3]=0.0F-m1[4];
|
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[4];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){
|
|
|
|
|
|
|
|
float m1[9];
|
|
|
|
float f=0.0;
|
|
|
|
|
|
|
|
if( boxp->x1 > boxp->x2){
|
|
|
|
f=boxp->x1;
|
|
|
|
boxp->x1=boxp->x2;
|
|
|
|
boxp->x2 = f;
|
|
|
|
}
|
|
|
|
if( boxp->y1 > boxp->y2){
|
|
|
|
f=boxp->y1;
|
|
|
|
boxp->y1=boxp->y2;
|
|
|
|
boxp->y2 = f;
|
|
|
|
}
|
|
|
|
boxp->mat[0]=m1[0]=boxp->x2-boxp->x1;
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[1]=m1[1]=0.0F;
|
|
|
|
boxp->mat[2]=m1[2]=0.0F;
|
|
|
|
boxp->mat[3]=m1[3]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[4]=m1[4]=boxp->y2-boxp->y1;
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[5]=m1[5]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]=m1[6]=boxp->x1;
|
|
|
|
boxp->mat[7]=m1[7]=boxp->y1;
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[8]=m1[8]=1.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
switch(orientation){
|
|
|
|
case 5:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
|
|
|
boxp->mat[1]=0.0F-m1[4];
|
|
|
|
boxp->mat[3]=0.0F-m1[0];
|
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[0];
|
|
|
|
boxp->mat[7]+=m1[4];
|
|
|
|
break;
|
|
|
|
case 6:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
|
|
|
boxp->mat[1]=0.0F-m1[4];
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[3]=m1[0];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[7]+=m1[4];
|
|
|
|
break;
|
|
|
|
case 7:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[1]=m1[4];
|
|
|
|
boxp->mat[3]=m1[0];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
case 8:
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[0]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[1]=m1[4];
|
2004-05-26 05:24:07 -04:00
|
|
|
boxp->mat[3]=0.0F-m1[0];
|
|
|
|
boxp->mat[4]=0.0F;
|
2003-11-25 11:39:22 -05:00
|
|
|
boxp->mat[6]+=m1[0];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Contents stream to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
ttile_t i=0;
|
|
|
|
char buffer[512];
|
|
|
|
int buflen=0;
|
|
|
|
T2P_BOX box;
|
|
|
|
|
|
|
|
if(t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount>0){
|
|
|
|
for(i=0;i<t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount; i++){
|
|
|
|
box=t2p->tiff_tiles[t2p->pdf_page].tiles_tiles[i].tile_box;
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer),
|
2006-04-21 11:09:34 -04:00
|
|
|
"q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d_%ld Do Q\n",
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->tiff_transferfunctioncount?"/GS1 gs ":"",
|
|
|
|
box.mat[0],
|
|
|
|
box.mat[1],
|
|
|
|
box.mat[3],
|
|
|
|
box.mat[4],
|
|
|
|
box.mat[6],
|
|
|
|
box.mat[7],
|
2005-09-13 09:40:48 -04:00
|
|
|
t2p->pdf_page + 1,
|
|
|
|
(long)(i + 1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_stream(buffer, buflen, output);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
box=t2p->pdf_imagebox;
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer),
|
2006-04-21 11:09:34 -04:00
|
|
|
"q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d Do Q\n",
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->tiff_transferfunctioncount?"/GS1 gs ":"",
|
|
|
|
box.mat[0],
|
|
|
|
box.mat[1],
|
|
|
|
box.mat[3],
|
|
|
|
box.mat[4],
|
|
|
|
box.mat[6],
|
|
|
|
box.mat[7],
|
|
|
|
t2p->pdf_page+1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_stream(buffer, buflen, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Image XObject stream dictionary to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile,
|
|
|
|
T2P* t2p,
|
|
|
|
TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
|
|
|
written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount+1, output);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output,
|
2006-04-21 11:09:34 -04:00
|
|
|
(tdata_t) "/Type /XObject \n/Subtype /Image \n/Name /Im",
|
2003-11-25 11:39:22 -05:00
|
|
|
42);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(tile != 0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "_", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)tile);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/Width ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(tile==0){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_width);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/Height ", 9);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(tile==0){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_length);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/BitsPerComponent ", 19);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/ColorSpace ", 13);
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_xobject_cs(t2p, output);
|
2005-05-05 16:52:57 -04:00
|
|
|
if (t2p->pdf_image_interpolate)
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output,
|
2006-04-21 11:09:34 -04:00
|
|
|
(tdata_t) "\n/Interpolate true", 18);
|
2003-11-25 11:39:22 -05:00
|
|
|
if( (t2p->pdf_switchdecode != 0)
|
|
|
|
#ifdef CCITT_SUPPORT
|
2013-09-20 11:35:37 -04:00
|
|
|
&& ! (t2p->pdf_colorspace & T2P_CS_BILEVEL
|
2003-11-25 11:39:22 -05:00
|
|
|
&& t2p->pdf_compression == T2P_COMPRESS_G4)
|
|
|
|
#endif
|
|
|
|
){
|
|
|
|
written += t2p_write_pdf_xobject_decode(t2p, output);
|
|
|
|
}
|
|
|
|
written += t2p_write_pdf_xobject_stream_filter(tile, t2p, output);
|
2005-05-05 16:52:57 -04:00
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
2020-03-24 06:34:36 -04:00
|
|
|
|
|
|
|
/* used to normalize the White Point */
|
|
|
|
#define normalizePoint(x,y,z) do { \
|
|
|
|
if (y != 0.0F) { \
|
|
|
|
x /= y; \
|
|
|
|
z /= y; \
|
|
|
|
y = 1.0F; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
/*
|
2020-04-04 18:13:13 -04:00
|
|
|
* This function writes a PDF Image XObject Colorspace name to output.
|
2005-05-05 16:52:57 -04:00
|
|
|
*/
|
|
|
|
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
char buffer[128];
|
|
|
|
int buflen=0;
|
|
|
|
|
|
|
|
float X_W=1.0;
|
|
|
|
float Y_W=1.0;
|
|
|
|
float Z_W=1.0;
|
|
|
|
|
|
|
|
if( (t2p->pdf_colorspace & T2P_CS_ICCBASED) != 0){
|
|
|
|
written += t2p_write_pdf_xobject_icccs(t2p, output);
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
if( (t2p->pdf_colorspace & T2P_CS_PALETTE) != 0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "[ /Indexed ", 11);
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_colorspace ^= T2P_CS_PALETTE;
|
|
|
|
written += t2p_write_pdf_xobject_cs(t2p, output);
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_PALETTE;
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", (0x0001 << t2p->tiff_bitspersample)-1 );
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " ", 1);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_palettecs );
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ]\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_BILEVEL){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DeviceGray \n", 13);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_GRAY){
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALGRAY){
|
|
|
|
written += t2p_write_pdf_xobject_calcs(t2p, output);
|
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DeviceGray \n", 13);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_RGB){
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALRGB){
|
|
|
|
written += t2p_write_pdf_xobject_calcs(t2p, output);
|
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DeviceRGB \n", 12);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CMYK){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DeviceCMYK \n", 13);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_LAB){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "[/Lab << \n", 10);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12);
|
2003-11-25 11:39:22 -05:00
|
|
|
X_W = t2p->tiff_whitechromaticities[0];
|
|
|
|
Y_W = t2p->tiff_whitechromaticities[1];
|
2004-05-26 05:24:07 -04:00
|
|
|
Z_W = 1.0F - (X_W + Y_W);
|
2020-03-24 06:34:36 -04:00
|
|
|
normalizePoint(X_W, Y_W, Z_W);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Range ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "[%d %d %d %d] \n",
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_labrange[0],
|
|
|
|
t2p->pdf_labrange[1],
|
|
|
|
t2p->pdf_labrange[2],
|
|
|
|
t2p->pdf_labrange[3]);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>] \n", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< /Type /ExtGState \n/TR ", 25);
|
2004-09-10 07:50:57 -04:00
|
|
|
if(t2p->tiff_transferfunctioncount == 1){
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(t2p->pdf_xrefcount + 1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "[ ", 2);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(t2p->pdf_xrefcount + 1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(t2p->pdf_xrefcount + 2));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)(t2p->pdf_xrefcount + 3));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R ", 5);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Identity ] ", 12);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " >> \n", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
char buffer[32];
|
|
|
|
int buflen=0;
|
2010-06-21 15:09:26 -04:00
|
|
|
(void)i; /* XXX */
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/FunctionType 0 \n", 17);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Domain [0.0 1.0] \n", 19);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Range [0.0 1.0] \n", 18);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "/Size [%u] \n", (1<<t2p->tiff_bitspersample));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/BitsPerSample 16 \n", 19);
|
2008-01-01 10:49:00 -05:00
|
|
|
written += t2p_write_pdf_stream_dict(((tsize_t)1)<<(t2p->tiff_bitspersample+1), 0, output);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
|
|
|
written += t2p_write_pdf_stream(
|
|
|
|
t2p->tiff_transferfunction[i],
|
2008-01-01 10:49:00 -05:00
|
|
|
(((tsize_t)1)<<(t2p->tiff_bitspersample+1)),
|
2003-11-25 11:39:22 -05:00
|
|
|
output);
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Image XObject Colorspace array to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[256];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
|
|
|
float X_W=0.0;
|
|
|
|
float Y_W=0.0;
|
|
|
|
float Z_W=0.0;
|
|
|
|
float X_R=0.0;
|
|
|
|
float Y_R=0.0;
|
|
|
|
float Z_R=0.0;
|
|
|
|
float X_G=0.0;
|
|
|
|
float Y_G=0.0;
|
|
|
|
float Z_G=0.0;
|
|
|
|
float X_B=0.0;
|
|
|
|
float Y_B=0.0;
|
|
|
|
float Z_B=0.0;
|
|
|
|
float x_w=0.0;
|
|
|
|
float y_w=0.0;
|
|
|
|
float z_w=0.0;
|
|
|
|
float x_r=0.0;
|
|
|
|
float y_r=0.0;
|
|
|
|
float x_g=0.0;
|
|
|
|
float y_g=0.0;
|
|
|
|
float x_b=0.0;
|
|
|
|
float y_b=0.0;
|
|
|
|
float R=1.0;
|
|
|
|
float G=1.0;
|
|
|
|
float B=1.0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "[", 1);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALGRAY){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/CalGray ", 9);
|
2003-11-25 11:39:22 -05:00
|
|
|
X_W = t2p->tiff_whitechromaticities[0];
|
|
|
|
Y_W = t2p->tiff_whitechromaticities[1];
|
2004-05-26 05:24:07 -04:00
|
|
|
Z_W = 1.0F - (X_W + Y_W);
|
2020-03-24 06:34:36 -04:00
|
|
|
normalizePoint(X_W, Y_W, Z_W);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALRGB){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/CalRGB ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
x_w = t2p->tiff_whitechromaticities[0];
|
|
|
|
y_w = t2p->tiff_whitechromaticities[1];
|
|
|
|
x_r = t2p->tiff_primarychromaticities[0];
|
|
|
|
y_r = t2p->tiff_primarychromaticities[1];
|
|
|
|
x_g = t2p->tiff_primarychromaticities[2];
|
|
|
|
y_g = t2p->tiff_primarychromaticities[3];
|
|
|
|
x_b = t2p->tiff_primarychromaticities[4];
|
|
|
|
y_b = t2p->tiff_primarychromaticities[5];
|
|
|
|
z_w = y_w * ((x_g - x_b)*y_r - (x_r-x_b)*y_g + (x_r-x_g)*y_b);
|
|
|
|
Y_R = (y_r/R) * ((x_g-x_b)*y_w - (x_w-x_b)*y_g + (x_w-x_g)*y_b) / z_w;
|
|
|
|
X_R = Y_R * x_r / y_r;
|
|
|
|
Z_R = Y_R * (((1-x_r)/y_r)-1);
|
2004-06-04 09:46:25 -04:00
|
|
|
Y_G = ((0.0F-(y_g))/G) * ((x_r-x_b)*y_w - (x_w-x_b)*y_r + (x_w-x_r)*y_b) / z_w;
|
2003-11-25 11:39:22 -05:00
|
|
|
X_G = Y_G * x_g / y_g;
|
|
|
|
Z_G = Y_G * (((1-x_g)/y_g)-1);
|
|
|
|
Y_B = (y_b/B) * ((x_r-x_g)*y_w - (x_w-x_g)*y_r + (x_w-x_r)*y_g) / z_w;
|
|
|
|
X_B = Y_B * x_b / y_b;
|
|
|
|
Z_B = Y_B * (((1-x_b)/y_b)-1);
|
|
|
|
X_W = (X_R * R) + (X_G * G) + (X_B * B);
|
|
|
|
Y_W = (Y_R * R) + (Y_G * G) + (Y_B * B);
|
|
|
|
Z_W = (Z_R * R) + (Z_G * G) + (Z_B * B);
|
2020-03-24 06:34:36 -04:00
|
|
|
normalizePoint(X_W, Y_W, Z_W);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< \n", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALGRAY){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Gamma 2.2 \n", 12);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p->pdf_colorspace & T2P_CS_CALRGB){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Matrix ", 8);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f] \n",
|
2003-11-25 11:39:22 -05:00
|
|
|
X_R, Y_R, Z_R,
|
|
|
|
X_G, Y_G, Z_G,
|
|
|
|
X_B, Y_B, Z_B);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Gamma [2.2 2.2 2.2] \n", 22);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>] \n", 5);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Image XObject Colorspace array to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "[/ICCBased ", 11);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_icccs);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R] \n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/N ", 3);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u \n", t2p->tiff_samplesperpixel);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Alternate ", 11);
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_colorspace ^= T2P_CS_ICCBASED;
|
|
|
|
written += t2p_write_pdf_xobject_cs(t2p, output);
|
|
|
|
t2p->pdf_colorspace |= T2P_CS_ICCBASED;
|
|
|
|
written += t2p_write_pdf_stream_dict(t2p->tiff_iccprofilelength, 0, output);
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
|
|
|
written += t2p_write_pdf_stream(
|
|
|
|
(tdata_t) t2p->tiff_iccprofile,
|
|
|
|
(tsize_t) t2p->tiff_iccprofilelength,
|
|
|
|
output);
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a palette stream for an indexed color space to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
|
|
|
|
written += t2p_write_pdf_stream(
|
|
|
|
(tdata_t) t2p->pdf_palette,
|
|
|
|
(tsize_t) t2p->pdf_palettesize,
|
|
|
|
output);
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Image XObject Decode array to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
int i=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Decode [ ", 10);
|
2003-11-25 11:39:22 -05:00
|
|
|
for (i=0;i<t2p->tiff_samplesperpixel;i++){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "1 0 ", 4);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "]\n", 2);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF Image XObject stream filter name and parameters to
|
|
|
|
output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[32];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
|
|
|
|
if(t2p->pdf_compression==T2P_COMPRESS_NONE){
|
|
|
|
return(written);
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Filter ", 8);
|
2003-11-25 11:39:22 -05:00
|
|
|
switch(t2p->pdf_compression){
|
|
|
|
#ifdef CCITT_SUPPORT
|
|
|
|
case T2P_COMPRESS_G4:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/CCITTFaxDecode ", 16);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< /K -1 ", 9);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(tile==0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Columns ", 9);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_width);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " /Rows ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_length);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
|
|
|
if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Columns ", 9);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/Columns ", 9);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " /Rows ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
} else {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " /Rows ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(t2p->pdf_switchdecode == 0){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) " /BlackIs1 true ", 16);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>\n", 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_SUPPORT
|
|
|
|
case T2P_COMPRESS_JPEG:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DCTDecode ", 11);
|
2006-02-07 09:28:48 -05:00
|
|
|
|
|
|
|
if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR) {
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13);
|
2015-06-14 16:54:32 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< /ColorTransform 1 >>\n", 24);
|
2006-02-07 09:28:48 -05:00
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef ZIP_SUPPORT
|
|
|
|
case T2P_COMPRESS_ZIP:
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/FlateDecode ", 13);
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_compressionquality%100){
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "<< /Predictor ", 14);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_compressionquality%100);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " /Columns ", 10);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->tiff_width);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " /Colors ", 9);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_samplesperpixel);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " /BitsPerComponent ", 19);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) ">>\n", 3);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function writes a PDF xref table to output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
2013-05-02 10:44:29 -04:00
|
|
|
char buffer[64];
|
2003-11-25 11:39:22 -05:00
|
|
|
int buflen=0;
|
|
|
|
uint32 i=0;
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "xref\n0 ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " \n0000000000 65535 f \n", 22);
|
2003-11-25 11:39:22 -05:00
|
|
|
for (i=0;i<t2p->pdf_xrefcount;i++){
|
2013-05-02 10:44:29 -04:00
|
|
|
snprintf(buffer, sizeof(buffer), "%.10lu 00000 n \n",
|
2005-09-13 09:40:48 -04:00
|
|
|
(unsigned long)t2p->pdf_xrefoffsets[i]);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, 20);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-06-08 07:27:11 -04:00
|
|
|
* This function writes a PDF trailer to output.
|
2005-06-23 09:28:33 -04:00
|
|
|
*/
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2005-06-23 09:28:33 -04:00
|
|
|
tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output)
|
|
|
|
{
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2005-06-23 09:28:33 -04:00
|
|
|
tsize_t written = 0;
|
2003-11-25 11:39:22 -05:00
|
|
|
char buffer[32];
|
2005-06-23 09:28:33 -04:00
|
|
|
int buflen = 0;
|
2010-06-30 12:04:50 -04:00
|
|
|
size_t i = 0;
|
|
|
|
|
2010-07-08 05:37:52 -04:00
|
|
|
for (i = 0; i < sizeof(t2p->pdf_fileid) - 8; i += 8)
|
2010-06-30 12:04:50 -04:00
|
|
|
snprintf(t2p->pdf_fileid + i, 9, "%.8X", rand());
|
2003-11-25 11:39:22 -05:00
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "trailer\n<<\n/Size ", 17);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount+1));
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n/Root ", 7);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_catalog);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n/Info ", 12);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_info);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) " 0 R \n/ID[<", 11);
|
2010-06-30 12:04:50 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid,
|
|
|
|
sizeof(t2p->pdf_fileid) - 1);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) "><", 2);
|
2010-06-30 12:04:50 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid,
|
|
|
|
sizeof(t2p->pdf_fileid) - 1);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) ">]\n>>\nstartxref\n", 16);
|
2013-05-02 10:44:29 -04:00
|
|
|
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_startxref);
|
From Yuriy M. Kaminskiy:
There are a lot of code like this:
buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number);
written += t2pWriteFile(output, (tdata_t) buffer, buflen );
in tiff2pdf. This is seriously broken: when formatted string is larger than
buffer, snprintf return value is >= sizeof(buffer) [current standard] or -1
[legacy]. And in case of other errors, snprintf returns -1.
Both would result in reading unallocated memory and possible SIGSEGV (DoS).
I doubt it can be really exploitable (to begin with, in most cases buffer was
large enough and sprintf->snprintf change was pure paranoia, IMO), but /if/ you
decided previous code was not safe and snprintf is necessary, /then/ you MUST
check its return value.
2015-06-13 01:14:57 -04:00
|
|
|
check_snprintf_ret(t2p, buflen, buffer);
|
2007-07-03 11:47:05 -04:00
|
|
|
written += t2pWriteFile(output, (tdata_t) buffer, buflen);
|
|
|
|
written += t2pWriteFile(output, (tdata_t) "\n%%EOF\n", 7);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This function writes a PDF to a file given a pointer to a TIFF.
|
|
|
|
|
|
|
|
The idea with using a TIFF* as output for a PDF file is that the file
|
|
|
|
can be created with TIFFClientOpen for memory-mapped use within the TIFF
|
|
|
|
library, and TIFFWriteEncodedStrip can be used to write compressed data to
|
|
|
|
the output. The output is not actually a TIFF file, it is a PDF file.
|
|
|
|
|
2007-07-03 11:47:05 -04:00
|
|
|
This function uses only t2pWriteFile and TIFFWriteEncodedStrip to write to
|
2003-11-25 11:39:22 -05:00
|
|
|
the output TIFF file. When libtiff would otherwise be writing data to the
|
|
|
|
output file, the write procedure of the TIFF structure is replaced with an
|
|
|
|
empty implementation.
|
|
|
|
|
|
|
|
The first argument to the function is an initialized and validated T2P
|
|
|
|
context struct pointer.
|
|
|
|
|
|
|
|
The second argument to the function is the TIFF* that is the input that has
|
|
|
|
been opened for reading and no other functions have been called upon it.
|
|
|
|
|
|
|
|
The third argument to the function is the TIFF* that is the output that has
|
|
|
|
been opened for writing. It has to be opened so that it hasn't written any
|
|
|
|
data to the output. If the output is seekable then it's OK to seek to the
|
|
|
|
beginning of the file. The function only writes to the output PDF and does
|
|
|
|
not seek. See the example usage in the main() function.
|
|
|
|
|
|
|
|
TIFF* output = TIFFOpen("output.pdf", "w");
|
|
|
|
assert(output != NULL);
|
|
|
|
|
|
|
|
if(output->tif_seekproc != NULL){
|
2007-07-03 11:47:05 -04:00
|
|
|
t2pSeekFile(output, (toff_t) 0, SEEK_SET);
|
2003-11-25 11:39:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
This function returns the file size of the output PDF file. On error it
|
|
|
|
returns zero and the t2p->t2p_error variable is set to T2P_ERR_ERROR.
|
|
|
|
|
|
|
|
After this function completes, call t2p_free on t2p, TIFFClose on input,
|
|
|
|
and TIFFClose on output.
|
|
|
|
*/
|
|
|
|
|
|
|
|
tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){
|
|
|
|
|
|
|
|
tsize_t written=0;
|
|
|
|
ttile_t i2=0;
|
|
|
|
tsize_t streamlen=0;
|
|
|
|
uint16 i=0;
|
|
|
|
|
|
|
|
t2p_read_tiff_init(t2p, input);
|
|
|
|
if(t2p->t2p_error!=T2P_ERR_OK){return(0);}
|
2014-12-09 21:53:30 -05:00
|
|
|
t2p->pdf_xrefoffsets= (uint32*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_xrefcount,sizeof(uint32)) );
|
2003-11-25 11:39:22 -05:00
|
|
|
if(t2p->pdf_xrefoffsets==NULL){
|
|
|
|
TIFFError(
|
2003-11-29 10:32:40 -05:00
|
|
|
TIFF2PDF_MODULE,
|
2008-12-31 18:48:01 -05:00
|
|
|
"Can't allocate %u bytes of memory for t2p_write_pdf",
|
2010-06-13 15:25:54 -04:00
|
|
|
(unsigned int) (t2p->pdf_xrefcount * sizeof(uint32)) );
|
2012-07-19 11:43:41 -04:00
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
2003-11-25 11:39:22 -05:00
|
|
|
return(written);
|
|
|
|
}
|
|
|
|
t2p->pdf_xrefcount=0;
|
|
|
|
t2p->pdf_catalog=1;
|
|
|
|
t2p->pdf_info=2;
|
|
|
|
t2p->pdf_pages=3;
|
|
|
|
written += t2p_write_pdf_header(t2p, output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
t2p->pdf_catalog=t2p->pdf_xrefcount;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_catalog(t2p, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
t2p->pdf_info=t2p->pdf_xrefcount;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_info(t2p, input, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
t2p->pdf_pages=t2p->pdf_xrefcount;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_pages(t2p, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
for(t2p->pdf_page=0;t2p->pdf_page<t2p->tiff_pagecount;t2p->pdf_page++){
|
|
|
|
t2p_read_tiff_data(t2p, input);
|
|
|
|
if(t2p->t2p_error!=T2P_ERR_OK){return(0);}
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_page(t2p->pdf_xrefcount, t2p, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount+1, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
|
|
|
streamlen=written;
|
|
|
|
written += t2p_write_pdf_page_content_stream(t2p, output);
|
|
|
|
streamlen=written-streamlen;
|
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_length(streamlen, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
if(t2p->tiff_transferfunctioncount != 0){
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_transfer(t2p, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
2004-09-10 07:50:57 -04:00
|
|
|
for(i=0; i < t2p->tiff_transferfunctioncount; i++){
|
2003-11-25 11:39:22 -05:00
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_transfer_dict(t2p, output, i);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_transfer_stream(t2p, output, i);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written-streamlen; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (t2p->pdf_colorspace & T2P_CS_PALETTE) != 0){
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
t2p->pdf_palettecs=t2p->pdf_xrefcount;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_stream_dict(t2p->pdf_palettesize, 0, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_xobject_palettecs_stream(t2p, output);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written-streamlen; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
}
|
|
|
|
if( (t2p->pdf_colorspace & T2P_CS_ICCBASED) != 0){
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
t2p->pdf_icccs=t2p->pdf_xrefcount;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_xobject_icccs_dict(t2p, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_xobject_icccs_stream(t2p, output);
|
2015-05-30 11:33:54 -04:00
|
|
|
/* streamlen=written-streamlen; */ /* value not used */
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
}
|
|
|
|
if(t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount !=0){
|
|
|
|
for(i2=0;i2<t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount;i2++){
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_xobject_stream_dict(
|
|
|
|
i2+1,
|
|
|
|
t2p,
|
|
|
|
output);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
|
|
|
streamlen=written;
|
|
|
|
t2p_read_tiff_size_tile(t2p, input, i2);
|
2020-11-17 18:34:43 -05:00
|
|
|
if (t2p->tiff_maxdatasize && (t2p->tiff_datasize > t2p->tiff_maxdatasize)) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Allocation of " TIFF_UINT64_FORMAT " bytes is forbidden. Limit is " TIFF_UINT64_FORMAT ". Use -m option to change limit",
|
|
|
|
(uint64)t2p->tiff_datasize, (uint64)t2p->tiff_maxdatasize);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_readwrite_pdf_image_tile(t2p, input, output, i2);
|
|
|
|
t2p_write_advance_directory(t2p, output);
|
|
|
|
if(t2p->t2p_error!=T2P_ERR_OK){return(0);}
|
|
|
|
streamlen=written-streamlen;
|
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_length(streamlen, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_dict_start(output);
|
|
|
|
written += t2p_write_pdf_xobject_stream_dict(
|
|
|
|
0,
|
|
|
|
t2p,
|
|
|
|
output);
|
|
|
|
written += t2p_write_pdf_stream_dict_end(output);
|
|
|
|
written += t2p_write_pdf_stream_start(output);
|
|
|
|
streamlen=written;
|
|
|
|
t2p_read_tiff_size(t2p, input);
|
2020-03-21 10:30:43 -04:00
|
|
|
if (t2p->tiff_maxdatasize && (t2p->tiff_datasize > t2p->tiff_maxdatasize)) {
|
|
|
|
TIFFError(TIFF2PDF_MODULE,
|
|
|
|
"Allocation of " TIFF_UINT64_FORMAT " bytes is forbidden. Limit is " TIFF_UINT64_FORMAT ". Use -m option to change limit",
|
|
|
|
(uint64)t2p->tiff_datasize, (uint64)t2p->tiff_maxdatasize);
|
|
|
|
t2p->t2p_error = T2P_ERR_ERROR;
|
|
|
|
return (0);
|
|
|
|
}
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_readwrite_pdf_image(t2p, input, output);
|
|
|
|
t2p_write_advance_directory(t2p, output);
|
|
|
|
if(t2p->t2p_error!=T2P_ERR_OK){return(0);}
|
|
|
|
streamlen=written-streamlen;
|
|
|
|
written += t2p_write_pdf_stream_end(output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written;
|
|
|
|
written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output);
|
|
|
|
written += t2p_write_pdf_stream_length(streamlen, output);
|
|
|
|
written += t2p_write_pdf_obj_end(output);
|
|
|
|
}
|
|
|
|
}
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p->pdf_startxref = written;
|
2003-11-25 11:39:22 -05:00
|
|
|
written += t2p_write_pdf_xreftable(t2p, output);
|
|
|
|
written += t2p_write_pdf_trailer(t2p, output);
|
2007-07-03 11:47:05 -04:00
|
|
|
t2p_disable(output);
|
2003-11-25 11:39:22 -05:00
|
|
|
|
|
|
|
return(written);
|
2004-01-26 12:00:55 -05:00
|
|
|
}
|
2004-09-10 07:50:57 -04:00
|
|
|
|
|
|
|
/* vim: set ts=8 sts=8 sw=8 noet: */
|
2010-03-10 13:56:48 -05:00
|
|
|
/*
|
|
|
|
* Local Variables:
|
|
|
|
* mode: c
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* fill-column: 78
|
|
|
|
* End:
|
|
|
|
*/
|