/* 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 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. */ private int readwrite_pdf_image_tile(Tiff input, int tile) { bool edge = false; edge |= tile_is_right_edge(m_tiff_pages[m_pdf_page], tile); edge |= tile_is_bottom_edge(m_tiff_pages[m_pdf_page], tile); byte[] buffer = null; int bufferoffset = 0; FieldValue[] result = null; if ((m_pdf_transcode == t2p_transcode_t.T2P_TRANSCODE_RAW) && (!edge || (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_JPEG))) { if (m_pdf_compression == t2p_compress_t.T2P_COMPRESS_G4) { buffer = new byte [m_tiff_datasize]; input.ReadRawTile(tile, 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_pdf_compression == t2p_compress_t.T2P_COMPRESS_ZIP) { buffer = new byte [m_tiff_datasize]; input.ReadRawTile(tile, 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) { byte[] table_end = new byte[2]; 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 > 0) { Buffer.BlockCopy(jpt, 0, buffer, 0, count); bufferoffset += count - 2; table_end[0] = buffer[bufferoffset - 2]; table_end[1] = buffer[bufferoffset - 1]; } if (count > 0) { int xuint32 = bufferoffset; bufferoffset += input.ReadRawTile(tile, buffer, bufferoffset - 2, -1); buffer[xuint32 - 2] = table_end[0]; buffer[xuint32 - 1] = table_end[1]; } else { bufferoffset += input.ReadRawTile(tile, buffer, bufferoffset, -1); } } writeToFile(buffer, bufferoffset); return bufferoffset; } } if (m_pdf_sample == t2p_sample_t.T2P_SAMPLE_NOTHING) { buffer = new byte [m_tiff_datasize]; int read = input.ReadEncodedTile(tile, buffer, bufferoffset, m_tiff_datasize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding tile {0} of {1}", tile, input.FileName()); m_error = true; return 0; } } else { if (m_pdf_sample == t2p_sample_t.T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG) { int septilesize = input.TileSize(); int septilecount = input.NumberOfTiles(); int tilecount = septilecount / m_tiff_samplesperpixel; buffer = new byte [m_tiff_datasize]; byte[] samplebuffer = new byte [m_tiff_datasize]; int samplebufferoffset = 0; for (short i = 0; i < m_tiff_samplesperpixel; i++) { int read = input.ReadEncodedTile(tile + i * tilecount, samplebuffer, samplebufferoffset, septilesize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding tile {0} of {1}", tile + i * tilecount, input.FileName()); m_error = true; return 0; } samplebufferoffset += read; } sample_planar_separate_to_contig(buffer, bufferoffset, samplebuffer, samplebufferoffset); bufferoffset += samplebufferoffset; } if (buffer == null) { buffer = new byte [m_tiff_datasize]; int read = input.ReadEncodedTile(tile, buffer, bufferoffset, m_tiff_datasize); if (read == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error on decoding tile {0} of {1}", tile, input.FileName()); m_error = true; return 0; } } if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_RGBA_TO_RGB) != 0) m_tiff_datasize = sample_rgba_to_rgb(buffer, m_tiff_pages[m_pdf_page].tiles_tilewidth * m_tiff_pages[m_pdf_page].tiles_tilelength); if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_RGBAA_TO_RGB) != 0) m_tiff_datasize = sample_rgbaa_to_rgb(buffer, m_tiff_pages[m_pdf_page].tiles_tilewidth * m_tiff_pages[m_pdf_page].tiles_tilelength); if ((m_pdf_sample & t2p_sample_t.T2P_SAMPLE_YCBCR_TO_RGB) != 0) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "No support for YCbCr to RGB in tile for {0}", input.FileName()); m_error = true; return 0; } 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_pages[m_pdf_page].tiles_tilewidth * m_tiff_pages[m_pdf_page].tiles_tilelength); } if (tile_is_right_edge(m_tiff_pages[m_pdf_page], tile)) tile_collapse_left(buffer, input.TileRowSize(), m_tiff_pages[m_pdf_page].tiles_tilewidth, m_tiff_pages[m_pdf_page].tiles_edgetilewidth, m_tiff_pages[m_pdf_page].tiles_tilelength); 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); if (!tile_is_right_edge(m_tiff_pages[m_pdf_page], tile)) m_output.SetField(TiffTag.IMAGEWIDTH, m_tiff_pages[m_pdf_page].tiles_tilewidth); else m_output.SetField(TiffTag.IMAGEWIDTH, m_tiff_pages[m_pdf_page].tiles_edgetilewidth); if (!tile_is_bottom_edge(m_tiff_pages[m_pdf_page], tile)) { m_output.SetField(TiffTag.IMAGELENGTH, m_tiff_pages[m_pdf_page].tiles_tilelength); m_output.SetField(TiffTag.ROWSPERSTRIP, m_tiff_pages[m_pdf_page].tiles_tilelength); } else { m_output.SetField(TiffTag.IMAGELENGTH, m_tiff_pages[m_pdf_page].tiles_edgetilelength); m_output.SetField(TiffTag.ROWSPERSTRIP, m_tiff_pages[m_pdf_page].tiles_edgetilelength); } 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); } } m_output.SetField(TiffTag.COMPRESSION, Compression.JPEG); m_output.SetField(TiffTag.JPEGTABLESMODE, 0); /* JpegTablesMode.NONE */ 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; bufferoffset = m_output.WriteEncodedStrip(0, buffer, m_output.StripSize()); buffer = null; if (bufferoffset == -1) { Tiff.Error(Tiff2PdfConstants.TIFF2PDF_MODULE, "Error writing encoded tile to output PDF {0}", m_output.FileName()); m_error = true; return 0; } return m_outputwritten; }