bool writeBufferToSeparateTiles(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp) { byte[] obuf = new byte[outImage.TileSize()]; FieldValue[] result = outImage.GetField(TiffTag.TILELENGTH); int tl = result[0].ToInt(); result = outImage.GetField(TiffTag.TILEWIDTH); int tw = result[0].ToInt(); result = outImage.GetField(TiffTag.BITSPERSAMPLE); short bps = result[0].ToShort(); Debug.Assert(bps % 8 == 0); short bytes_per_sample = (short)(bps / 8); int imagew = outImage.ScanlineSize(); int tilew = outImage.TileRowSize(); int iimagew = outImage.RasterScanlineSize(); int iskew = iimagew - tilew * spp; int bufp = 0; for (int row = 0; row < imagelength; row += tl) { int nrow = (row + tl > imagelength) ? imagelength - row : tl; int colb = 0; for (int col = 0; col < imagewidth; col += tw) { for (short s = 0; s < spp; s++) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ if (colb + tilew > imagew) { int width = imagew - colb; int oskew = tilew - width; cpContigBufToSeparateBuf(obuf, buf, bufp + (colb * spp) + s, nrow, width / bytes_per_sample, oskew, (oskew * spp) + iskew, spp, bytes_per_sample); } else cpContigBufToSeparateBuf(obuf, buf, bufp + (colb * spp) + s, nrow, m_tilewidth, 0, iskew, spp, bytes_per_sample); if (outImage.WriteTile(obuf, col, row, 0, s) < 0) { Tiff.Error(outImage.FileName(), "Error, can't write tile at {0} {1} sample {2}", col, row, s); return false; } } colb += tilew; } bufp += nrow * iimagew; } return true; }
bool writeBufferToContigTiles(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp) { byte[] obuf = new byte[outImage.TileSize()]; FieldValue[] result = outImage.GetField(TiffTag.TILELENGTH); int tl = result[0].ToInt(); result = outImage.GetField(TiffTag.TILEWIDTH); int tw = result[0].ToInt(); int imagew = outImage.ScanlineSize(); int tilew = outImage.TileRowSize(); int iskew = imagew - tilew; int bufp = 0; for (int row = 0; row < imagelength; row += m_tilelength) { int nrow = (row + tl > imagelength) ? imagelength - row : tl; int colb = 0; for (int col = 0; col < imagewidth; col += tw) { /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ if (colb + tilew > imagew) { int width = imagew - colb; int oskew = tilew - width; cpStripToTile(obuf, 0, buf, bufp + colb, nrow, width, oskew, oskew + iskew); } else cpStripToTile(obuf, 0, buf, bufp + colb, nrow, tilew, 0, iskew); if (outImage.WriteTile(obuf, col, row, 0, 0) < 0) { Tiff.Error(outImage.FileName(), "Error, can't write tile at {0} {1}", col, row); return false; } colb += tilew; } bufp += nrow * imagew; } return true; }
bool readSeparateTilesIntoBuffer(Tiff inImage, byte[] buf, int imagelength, int imagewidth, short spp) { byte[] tilebuf = new byte[inImage.TileSize()]; FieldValue[] result = inImage.GetField(TiffTag.TILEWIDTH); int tw = result[0].ToInt(); result = inImage.GetField(TiffTag.TILELENGTH); int tl = result[0].ToInt(); result = inImage.GetField(TiffTag.BITSPERSAMPLE); short bps = result[0].ToShort(); Debug.Assert(bps % 8 == 0); short bytes_per_sample = (short)(bps / 8); int imagew = inImage.RasterScanlineSize(); int tilew = inImage.TileRowSize(); int iskew = imagew - tilew * spp; int bufp = 0; for (int row = 0; row < imagelength; row += tl) { int nrow = (row + tl > imagelength) ? imagelength - row : tl; int colb = 0; for (int col = 0; col < imagewidth; col += tw) { for (short s = 0; s < spp; s++) { if (inImage.ReadTile(tilebuf, 0, col, row, 0, s) < 0 && !m_ignore) { Tiff.Error(inImage.FileName(), "Error, can't read tile at {0} {1}, sample {2}", col, row, s); return false; } /* * Tile is clipped horizontally. Calculate * visible portion and skewing factors. */ if (colb + tilew * spp > imagew) { int width = imagew - colb; int oskew = tilew * spp - width; cpSeparateBufToContigBuf(buf, bufp + colb + s * bytes_per_sample, tilebuf, nrow, width / (spp * bytes_per_sample), oskew + iskew, oskew / spp, spp, bytes_per_sample); } else cpSeparateBufToContigBuf(buf, bufp + colb + s * bytes_per_sample, tilebuf, nrow, tw, iskew, 0, spp, bytes_per_sample); } colb += tilew * spp; } bufp += imagew * nrow; } return true; }
bool readContigTilesIntoBuffer(Tiff inImage, byte[] buf, int imagelength, int imagewidth, short spp) { byte[] tilebuf = new byte[inImage.TileSize()]; FieldValue[] result = inImage.GetField(TiffTag.TILEWIDTH); int tw = result[0].ToInt(); result = inImage.GetField(TiffTag.TILELENGTH); int tl = result[0].ToInt(); int imagew = inImage.ScanlineSize(); int tilew = inImage.TileRowSize(); int iskew = imagew - tilew; int bufp = 0; for (int row = 0; row < imagelength; row += tl) { int nrow = (row + tl > imagelength) ? imagelength - row : tl; int colb = 0; for (int col = 0; col < imagewidth; col += tw) { if (inImage.ReadTile(tilebuf, 0, col, row, 0, 0) < 0 && !m_ignore) { Tiff.Error(inImage.FileName(), "Error, can't read tile at {0} {1}", col, row); return false; } if (colb + tilew > imagew) { int width = imagew - colb; int oskew = tilew - width; cpStripToTile(buf, bufp + colb, tilebuf, 0, nrow, width, oskew + iskew, oskew); } else cpStripToTile(buf, bufp + colb, tilebuf, 0, nrow, tilew, iskew, 0); colb += tilew; } bufp += imagew * nrow; } return true; }
/* * 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; }
/* 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. */ private void read_tiff_size_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); if (m_pdf_transcode == t2p_transcode_t.T2P_TRANSCODE_RAW) { if (edge && m_pdf_compression != t2p_compress_t.T2P_COMPRESS_JPEG) { m_tiff_datasize = input.TileSize(); return; } else { FieldValue[] result = input.GetField(TiffTag.TILEBYTECOUNTS); int[] tbc = result[0].ToIntArray(); m_tiff_datasize = tbc[tile]; 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 -= 4; /* don't use EOI of header or SOI of tile */ } } } return; } } m_tiff_datasize = input.TileSize(); if (m_tiff_planar == PlanarConfig.SEPARATE) m_tiff_datasize *= m_tiff_samplesperpixel; }