/* * Strip -> strip for change in encoding. */ bool cpDecodedStrips(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp) { int stripsize = inImage.StripSize(); byte[] buf = new byte[stripsize]; int ns = inImage.NumberOfStrips(); int row = 0; for (int s = 0; s < ns; s++) { int cc = (row + m_rowsperstrip > imagelength) ? inImage.VStripSize(imagelength - row) : stripsize; if (inImage.ReadEncodedStrip(s, buf, 0, cc) < 0 && !m_ignore) { Tiff.Error(inImage.FileName(), "Error, can't read strip {0}", s); return false; } if (outImage.WriteEncodedStrip(s, buf, cc) < 0) { Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", s); return false; } row += m_rowsperstrip; } return true; }
/* 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. It determines if the image can be converted as raw data without requiring transcoding of the image data. */ private void read_tiff_data(Tiff input) { m_pdf_transcode = t2p_transcode_t.T2P_TRANSCODE_ENCODE; m_pdf_sample = t2p_sample_t.T2P_SAMPLE_NOTHING; m_pdf_switchdecode = m_pdf_colorspace_invert; input.SetDirectory(m_tiff_pages[m_pdf_page].page_directory); FieldValue[] result = input.GetField(TiffTag.IMAGEWIDTH); m_tiff_width = result[0].ToInt(); if (m_tiff_width == 0) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with zero width", input.FileName()); m_error = true; return; } result = input.GetField(TiffTag.IMAGELENGTH); m_tiff_length = result[0].ToInt(); if (m_tiff_length == 0) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with zero length", input.FileName()); m_error = true; return; } result = input.GetField(TiffTag.COMPRESSION); if (result == null) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with no compression tag", input.FileName()); m_error = true; return; } else m_tiff_compression = (Compression)result[0].ToInt(); if (!input.IsCodecConfigured(m_tiff_compression)) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with compression type {1}: not configured", input.FileName(), m_tiff_compression); m_error = true; return; } result = input.GetFieldDefaulted(TiffTag.BITSPERSAMPLE); m_tiff_bitspersample = result[0].ToShort(); switch (m_tiff_bitspersample) { case 1: case 2: case 4: case 8: break; case 0: Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "Image {0} has 0 bits per sample, assuming 1", input.FileName()); m_tiff_bitspersample = 1; break; default: Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with {1} bits per sample", input.FileName(), m_tiff_bitspersample); m_error = true; return; } result = input.GetFieldDefaulted(TiffTag.SAMPLESPERPIXEL); m_tiff_samplesperpixel = result[0].ToShort(); if (m_tiff_samplesperpixel > 4) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with {1} samples per pixel", input.FileName(), m_tiff_samplesperpixel); m_error = true; return; } if (m_tiff_samplesperpixel == 0) { Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "Image {0} has 0 samples per pixel, assuming 1", input.FileName()); m_tiff_samplesperpixel = 1; } result = input.GetField(TiffTag.SAMPLEFORMAT); if (result != null) { SampleFormat f = (SampleFormat)result[0].ToByte(); switch (f) { case 0: case SampleFormat.UINT: case SampleFormat.VOID: break; default: Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with sample format {1}", input.FileName(), f); m_error = true; return; } } result = input.GetFieldDefaulted(TiffTag.FILLORDER); m_tiff_fillorder = (FillOrder)result[0].ToByte(); result = input.GetField(TiffTag.PHOTOMETRIC); if (result == null) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with no photometric interpretation tag", input.FileName()); m_error = true; return; } else m_tiff_photometric = (Photometric)result[0].ToInt(); short[] r; short[] g; short[] b; short[] a; bool photometric_palette; bool photometric_palette_cmyk; switch (m_tiff_photometric) { case Photometric.MINISWHITE: case Photometric.MINISBLACK: if (m_tiff_bitspersample == 1) { m_pdf_colorspace = t2p_cs_t.T2P_CS_BILEVEL; if (m_tiff_photometric == Photometric.MINISWHITE) m_pdf_switchdecode ^= true; } else { m_pdf_colorspace = t2p_cs_t.T2P_CS_GRAY; if (m_tiff_photometric == Photometric.MINISWHITE) m_pdf_switchdecode ^= true; } break; case Photometric.RGB: case Photometric.PALETTE: photometric_palette = (m_tiff_photometric == Photometric.PALETTE); if (!photometric_palette) { m_pdf_colorspace = t2p_cs_t.T2P_CS_RGB; if (m_tiff_samplesperpixel == 3) break; result = input.GetField(TiffTag.INDEXED); if (result != null) { if (result[0].ToInt() == 1) photometric_palette = true; } } if (!photometric_palette) { if (m_tiff_samplesperpixel > 3) { if (m_tiff_samplesperpixel == 4) { m_pdf_colorspace = t2p_cs_t.T2P_CS_RGB; result = input.GetField(TiffTag.EXTRASAMPLES); if (result != null && result[0].ToInt() == 1) { byte[] xuint16p = result[1].ToByteArray(); if ((ExtraSample)xuint16p[0] == ExtraSample.ASSOCALPHA) { m_pdf_sample = t2p_sample_t.T2P_SAMPLE_RGBAA_TO_RGB; break; } if ((ExtraSample)xuint16p[0] == ExtraSample.UNASSALPHA) { m_pdf_sample = t2p_sample_t.T2P_SAMPLE_RGBA_TO_RGB; break; } Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "RGB image {0} has 4 samples per pixel, assuming RGBA", input.FileName()); break; } m_pdf_colorspace = t2p_cs_t.T2P_CS_CMYK; m_pdf_switchdecode ^= true; Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "RGB image {0} has 4 samples per pixel, assuming inverse CMYK", input.FileName()); break; } else { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for RGB image {0} with {1} samples per pixel", input.FileName(), m_tiff_samplesperpixel); m_error = true; break; } } else { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for RGB image {0} with {1} samples per pixel", input.FileName(), m_tiff_samplesperpixel); m_error = true; break; } } if (photometric_palette) { if (m_tiff_samplesperpixel != 1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for palletized image {0} with not one sample per pixel", input.FileName()); m_error = true; return; } m_pdf_colorspace = (t2p_cs_t)(t2p_cs_t.T2P_CS_RGB | t2p_cs_t.T2P_CS_PALETTE); m_pdf_palettesize = 0x0001 << m_tiff_bitspersample; result = input.GetField(TiffTag.COLORMAP); if (result == null) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Palletized image {0} has no color map", input.FileName()); m_error = true; return; } else { r = result[0].ToShortArray(); g = result[1].ToShortArray(); b = result[2].ToShortArray(); } m_pdf_palette = new byte [m_pdf_palettesize * 3]; for (int i = 0; i < m_pdf_palettesize; i++) { m_pdf_palette[i * 3] = (byte)(r[i] >> 8); m_pdf_palette[i * 3 + 1] = (byte)(g[i] >> 8); m_pdf_palette[i * 3 + 2] = (byte)(b[i] >> 8); } m_pdf_palettesize *= 3; } break; case Photometric.SEPARATED: photometric_palette_cmyk = false; result = input.GetField(TiffTag.INDEXED); if (result != null) { if (result[0].ToInt() == 1) photometric_palette_cmyk = true; } if (!photometric_palette_cmyk) { result = input.GetField(TiffTag.INKSET); if (result != null) { if ((InkSet)result[0].ToByte() != InkSet.CMYK) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} because its inkset is not CMYK", input.FileName()); m_error = true; return; } } if (m_tiff_samplesperpixel == 4) { m_pdf_colorspace = t2p_cs_t.T2P_CS_CMYK; } else { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} because it has {1} samples per pixel", input.FileName(), m_tiff_samplesperpixel); m_error = true; return; } } else { if (m_tiff_samplesperpixel != 1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for palletized CMYK image {0} with not one sample per pixel", input.FileName()); m_error = true; return; } m_pdf_colorspace = (t2p_cs_t)(t2p_cs_t.T2P_CS_CMYK | t2p_cs_t.T2P_CS_PALETTE); m_pdf_palettesize = 0x0001 << m_tiff_bitspersample; result = input.GetField(TiffTag.COLORMAP); if (result == null) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Palletized image {0} has no color map", input.FileName()); m_error = true; return; } else { r = result[0].ToShortArray(); g = result[1].ToShortArray(); b = result[2].ToShortArray(); a = result[3].ToShortArray(); } m_pdf_palette = new byte [m_pdf_palettesize * 4]; for (int i = 0; i < m_pdf_palettesize; i++) { m_pdf_palette[i * 4] = (byte)(r[i] >> 8); m_pdf_palette[i * 4 + 1] = (byte)(g[i] >> 8); m_pdf_palette[i * 4 + 2] = (byte)(b[i] >> 8); m_pdf_palette[i * 4 + 3] = (byte)(a[i] >> 8); } m_pdf_palettesize *= 4; } break; case Photometric.YCBCR: m_pdf_colorspace = t2p_cs_t.T2P_CS_RGB; if (m_tiff_samplesperpixel == 1) { m_pdf_colorspace = t2p_cs_t.T2P_CS_GRAY; m_tiff_photometric = Photometric.MINISBLACK; break; } m_pdf_sample = t2p_sample_t.T2P_SAMPLE_YCBCR_TO_RGB; if (m_pdf_defaultcompression == t2p_compress_t.T2P_COMPRESS_JPEG) m_pdf_sample = t2p_sample_t.T2P_SAMPLE_NOTHING; break; case Photometric.CIELAB: m_pdf_labrange[0] = -127; m_pdf_labrange[1] = 127; m_pdf_labrange[2] = -127; m_pdf_labrange[3] = 127; m_pdf_sample = t2p_sample_t.T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED; m_pdf_colorspace = t2p_cs_t.T2P_CS_LAB; break; case Photometric.ICCLAB: m_pdf_labrange[0] = 0; m_pdf_labrange[1] = 255; m_pdf_labrange[2] = 0; m_pdf_labrange[3] = 255; m_pdf_colorspace = t2p_cs_t.T2P_CS_LAB; break; case Photometric.ITULAB: m_pdf_labrange[0] = -85; m_pdf_labrange[1] = 85; m_pdf_labrange[2] = -75; m_pdf_labrange[3] = 124; m_pdf_sample = t2p_sample_t.T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED; m_pdf_colorspace = t2p_cs_t.T2P_CS_LAB; break; case Photometric.LOGL: case Photometric.LOGLUV: Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with photometric interpretation LogL/LogLuv", input.FileName()); m_error = true; return; default: Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with photometric interpretation {1}", input.FileName(), m_tiff_photometric); m_error = true; return; } result = input.GetField(TiffTag.PLANARCONFIG); if (result != null) { m_tiff_planar = (PlanarConfig)result[0].ToShort(); switch (m_tiff_planar) { case 0: Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "Image {0} has planar configuration 0, assuming 1", input.FileName()); m_tiff_planar = PlanarConfig.CONTIG; break; case PlanarConfig.CONTIG: break; case PlanarConfig.SEPARATE: m_pdf_sample = t2p_sample_t.T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG; if (m_tiff_bitspersample != 8) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with separated planar configuration and {1} bits per sample", input.FileName(), m_tiff_bitspersample); m_error = true; return; } break; default: Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with planar configuration {1}", input.FileName(), m_tiff_planar); m_error = true; return; } } result = input.GetFieldDefaulted(TiffTag.ORIENTATION); m_tiff_orientation = (Orientation)result[0].ToByte(); if (m_tiff_orientation > Orientation.LEFTBOT) { Tiff.Warning(Tiff2PdfConstants.TIFF2PDF_MODULE, "Image {0} has orientation {1}, assuming 0", input.FileName(), m_tiff_orientation); m_tiff_orientation = 0; } result = input.GetField(TiffTag.XRESOLUTION); if (result == null) m_tiff_xres = 0.0f; else m_tiff_xres = result[0].ToFloat(); result = input.GetField(TiffTag.YRESOLUTION); if (result == null) m_tiff_yres = 0.0f; else m_tiff_yres = result[0].ToFloat(); result = input.GetFieldDefaulted(TiffTag.RESOLUTIONUNIT); m_tiff_resunit = (ResUnit)result[0].ToByte(); if (m_tiff_resunit == ResUnit.CENTIMETER) { m_tiff_xres *= 2.54F; m_tiff_yres *= 2.54F; } else if (m_tiff_resunit != ResUnit.INCH && m_pdf_centimeters) { m_tiff_xres *= 2.54F; m_tiff_yres *= 2.54F; } compose_pdf_page(); m_pdf_transcode = t2p_transcode_t.T2P_TRANSCODE_ENCODE; if (!m_pdf_nopassthrough) { if (m_tiff_compression == Compression.CCITTFAX4) { if (input.IsTiled() || (input.NumberOfStrips() == 1)) { m_pdf_transcode = t2p_transcode_t.T2P_TRANSCODE_RAW; m_pdf_compression = t2p_compress_t.T2P_COMPRESS_G4; } } if (m_tiff_compression == Compression.ADOBE_DEFLATE || m_tiff_compression == Compression.DEFLATE) { if (input.IsTiled() || (input.NumberOfStrips() == 1)) { m_pdf_transcode = t2p_transcode_t.T2P_TRANSCODE_RAW; m_pdf_compression = t2p_compress_t.T2P_COMPRESS_ZIP; } } if (m_tiff_compression == Compression.JPEG) { m_pdf_transcode = t2p_transcode_t.T2P_TRANSCODE_RAW; m_pdf_compression = t2p_compress_t.T2P_COMPRESS_JPEG; } } if (m_pdf_transcode != t2p_transcode_t.T2P_TRANSCODE_RAW) m_pdf_compression = m_pdf_defaultcompression; if (m_pdf_defaultcompression == t2p_compress_t.T2P_COMPRESS_JPEG) { if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_PALETTE) != 0) { m_pdf_sample = (t2p_sample_t)(m_pdf_sample | t2p_sample_t.T2P_SAMPLE_REALIZE_PALETTE); m_pdf_colorspace = (t2p_cs_t)(m_pdf_colorspace ^ t2p_cs_t.T2P_CS_PALETTE); m_tiff_pages[m_pdf_page].page_extra--; } } if (m_tiff_compression == Compression.JPEG) { if (m_tiff_planar == PlanarConfig.SEPARATE) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for {0} with JPEG compression and separated planar configuration", input.FileName()); m_error = true; return; } } if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_REALIZE_PALETTE) != 0) { if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_CMYK) != 0) { m_tiff_samplesperpixel = 4; m_tiff_photometric = Photometric.SEPARATED; } else { m_tiff_samplesperpixel = 3; m_tiff_photometric = Photometric.RGB; } } result = input.GetField(TiffTag.TRANSFERFUNCTION); if (result != null) { m_tiff_transferfunction[0] = result[0].GetBytes(); m_tiff_transferfunction[1] = result[1].GetBytes(); m_tiff_transferfunction[2] = result[2].GetBytes(); if (m_tiff_transferfunction[1] != m_tiff_transferfunction[0]) m_tiff_transferfunctioncount = 3; else m_tiff_transferfunctioncount = 1; } else { m_tiff_transferfunctioncount = 0; } result = input.GetField(TiffTag.WHITEPOINT); if (result != null) { float[] xfloatp = result[0].ToFloatArray(); m_tiff_whitechromaticities[0] = xfloatp[0]; m_tiff_whitechromaticities[1] = xfloatp[1]; if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_GRAY) != 0) m_pdf_colorspace = (t2p_cs_t)(m_pdf_colorspace | t2p_cs_t.T2P_CS_CALGRAY); if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_RGB) != 0) m_pdf_colorspace = (t2p_cs_t)(m_pdf_colorspace | t2p_cs_t.T2P_CS_CALRGB); } result = input.GetField(TiffTag.PRIMARYCHROMATICITIES); if (result != null) { float[] xfloatp = result[0].ToFloatArray(); m_tiff_primarychromaticities[0] = xfloatp[0]; m_tiff_primarychromaticities[1] = xfloatp[1]; m_tiff_primarychromaticities[2] = xfloatp[2]; m_tiff_primarychromaticities[3] = xfloatp[3]; m_tiff_primarychromaticities[4] = xfloatp[4]; m_tiff_primarychromaticities[5] = xfloatp[5]; if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_RGB) != 0) m_pdf_colorspace = (t2p_cs_t)(m_pdf_colorspace | t2p_cs_t.T2P_CS_CALRGB); } if ((m_pdf_colorspace & t2p_cs_t.T2P_CS_LAB) != 0) { result = input.GetField(TiffTag.WHITEPOINT); if (result != null) { float[] xfloatp = result[0].ToFloatArray(); m_tiff_whitechromaticities[0] = xfloatp[0]; m_tiff_whitechromaticities[1] = xfloatp[1]; } else { m_tiff_whitechromaticities[0] = 0.3457F; /* 0.3127F; */ m_tiff_whitechromaticities[1] = 0.3585F; /* 0.3290F; */ } } result = input.GetField(TiffTag.ICCPROFILE); if (result != null) { m_tiff_iccprofilelength = result[0].ToInt(); m_tiff_iccprofile = result[1].ToByteArray(); m_pdf_colorspace = (t2p_cs_t)(m_pdf_colorspace | t2p_cs_t.T2P_CS_ICCBASED); } else { m_tiff_iccprofilelength = 0; m_tiff_iccprofile = null; } if (m_tiff_bitspersample == 1 && m_tiff_samplesperpixel == 1) m_pdf_compression = t2p_compress_t.T2P_COMPRESS_G4; }
/* 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. */ private int readwrite_pdf_image(Tiff input) { byte[] buffer = null; int bufferoffset = 0; int stripcount = 0; int max_striplength = 0; FieldValue[] result = null; if (m_pdf_transcode == t2p_transcode_t.T2P_TRANSCODE_RAW) { if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_G4) { buffer = new byte [m_tiff_datasize]; input.ReadRawStrip(0, buffer, 0, m_tiff_datasize); if (m_tiff_fillorder == FillOrder.LSB2MSB) { /* * make sure is lsb-to-msb * bit-endianness fill order */ Tiff.ReverseBits(buffer, m_tiff_datasize); } writeToFile(buffer, m_tiff_datasize); return m_tiff_datasize; } if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_ZIP) { buffer = new byte [m_tiff_datasize]; input.ReadRawStrip(0, buffer, 0, m_tiff_datasize); if (m_tiff_fillorder == FillOrder.LSB2MSB) Tiff.ReverseBits(buffer, m_tiff_datasize); writeToFile(buffer, m_tiff_datasize); return m_tiff_datasize; } if (m_tiff_compression == Compression.JPEG) { buffer = new byte [m_tiff_datasize]; result = input.GetField(TiffTag.JPEGTABLES); if (result != null) { int count = result[0].ToInt(); byte[] jpt = result[1].ToByteArray(); if (count > 4) { Buffer.BlockCopy(jpt, 0, buffer, 0, count); bufferoffset += count - 2; } } stripcount = input.NumberOfStrips(); result = input.GetField(TiffTag.STRIPBYTECOUNTS); int[] sbc = result[0].ToIntArray(); for (int i = 0; i < stripcount; i++) { if (sbc[i] > max_striplength) max_striplength = sbc[i]; } byte[] stripbuffer = new byte [max_striplength]; for (int i = 0; i < stripcount; i++) { int striplength = input.ReadRawStrip(i, stripbuffer, 0, -1); if (!process_jpeg_strip(stripbuffer, striplength, buffer, ref bufferoffset, stripcount, i, m_tiff_length)) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Can't process JPEG data in input file {0}", input.FileName()); m_error = true; return 0; } } buffer[bufferoffset++] = 0xff; buffer[bufferoffset++] = 0xd9; writeToFile(buffer, bufferoffset); return bufferoffset; } } int stripsize = 0; if (m_pdf_sample == t2p_sample_t.T2P_SAMPLE_NOTHING) { buffer = new byte [m_tiff_datasize]; stripsize = input.StripSize(); stripcount = input.NumberOfStrips(); for (int i = 0; i < stripcount; i++) { int read = input.ReadEncodedStrip(i, buffer, bufferoffset, stripsize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding strip {0} of {1}", i, input.FileName()); m_error = true; return 0; } bufferoffset += read; } } else { byte[] samplebuffer = null; bool dataready = false; if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG) != 0) { int sepstripsize = input.StripSize(); int sepstripcount = input.NumberOfStrips(); stripsize = sepstripsize * m_tiff_samplesperpixel; stripcount = sepstripcount / m_tiff_samplesperpixel; buffer = new byte [m_tiff_datasize]; samplebuffer = new byte [stripsize]; for (int i = 0; i < stripcount; i++) { int samplebufferoffset = 0; for (int j = 0; j < m_tiff_samplesperpixel; j++) { int read = input.ReadEncodedStrip(i + j * stripcount, samplebuffer, samplebufferoffset, sepstripsize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding strip {0} of {1}", i + j * stripcount, input.FileName()); m_error = true; return 0; } samplebufferoffset += read; } sample_planar_separate_to_contig(buffer, bufferoffset, samplebuffer, samplebufferoffset); bufferoffset += samplebufferoffset; } dataready = true; } if (!dataready) { buffer = new byte [m_tiff_datasize]; stripsize = input.StripSize(); stripcount = input.NumberOfStrips(); for (int i = 0; i < stripcount; i++) { int read = input.ReadEncodedStrip(i, buffer, bufferoffset, stripsize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding strip {0} of {1}", i, input.FileName()); m_error = true; return 0; } bufferoffset += read; } if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_REALIZE_PALETTE) != 0) { samplebuffer = Tiff.Realloc(buffer, m_tiff_datasize * m_tiff_samplesperpixel); buffer = samplebuffer; m_tiff_datasize *= m_tiff_samplesperpixel; sample_realize_palette(buffer); } if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_RGBA_TO_RGB) != 0) m_tiff_datasize = sample_rgba_to_rgb(buffer, m_tiff_width * m_tiff_length); if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_RGBAA_TO_RGB) != 0) m_tiff_datasize = sample_rgbaa_to_rgb(buffer, m_tiff_width * m_tiff_length); if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_YCBCR_TO_RGB) != 0) { samplebuffer = Tiff.Realloc(buffer, m_tiff_width * m_tiff_length * 4); buffer = samplebuffer; int[] buffer32 = Tiff.ByteArrayToInts(buffer, 0, m_tiff_width * m_tiff_length * 4); if (!input.ReadRGBAImageOriented(m_tiff_width, m_tiff_length, buffer32, Orientation.TOPLEFT, false)) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Can't use ReadRGBAImageOriented to extract RGB image from {0}", input.FileName()); m_error = true; return 0; } Tiff.IntsToByteArray(buffer32, 0, m_tiff_width * m_tiff_length, buffer, 0); m_tiff_datasize = sample_abgr_to_rgb(buffer, m_tiff_width * m_tiff_length); } if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED) != 0) m_tiff_datasize = sample_lab_signed_to_unsigned(buffer, m_tiff_width * m_tiff_length); } } disable(m_output); m_output.SetField(TiffTag.PHOTOMETRIC, m_tiff_photometric); m_output.SetField(TiffTag.BITSPERSAMPLE, m_tiff_bitspersample); m_output.SetField(TiffTag.SAMPLESPERPIXEL, m_tiff_samplesperpixel); m_output.SetField(TiffTag.IMAGEWIDTH, m_tiff_width); m_output.SetField(TiffTag.IMAGELENGTH, m_tiff_length); m_output.SetField(TiffTag.ROWSPERSTRIP, m_tiff_length); m_output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG); m_output.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB); switch (m_pdf_compression) { case t2p_compress_t.T2P_COMPRESS_NONE: m_output.SetField(TiffTag.COMPRESSION, Compression.NONE); break; case t2p_compress_t.T2P_COMPRESS_G4: m_output.SetField(TiffTag.COMPRESSION, Compression.CCITTFAX4); break; case t2p_compress_t.T2P_COMPRESS_JPEG: if (m_tiff_photometric == Photometric.YCBCR) { result = input.GetField(TiffTag.YCBCRSUBSAMPLING); if (result != null) { short hor = result[0].ToShort(); short ver = result[1].ToShort(); if (hor != 0 && ver != 0) m_output.SetField(TiffTag.YCBCRSUBSAMPLING, hor, ver); } result = input.GetField(TiffTag.REFERENCEBLACKWHITE); if (result != null) { float[] xfloatp = result[0].ToFloatArray(); m_output.SetField(TiffTag.REFERENCEBLACKWHITE, xfloatp); } } if (!m_output.SetField(TiffTag.COMPRESSION, Compression.JPEG)) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Unable to use JPEG compression for input {0} and output {1}", input.FileName(), m_output.FileName()); m_error = true; return 0; } m_output.SetField(TiffTag.JPEGTABLESMODE, 0); if ((m_pdf_colorspace & (t2p_cs_t.T2P_CS_RGB | t2p_cs_t.T2P_CS_LAB)) != 0) { m_output.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR); if (m_tiff_photometric != Photometric.YCBCR) m_output.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RGB); else m_output.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RAW); } if (m_pdf_defaultcompressionquality != 0) m_output.SetField(TiffTag.JPEGQUALITY, m_pdf_defaultcompressionquality); break; case t2p_compress_t.T2P_COMPRESS_ZIP: m_output.SetField(TiffTag.COMPRESSION, Compression.DEFLATE); if (m_pdf_defaultcompressionquality % 100 != 0) m_output.SetField(TiffTag.PREDICTOR, m_pdf_defaultcompressionquality % 100); if (m_pdf_defaultcompressionquality / 100 != 0) m_output.SetField(TiffTag.ZIPQUALITY, (m_pdf_defaultcompressionquality / 100)); break; default: break; } enable(m_output); m_outputwritten = 0; if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_JPEG && m_tiff_photometric == Photometric.YCBCR) bufferoffset = m_output.WriteEncodedStrip(0, buffer, stripsize * stripcount); else bufferoffset = m_output.WriteEncodedStrip(0, buffer, m_tiff_datasize); buffer = null; if (bufferoffset == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error writing encoded strip to output PDF {0}", m_output.FileName()); m_error = true; return 0; } return m_outputwritten; }
/* 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. */ private void read_tiff_init(Tiff input) { short directorycount = input.NumberOfDirectories(); m_tiff_pages = new T2P_PAGE [directorycount]; for (int p = 0; p < directorycount; p++) m_tiff_pages[p] = new T2P_PAGE(); FieldValue[] result = null; for (short i = 0; i < directorycount; i++) { int subfiletype = 0; if (!input.SetDirectory(i)) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Can't set directory {0} of input file {1}", i, input.FileName()); return; } result = input.GetField(TiffTag.PAGENUMBER); if (result != null) { short pagen = result[0].ToShort(); short paged = result[1].ToShort(); if ((pagen > paged) && (paged != 0)) m_tiff_pages[m_tiff_pagecount].page_number = paged; else m_tiff_pages[m_tiff_pagecount].page_number = pagen; } else { result = input.GetField(TiffTag.SUBFILETYPE); if (result != null) { subfiletype = result[0].ToInt(); if ((((FileType)subfiletype & FileType.PAGE) == 0) && (subfiletype != 0)) continue; } else { result = input.GetField(TiffTag.OSUBFILETYPE); if (result != null) { subfiletype = result[0].ToInt(); if (((OFileType)subfiletype != OFileType.IMAGE) && ((OFileType)subfiletype != OFileType.PAGE) && (subfiletype != 0)) continue; } } m_tiff_pages[m_tiff_pagecount].page_number = m_tiff_pagecount; } m_tiff_pages[m_tiff_pagecount].page_directory = i; if (input.IsTiled()) m_tiff_pages[m_tiff_pagecount].page_tilecount = input.NumberOfTiles(); m_tiff_pagecount++; } IComparer myComparer = new cmp_t2p_page(); Array.Sort(m_tiff_pages, myComparer); for (short i = 0; i < m_tiff_pagecount; i++) { m_pdf_xrefcount += 5; input.SetDirectory(m_tiff_pages[i].page_directory); result = input.GetField(TiffTag.PHOTOMETRIC); if ((result != null && ((Photometric)result[0].ToInt() == Photometric.PALETTE)) || input.GetField(TiffTag.INDEXED) != null) { m_tiff_pages[i].page_extra++; m_pdf_xrefcount++; } result = input.GetField(TiffTag.COMPRESSION); if (result != null) { Compression xuint16 = (Compression)result[0].ToInt(); if ((xuint16 == Compression.DEFLATE || xuint16 == Compression.ADOBE_DEFLATE) && ((m_tiff_pages[i].page_tilecount != 0) || input.NumberOfStrips() == 1) && !m_pdf_nopassthrough) { if (m_pdf_minorversion < 2) m_pdf_minorversion = 2; } } result = input.GetField(TiffTag.TRANSFERFUNCTION); if (result != null) { m_tiff_transferfunction[0] = result[0].GetBytes(); m_tiff_transferfunction[1] = result[1].GetBytes(); m_tiff_transferfunction[2] = result[2].GetBytes(); if (m_tiff_transferfunction[1] != m_tiff_transferfunction[0]) { m_tiff_transferfunctioncount = 3; m_tiff_pages[i].page_extra += 4; m_pdf_xrefcount += 4; } else { m_tiff_transferfunctioncount = 1; m_tiff_pages[i].page_extra += 2; m_pdf_xrefcount += 2; } if (m_pdf_minorversion < 2) m_pdf_minorversion = 2; } else { m_tiff_transferfunctioncount = 0; } result = input.GetField(TiffTag.ICCPROFILE); if (result != null) { m_tiff_iccprofilelength = result[0].ToInt(); m_tiff_iccprofile = result[1].ToByteArray(); m_tiff_pages[i].page_extra++; m_pdf_xrefcount++; if (m_pdf_minorversion < 3) m_pdf_minorversion = 3; } //m_tiff_tiles[i].tiles_tilecount = m_tiff_pages[i].page_tilecount; result = input.GetField(TiffTag.PLANARCONFIG); if (result != null && ((PlanarConfig)result[0].ToShort() == PlanarConfig.SEPARATE)) { result = input.GetField(TiffTag.SAMPLESPERPIXEL); int xuint16 = result[0].ToInt(); m_tiff_pages[i].page_tilecount /= xuint16; } if (m_tiff_pages[i].page_tilecount > 0) { m_pdf_xrefcount += (m_tiff_pages[i].page_tilecount - 1) * 2; result = input.GetField(TiffTag.TILEWIDTH); m_tiff_pages[i].tiles_tilewidth = result[0].ToInt(); input.GetField(TiffTag.TILELENGTH); m_tiff_pages[i].tiles_tilelength = result[0].ToInt(); m_tiff_pages[i].tiles_tiles = new T2P_TILE[m_tiff_pages[i].page_tilecount]; for (int idx = 0; idx < m_tiff_pages[i].page_tilecount; idx++) m_tiff_pages[i].tiles_tiles[idx] = new T2P_TILE(); } } }
/* 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. */ private void read_tiff_size(Tiff input) { if (m_pdf_transcode == t2p_transcode_t.T2P_TRANSCODE_RAW) { FieldValue[] result = null; if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_G4) { result = input.GetField(TiffTag.STRIPBYTECOUNTS); int[] sbc = result[0].ToIntArray(); m_tiff_datasize = sbc[0]; return; } if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_ZIP) { result = input.GetField(TiffTag.STRIPBYTECOUNTS); int[] sbc = result[0].ToIntArray(); m_tiff_datasize = sbc[0]; return; } if (m_tiff_compression == Compression.JPEG) { result = input.GetField(TiffTag.JPEGTABLES); if (result != null) { int count = result[0].ToInt(); if (count > 4) { m_tiff_datasize += count; m_tiff_datasize -= 2; /* don't use EOI of header */ } } else { m_tiff_datasize = 2; /* SOI for first strip */ } int stripcount = input.NumberOfStrips(); int[] sbc = null; result = input.GetField(TiffTag.STRIPBYTECOUNTS); if (result == null) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Input file {0} missing field: STRIPBYTECOUNTS", input.FileName()); m_error = true; return; } else sbc = result[0].ToIntArray(); for (int i = 0; i < stripcount; i++) { m_tiff_datasize += sbc[i]; m_tiff_datasize -= 4; /* don't use SOI or EOI of strip */ } m_tiff_datasize += 2; /* use EOI of last strip */ return; } } m_tiff_datasize = input.ScanlineSize() * m_tiff_length; if (m_tiff_planar == PlanarConfig.SEPARATE) m_tiff_datasize *= m_tiff_samplesperpixel; }