ReadRGBAImageOriented() public method

Reads the image and decodes it into RGBA format raster using specified raster origin.

ReadRGBAImageOriented reads a strip- or tile-based image into memory, storing the result in the user supplied RGBA raster. The raster is assumed to be an array of width times height 32-bit entries, where width must be less than or equal to the width of the image (height may be any non-zero size). If the raster dimensions are smaller than the image, the image data is cropped to the raster bounds. If the raster height is greater than that of the image, then the image data placement depends on orientation. Note that the raster is assumed to be organized such that the pixel at location (x, y) is raster[y * width + x]; with the raster origin specified by orientation parameter.

When ReadRGBAImageOriented is used with Orientation.BOTLEFT for the orientation the produced result is the same as retuned by O:BitMiracle.LibTiff.Classic.Tiff.ReadRGBAImage.

Raster pixels are 8-bit packed red, green, blue, alpha samples. The Tiff.GetR, Tiff.GetG, Tiff.GetB, and Tiff.GetA should be used to access individual samples. Images without Associated Alpha matting information have a constant Alpha of 1.0 (255).

ReadRGBAImageOriented converts non-8-bit images by scaling sample values. Palette, grayscale, bilevel, CMYK, and YCbCr images are converted to RGB transparently. Raster pixels are returned uncorrected by any colorimetry information present in the directory.

Samples must be either 1, 2, 4, 8, or 16 bits. Colorimetric samples/pixel must be either 1, 3, or 4 (i.e. SamplesPerPixel minus ExtraSamples).

Palette image colormaps that appear to be incorrectly written as 8-bit values are automatically scaled to 16-bits.

ReadRGBAImageOriented is just a wrapper around the more general TiffRgbaImage facilities.

All error messages are directed to the current error handler.

public ReadRGBAImageOriented ( int width, int height, int raster, Orientation orientation ) : bool
width int The raster width.
height int The raster height.
raster int The raster (the buffer to place decoded image data to).
orientation Orientation The raster origin position.
return bool
        private static (ProcessState state, SKImage image) ReadFullImage(T.Tiff tiff, ImageRequest request, bool allowSizeAboveFull)
        {
            int width  = tiff.GetField(T.TiffTag.IMAGEWIDTH)[0].ToInt();
            int height = tiff.GetField(T.TiffTag.IMAGELENGTH)[0].ToInt();

            var restag  = tiff.GetField(T.TiffTag.RESOLUTIONUNIT);
            var xrestag = tiff.GetField(T.TiffTag.XRESOLUTION);
            var yrestag = tiff.GetField(T.TiffTag.YRESOLUTION);

            var resunit = restag == null ? 2 : restag[0].ToShort();
            var xres    = xrestag == null ? 96 : xrestag[0].ToDouble();
            var yres    = yrestag == null ? 96 : yrestag[0].ToDouble();

            // pixels per metre
            if (resunit == 3)
            {
                xres = xres / 0.0254;
                yres = yres / 0.0254;
            }

            var isTileable = tiff.IsTiled();
            var state      = ImageRequestInterpreter.GetInterpretedValues(request, width, height, allowSizeAboveFull);

            state.HorizontalResolution = Convert.ToUInt16(xres);
            state.VerticalResolution   = Convert.ToUInt16(yres);
            var raster = new int[width * height];

            if (!tiff.ReadRGBAImageOriented(width, height, raster, T.Orientation.TOPLEFT))
            {
                throw new IOException("Unable to decode TIFF file");
            }
            using (var bmp = CreateBitmapFromPixels(raster, width, height))
            {
                var desiredWidth  = Math.Max(1, (int)Math.Round(state.RegionWidth * state.ImageScale));
                var desiredHeight = Math.Max(1, (int)Math.Round(state.RegionHeight * state.ImageScale));
                Log.Debug("Desired size {@DesiredWidth}, {@DesiredHeight}", desiredWidth, desiredHeight);

                var regionWidth  = state.RegionWidth;
                var regionHeight = state.RegionHeight;

                var srcRegion = SKRectI.Create(state.StartX, state.StartY, regionWidth, regionHeight);
                return(state, CopyImageRegion2(bmp, desiredWidth, desiredHeight, srcRegion));
            }
        }
Example #2
0
        /*
        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;
        }
Example #3
0
        /// <summary>
        /// Read the whole image into one big RGBA buffer and then write out
        /// strips from that. This is using the traditional TIFFReadRGBAImage()
        /// API that we trust.
        /// </summary>
        private bool cvt_whole_image(Tiff inImage, Tiff outImage, int width, int height)
        {
            int pixel_count = width * height;

            /* XXX: Check the integer overflow. */
            if (width == 0 || height == 0 || (pixel_count / width) != height)
            {
                Tiff.Error(inImage.FileName(),
                    "Malformed input file; can't allocate buffer for raster of {0}x{1} size",
                    width, height);
                return false;
            }

            m_rowsPerStrip = outImage.DefaultStripSize(m_rowsPerStrip);
            outImage.SetField(TiffTag.ROWSPERSTRIP, m_rowsPerStrip);

            int[] raster = new int[pixel_count];

            /* Read the image in one chunk into an RGBA array */
            if (!inImage.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT, false))
                return false;

            /*
             * Do we want to strip away alpha components?
             */
            byte[] rasterBytes;
            int rasterByteSize;
            if (m_noAlpha)
            {
                rasterByteSize = pixel_count * 3;
                rasterBytes = new byte[rasterByteSize];

                for (int i = 0, rasterBytesPos = 0; i < pixel_count; i++)
                {
                    byte[] bytes = BitConverter.GetBytes(raster[i]);
                    rasterBytes[rasterBytesPos++] = bytes[0];
                    rasterBytes[rasterBytesPos++] = bytes[1];
                    rasterBytes[rasterBytesPos++] = bytes[2];
                }
            }
            else
            {
                rasterByteSize = pixel_count * 4;
                rasterBytes = new byte[rasterByteSize];
                Buffer.BlockCopy(raster, 0, rasterBytes, 0, rasterByteSize);
            }

            /*
             * Write out the result in strips
             */
            for (int row = 0; row < height; row += m_rowsPerStrip)
            {
                int bytes_per_pixel;
                if (m_noAlpha)
                    bytes_per_pixel = 3;
                else
                    bytes_per_pixel = 4;

                int rows_to_write;
                if (row + m_rowsPerStrip > height)
                    rows_to_write = height - row;
                else
                    rows_to_write = m_rowsPerStrip;

                int offset = bytes_per_pixel * row * width;
                int count = bytes_per_pixel * rows_to_write * width;
                if (outImage.WriteEncodedStrip(row / m_rowsPerStrip, rasterBytes, offset, count) == -1)
                    return false;
            }

            return true;
        }