public GetFieldDefaulted ( TiffTag tag ) : BitMiracle.LibTiff.Classic.FieldValue[] | ||
tag | TiffTag | The tag. |
Résultat | BitMiracle.LibTiff.Classic.FieldValue[] |
public bool Copy(Tiff inImage, Tiff outImage) { int width = 0; FieldValue[] result = inImage.GetField(TiffTag.IMAGEWIDTH); if (result != null) { width = result[0].ToInt(); outImage.SetField(TiffTag.IMAGEWIDTH, width); } int length = 0; result = inImage.GetField(TiffTag.IMAGELENGTH); if (result != null) { length = result[0].ToInt(); outImage.SetField(TiffTag.IMAGELENGTH, length); } short bitspersample = 1; result = inImage.GetField(TiffTag.BITSPERSAMPLE); if (result != null) { bitspersample = result[0].ToShort(); outImage.SetField(TiffTag.BITSPERSAMPLE, bitspersample); } short samplesperpixel = 1; result = inImage.GetField(TiffTag.SAMPLESPERPIXEL); if (result != null) { samplesperpixel = result[0].ToShort(); outImage.SetField(TiffTag.SAMPLESPERPIXEL, samplesperpixel); } if (m_compression != (Compression)(-1)) outImage.SetField(TiffTag.COMPRESSION, m_compression); else { result = inImage.GetField(TiffTag.COMPRESSION); if (result != null) { m_compression = (Compression)result[0].ToInt(); outImage.SetField(TiffTag.COMPRESSION, m_compression); } } result = inImage.GetFieldDefaulted(TiffTag.COMPRESSION); Compression input_compression = (Compression)result[0].ToInt(); result = inImage.GetFieldDefaulted(TiffTag.PHOTOMETRIC); Photometric input_photometric = (Photometric)result[0].ToShort(); if (input_compression == Compression.JPEG) { /* Force conversion to RGB */ inImage.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RGB); } else if (input_photometric == Photometric.YCBCR) { /* Otherwise, can't handle subsampled input */ result = inImage.GetFieldDefaulted(TiffTag.YCBCRSUBSAMPLING); short subsamplinghor = result[0].ToShort(); short subsamplingver = result[1].ToShort(); if (subsamplinghor != 1 || subsamplingver != 1) { Console.Error.WriteLine("tiffcp: {0}: Can't copy/convert subsampled image.", inImage.FileName()); return false; } } if (m_compression == Compression.JPEG) { if (input_photometric == Photometric.RGB && m_jpegcolormode == JpegColorMode.RGB) outImage.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR); else outImage.SetField(TiffTag.PHOTOMETRIC, input_photometric); } else if (m_compression == Compression.SGILOG || m_compression == Compression.SGILOG24) { outImage.SetField(TiffTag.PHOTOMETRIC, samplesperpixel == 1 ? Photometric.LOGL : Photometric.LOGLUV); } else { if (input_compression != Compression.JPEG) copyTag(inImage, outImage, TiffTag.PHOTOMETRIC, 1, TiffType.SHORT); } if (m_fillorder != 0) outImage.SetField(TiffTag.FILLORDER, m_fillorder); else copyTag(inImage, outImage, TiffTag.FILLORDER, 1, TiffType.SHORT); /* * Will copy `Orientation' tag from input image */ result = inImage.GetFieldDefaulted(TiffTag.ORIENTATION); m_orientation = (Orientation)result[0].ToByte(); switch (m_orientation) { case Orientation.BOTRIGHT: case Orientation.RIGHTBOT: Tiff.Warning(inImage.FileName(), "using bottom-left orientation"); m_orientation = Orientation.BOTLEFT; break; case Orientation.LEFTBOT: case Orientation.BOTLEFT: break; case Orientation.TOPRIGHT: case Orientation.RIGHTTOP: default: Tiff.Warning(inImage.FileName(), "using top-left orientation"); m_orientation = Orientation.TOPLEFT; break; case Orientation.LEFTTOP: case Orientation.TOPLEFT: break; } outImage.SetField(TiffTag.ORIENTATION, m_orientation); /* * Choose tiles/strip for the output image according to * the command line arguments (-tiles, -strips) and the * structure of the input image. */ if (m_outtiled == -1) { if (inImage.IsTiled()) m_outtiled = 1; else m_outtiled = 0; } if (m_outtiled != 0) { /* * Setup output file's tile width&height. If either * is not specified, use either the value from the * input image or, if nothing is defined, use the * library default. */ if (m_tilewidth == -1) { result = inImage.GetFieldDefaulted(TiffTag.TILEWIDTH); if (result != null) m_tilewidth = result[0].ToInt(); } if (m_tilelength == -1) { result = inImage.GetFieldDefaulted(TiffTag.TILELENGTH); if (result != null) m_tilelength = result[0].ToInt(); } outImage.DefaultTileSize(ref m_tilewidth, ref m_tilelength); outImage.SetField(TiffTag.TILEWIDTH, m_tilewidth); outImage.SetField(TiffTag.TILELENGTH, m_tilelength); } else { /* * RowsPerStrip is left unspecified: use either the * value from the input image or, if nothing is defined, * use the library default. */ if (m_rowsperstrip == 0) { result = inImage.GetField(TiffTag.ROWSPERSTRIP); if (result == null) m_rowsperstrip = outImage.DefaultStripSize(m_rowsperstrip); else m_rowsperstrip = result[0].ToInt(); if (m_rowsperstrip > length && m_rowsperstrip != -1) m_rowsperstrip = length; } else if (m_rowsperstrip == -1) m_rowsperstrip = length; outImage.SetField(TiffTag.ROWSPERSTRIP, m_rowsperstrip); } if (m_config != PlanarConfig.UNKNOWN) outImage.SetField(TiffTag.PLANARCONFIG, m_config); else { result = inImage.GetField(TiffTag.PLANARCONFIG); if (result != null) { m_config = (PlanarConfig)result[0].ToShort(); outImage.SetField(TiffTag.PLANARCONFIG, m_config); } } if (samplesperpixel <= 4) copyTag(inImage, outImage, TiffTag.TRANSFERFUNCTION, 4, TiffType.SHORT); copyTag(inImage, outImage, TiffTag.COLORMAP, 4, TiffType.SHORT); /* SMinSampleValue & SMaxSampleValue */ switch (m_compression) { case Compression.JPEG: outImage.SetField(TiffTag.JPEGQUALITY, m_quality); outImage.SetField(TiffTag.JPEGCOLORMODE, m_jpegcolormode); break; case Compression.LZW: case Compression.ADOBE_DEFLATE: case Compression.DEFLATE: if (m_predictor != -1) outImage.SetField(TiffTag.PREDICTOR, m_predictor); else { result = inImage.GetField(TiffTag.PREDICTOR); if (result != null) { m_predictor = result[0].ToShort(); outImage.SetField(TiffTag.PREDICTOR, m_predictor); } } break; case Compression.CCITTFAX3: case Compression.CCITTFAX4: if (m_compression == Compression.CCITTFAX3) { if (m_g3opts != Group3Opt.UNKNOWN) outImage.SetField(TiffTag.GROUP3OPTIONS, m_g3opts); else { result = inImage.GetField(TiffTag.GROUP3OPTIONS); if (result != null) { m_g3opts = (Group3Opt)result[0].ToShort(); outImage.SetField(TiffTag.GROUP3OPTIONS, m_g3opts); } } } else copyTag(inImage, outImage, TiffTag.GROUP4OPTIONS, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.BADFAXLINES, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.CLEANFAXDATA, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.CONSECUTIVEBADFAXLINES, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.FAXRECVPARAMS, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.FAXRECVTIME, 1, TiffType.LONG); copyTag(inImage, outImage, TiffTag.FAXSUBADDRESS, 1, TiffType.ASCII); break; } result = inImage.GetField(TiffTag.ICCPROFILE); if (result != null) outImage.SetField(TiffTag.ICCPROFILE, result[0], result[1]); result = inImage.GetField(TiffTag.NUMBEROFINKS); if (result != null) { short ninks = result[0].ToShort(); outImage.SetField(TiffTag.NUMBEROFINKS, ninks); result = inImage.GetField(TiffTag.INKNAMES); if (result != null) { string inknames = result[0].ToString(); string[] parts = inknames.Split(new char[] { '\0' }); int inknameslen = 0; foreach (string part in parts) inknameslen += part.Length + 1; outImage.SetField(TiffTag.INKNAMES, inknameslen, inknames); } } result = inImage.GetField(TiffTag.PAGENUMBER); if (m_pageInSeq == 1) { if (m_pageNum < 0) { /* only one input file */ if (result != null) outImage.SetField(TiffTag.PAGENUMBER, result[0], result[1]); } else { outImage.SetField(TiffTag.PAGENUMBER, m_pageNum++, 0); } } else { if (result != null) { if (m_pageNum < 0) { /* only one input file */ outImage.SetField(TiffTag.PAGENUMBER, result[0], result[1]); } else { outImage.SetField(TiffTag.PAGENUMBER, m_pageNum++, 0); } } } int NTAGS = g_tags.Length; for (int i = 0; i < NTAGS; i++) { tagToCopy p = g_tags[i]; copyTag(inImage, outImage, p.tag, p.count, p.type); } return pickFuncAndCopy(inImage, outImage, bitspersample, samplesperpixel, length, width); }
static bool writeBufferToSeparateStrips(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp) { byte[] obuf = new byte[outImage.StripSize()]; FieldValue[] result = outImage.GetFieldDefaulted(TiffTag.ROWSPERSTRIP); int rowsperstrip = result[0].ToInt(); int rowsize = imagewidth * spp; int strip = 0; for (short s = 0; s < spp; s++) { for (int row = 0; row < imagelength; row += rowsperstrip) { int nrows = (row + rowsperstrip > imagelength) ? imagelength - row : rowsperstrip; int stripsize = outImage.VStripSize(nrows); cpContigBufToSeparateBuf(obuf, buf, row * rowsize + s, nrows, imagewidth, 0, 0, spp, 1); if (outImage.WriteEncodedStrip(strip++, obuf, stripsize) < 0) { Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", strip - 1); return false; } } } 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; }
static bool writeBufferToContigStrips(Tiff outImage, byte[] buffer, int imagelength, int imagewidth, short spp) { FieldValue[] result = outImage.GetFieldDefaulted(TiffTag.ROWSPERSTRIP); int rowsperstrip = result[0].ToInt(); int strip = 0; int offset = 0; for (int row = 0; row < imagelength; row += rowsperstrip) { int nrows = (row + rowsperstrip > imagelength) ? imagelength - row : rowsperstrip; int stripsize = outImage.VStripSize(nrows); if (outImage.WriteEncodedStrip(strip++, buffer, offset, stripsize) < 0) { Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", strip - 1); return false; } offset += stripsize; } return true; }
/// <summary> /// Creates new instance of the <see cref="TiffRgbaImage"/> class. /// </summary> /// <param name="tif"> /// The instance of the <see cref="BitMiracle.LibTiff.Classic"/> class used to retrieve /// image data. /// </param> /// <param name="stopOnError"> /// if set to <c>true</c> then an error will terminate the conversion; otherwise "get" /// methods will continue processing data until all the possible data in the image have /// been requested. /// </param> /// <param name="errorMsg">The error message (if any) gets placed here.</param> /// <returns> /// New instance of the <see cref="TiffRgbaImage"/> class if the image specified /// by <paramref name="tif"/> can be converted to RGBA format; otherwise, <c>null</c> is /// returned and <paramref name="errorMsg"/> contains the reason why it is being /// rejected. /// </returns> public static TiffRgbaImage Create(Tiff tif, bool stopOnError, out string errorMsg) { errorMsg = null; // Initialize to normal values TiffRgbaImage img = new TiffRgbaImage(); img.row_offset = 0; img.col_offset = 0; img.redcmap = null; img.greencmap = null; img.bluecmap = null; img.req_orientation = Orientation.BOTLEFT; // It is the default img.tif = tif; img.stoponerr = stopOnError; FieldValue[] result = tif.GetFieldDefaulted(TiffTag.BITSPERSAMPLE); img.bitspersample = result[0].ToShort(); switch (img.bitspersample) { case 1: case 2: case 4: case 8: case 16: break; default: errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle images with {0}-bit samples", img.bitspersample); return null; } img.alpha = 0; result = tif.GetFieldDefaulted(TiffTag.SAMPLESPERPIXEL); img.samplesperpixel = result[0].ToShort(); result = tif.GetFieldDefaulted(TiffTag.EXTRASAMPLES); short extrasamples = result[0].ToShort(); byte[] sampleinfo = result[1].ToByteArray(); if (extrasamples >= 1) { switch ((ExtraSample)sampleinfo[0]) { case ExtraSample.UNSPECIFIED: if (img.samplesperpixel > 3) { // Workaround for some images without correct info about alpha channel img.alpha = ExtraSample.ASSOCALPHA; } break; case ExtraSample.ASSOCALPHA: // data is pre-multiplied case ExtraSample.UNASSALPHA: // data is not pre-multiplied img.alpha = (ExtraSample)sampleinfo[0]; break; } } if (Tiff.DEFAULT_EXTRASAMPLE_AS_ALPHA) { result = tif.GetField(TiffTag.PHOTOMETRIC); if (result == null) img.photometric = Photometric.MINISWHITE; if (extrasamples == 0 && img.samplesperpixel == 4 && img.photometric == Photometric.RGB) { img.alpha = ExtraSample.ASSOCALPHA; extrasamples = 1; } } int colorchannels = img.samplesperpixel - extrasamples; result = tif.GetFieldDefaulted(TiffTag.COMPRESSION); Compression compress = (Compression)result[0].ToInt(); result = tif.GetFieldDefaulted(TiffTag.PLANARCONFIG); PlanarConfig planarconfig = (PlanarConfig)result[0].ToShort(); result = tif.GetField(TiffTag.PHOTOMETRIC); if (result == null) { switch (colorchannels) { case 1: if (img.isCCITTCompression()) img.photometric = Photometric.MINISWHITE; else img.photometric = Photometric.MINISBLACK; break; case 3: img.photometric = Photometric.RGB; break; default: errorMsg = string.Format(CultureInfo.InvariantCulture, "Missing needed {0} tag", photoTag); return null; } } else img.photometric = (Photometric)result[0].ToInt(); switch (img.photometric) { case Photometric.PALETTE: result = tif.GetField(TiffTag.COLORMAP); if (result == null) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Missing required \"Colormap\" tag"); return null; } short[] red_orig = result[0].ToShortArray(); short[] green_orig = result[1].ToShortArray(); short[] blue_orig = result[2].ToShortArray(); // copy the colormaps so we can modify them int n_color = (1 << img.bitspersample); img.redcmap = new ushort[n_color]; img.greencmap = new ushort[n_color]; img.bluecmap = new ushort[n_color]; Buffer.BlockCopy(red_orig, 0, img.redcmap, 0, n_color * sizeof(ushort)); Buffer.BlockCopy(green_orig, 0, img.greencmap, 0, n_color * sizeof(ushort)); Buffer.BlockCopy(blue_orig, 0, img.bluecmap, 0, n_color * sizeof(ushort)); if (planarconfig == PlanarConfig.CONTIG && img.samplesperpixel != 1 && img.bitspersample < 8) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle contiguous data with {0}={1}, and {2}={3} and Bits/Sample={4}", photoTag, img.photometric, "Samples/pixel", img.samplesperpixel, img.bitspersample); return null; } break; case Photometric.MINISWHITE: case Photometric.MINISBLACK: if (planarconfig == PlanarConfig.CONTIG && img.samplesperpixel != 1 && img.bitspersample < 8) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle contiguous data with {0}={1}, and {2}={3} and Bits/Sample={4}", photoTag, img.photometric, "Samples/pixel", img.samplesperpixel, img.bitspersample); return null; } break; case Photometric.YCBCR: // It would probably be nice to have a reality check here. if (planarconfig == PlanarConfig.CONTIG) { // can rely on LibJpeg.Net to convert to RGB // XXX should restore current state on exit switch (compress) { case Compression.JPEG: // TODO: when complete tests verify complete desubsampling and // YCbCr handling, remove use of JPEGCOLORMODE in favor of native // handling tif.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RGB); img.photometric = Photometric.RGB; break; default: // do nothing break; } } // TODO: if at all meaningful and useful, make more complete support check // here, or better still, refactor to let supporting code decide whether there // is support and what meaningfull error to return break; case Photometric.RGB: if (colorchannels < 3) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle RGB image with {0}={1}", "Color channels", colorchannels); return null; } break; case Photometric.SEPARATED: result = tif.GetFieldDefaulted(TiffTag.INKSET); InkSet inkset = (InkSet)result[0].ToByte(); if (inkset != InkSet.CMYK) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle separated image with {0}={1}", "InkSet", inkset); return null; } if (img.samplesperpixel < 4) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle separated image with {0}={1}", "Samples/pixel", img.samplesperpixel); return null; } break; case Photometric.LOGL: if (compress != Compression.SGILOG) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, LogL data must have {0}={1}", "Compression", Compression.SGILOG); return null; } tif.SetField(TiffTag.SGILOGDATAFMT, 3); // 8-bit RGB monitor values. img.photometric = Photometric.MINISBLACK; // little white lie img.bitspersample = 8; break; case Photometric.LOGLUV: if (compress != Compression.SGILOG && compress != Compression.SGILOG24) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, LogLuv data must have {0}={1} or {2}", "Compression", Compression.SGILOG, Compression.SGILOG24); return null; } if (planarconfig != PlanarConfig.CONTIG) { errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle LogLuv images with {0}={1}", "Planarconfiguration", planarconfig); return null; } tif.SetField(TiffTag.SGILOGDATAFMT, 3); // 8-bit RGB monitor values. img.photometric = Photometric.RGB; // little white lie img.bitspersample = 8; break; case Photometric.CIELAB: break; default: errorMsg = string.Format(CultureInfo.InvariantCulture, "Sorry, can not handle image with {0}={1}", photoTag, img.photometric); return null; } img.Map = null; img.BWmap = null; img.PALmap = null; img.ycbcr = null; img.cielab = null; result = tif.GetField(TiffTag.IMAGEWIDTH); img.width = result[0].ToInt(); result = tif.GetField(TiffTag.IMAGELENGTH); img.height = result[0].ToInt(); result = tif.GetFieldDefaulted(TiffTag.ORIENTATION); img.orientation = (Orientation)result[0].ToByte(); img.isContig = !(planarconfig == PlanarConfig.SEPARATE && colorchannels > 1); if (img.isContig) { if (!img.pickContigCase()) { errorMsg = "Sorry, can not handle image"; return null; } } else { if (!img.pickSeparateCase()) { errorMsg = "Sorry, can not handle image"; return null; } } return img; }