public static byte[] DecodeJpeg(ReadOnlySpan <byte> data)
    {
        using var decompressor = new JpegDecompressor();

        if (!decompressor.ReadHeader(data, out var width, out var height))
        {
            throw new ImageIOException("Failed to read JPEG header.");
        }

        var pixelData = new byte[width * height * 4];

        if (!decompressor.Read(data, pixelData, width, width * 4, height, JpegPixelFormat.BGRX))
        {
            throw new ImageIOException("Unable to decompress jpeg image.");
        }

        return(pixelData);
    }
    /// <summary>
    /// Tries to detect the image format of the given data by
    /// inspecting the header only.
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public static ImageFileInfo DetectImageFormat(ReadOnlySpan <byte> data)
    {
        ImageFileInfo info;

        if (StbNative.GetPngInfo(data, out info.width, out info.height, out info.hasAlpha))
        {
            info.format = ImageFileFormat.PNG;
            return(info);
        }

        if (StbNative.GetBitmapInfo(data, out info.width, out info.height, out info.hasAlpha))
        {
            info.format = ImageFileFormat.BMP;
            return(info);
        }

        using var jpegDecompressor = new JpegDecompressor();
        if (jpegDecompressor.ReadHeader(data, out info.width, out info.height))
        {
            info.hasAlpha = false;
            info.format   = ImageFileFormat.JPEG;
            return(info);
        }

        if (TargaImage.DetectTga(data, out info))
        {
            return(info);
        }

        // Not a very good heuristic
        if (data.Length == 256 * 256)
        {
            info.width    = 256;
            info.height   = 256;
            info.hasAlpha = true;
            info.format   = ImageFileFormat.FNTART;
            return(info);
        }

        return(info);
    }
Exemple #3
0
 /// <summary>
 /// This is the default resync_to_restart method for data source
 /// managers to use if they don't have any better approach.
 /// </summary>
 /// <param name="cinfo">An instance of <see cref="JpegDecompressor"/></param>
 /// <param name="desired">The desired</param>
 /// <returns><c>false</c> if suspension is required.</returns>
 /// <remarks>That method assumes that no backtracking is possible.
 /// Some data source managers may be able to back up, or may have
 /// additional knowledge about the data which permits a more
 /// intelligent recovery strategy; such managers would
 /// presumably supply their own resync method.<br/><br/>
 /// read_restart_marker calls resync_to_restart if it finds a marker other than
 /// the restart marker it was expecting.  (This code is *not* used unless
 /// a nonzero restart interval has been declared.)  cinfo.unread_marker is
 /// the marker code actually found (might be anything, except 0 or FF).
 /// The desired restart marker number (0..7) is passed as a parameter.<br/><br/>
 /// This routine is supposed to apply whatever error recovery strategy seems
 /// appropriate in order to position the input stream to the next data segment.
 /// Note that cinfo.unread_marker is treated as a marker appearing before
 /// the current data-source input point; usually it should be reset to zero
 /// before returning.<br/><br/>
 /// This implementation is substantially constrained by wanting to treat the
 /// input as a data stream; this means we can't back up.  Therefore, we have
 /// only the following actions to work with:<br/>
 /// 1. Simply discard the marker and let the entropy decoder resume at next
 /// byte of file.<br/>
 /// 2. Read forward until we find another marker, discarding intervening
 /// data.  (In theory we could look ahead within the current bufferload,
 /// without having to discard data if we don't find the desired marker.
 /// This idea is not implemented here, in part because it makes behavior
 /// dependent on buffer size and chance buffer-boundary positions.)<br/>
 /// 3. Leave the marker unread (by failing to zero cinfo.unread_marker).
 /// This will cause the entropy decoder to process an empty data segment,
 /// inserting dummy zeroes, and then we will reprocess the marker.<br/>
 /// #2 is appropriate if we think the desired marker lies ahead, while #3 is
 /// appropriate if the found marker is a future restart marker (indicating
 /// that we have missed the desired restart marker, probably because it got
 /// corrupted).<br/>
 /// We apply #2 or #3 if the found marker is a restart marker no more than
 /// two counts behind or ahead of the expected one.  We also apply #2 if the
 /// found marker is not a legal JPEG marker code (it's certainly bogus data).
 /// If the found marker is a restart marker more than 2 counts away, we do #1
 /// (too much risk that the marker is erroneous; with luck we will be able to
 /// resync at some future point).<br/>
 /// For any valid non-restart JPEG marker, we apply #3.  This keeps us from
 /// overrunning the end of a scan.  An implementation limited to single-scan
 /// files might find it better to apply #2 for markers other than EOI, since
 /// any other marker would have to be bogus data in that case.</remarks>
 public override bool resync_to_restart(JpegDecompressor cinfo, int desired)
 {
     Tiff tif = m_sp.GetTiff();
     Tiff.ErrorExt(tif, tif.m_clientdata, "LibJpeg", "Unexpected error");
     return false;
 }
Exemple #4
0
        private bool jpeg_create_decompress_encap()
        {
            try
            {
                m_libjpeg_jpeg_decompress_struct = new JpegDecompressor();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }
Exemple #5
0
        private bool TIFFjpeg_create_decompress()
        {
            /* initialize JPEG error handling */
            try
            {
                m_decompression = new JpegDecompressor();
                m_common = m_decompression;
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }
Exemple #6
0
        public override bool Init()
        {
            Debug.Assert(m_scheme == Compression.JPEG);

            /*
            * Merge codec-specific tag information and override parent get/set
            * field methods.
            */
            m_tif.MergeFieldInfo(jpegFieldInfo, jpegFieldInfo.Length);

            /*
             * Allocate state block so tag methods have storage to record values.
             */
            m_compression = null;
            m_decompression = null;
            m_photometric = 0;
            m_h_sampling = 0;
            m_v_sampling = 0;
            m_bytesperline = 0;
            m_scancount = 0;
            m_samplesperclump = 0;
            m_recvtime = 0;

            m_parentTagMethods = m_tif.m_tagmethods;
            m_tif.m_tagmethods = m_tagMethods;

            /* Default values for codec-specific fields */
            m_jpegtables = null;
            m_jpegtables_length = 0;
            m_jpegquality = 75; /* Default IJG quality */
            m_jpegcolormode = JpegColorMode.RGB;
            m_jpegtablesmode = JpegTablesMode.Quant | JpegTablesMode.Huff;

            m_recvparams = 0;
            m_subaddress = null;
            m_faxdcs = null;

            m_ycbcrsampling_fetched = false;

            m_rawDecode = false;
            m_rawEncode = false;
            m_tif.m_flags |= TiffFlags.NoBitRev; // no bit reversal, please

            m_cinfo_initialized = false;

            /*
             ** Create a JPEGTables field if no directory has yet been created. 
             ** We do this just to ensure that sufficient space is reserved for
             ** the JPEGTables field.  It will be properly created the right
             ** size later. 
             */
            if (m_tif.m_diroff == 0)
            {
                const int SIZE_OF_JPEGTABLES = 2000;

                // The following line assumes incorrectly that all JPEG-in-TIFF
                // files will have a JpegTables tag generated and causes
                // null-filled JpegTables tags to be written when the JPEG data
                // is placed with WriteRawStrip. The field bit should be 
                // set, anyway, later when actual JpegTables header is
                // generated, so removing it here hopefully is harmless.
                //
                //       m_tif.setFieldBit(FIELD_JPEGTABLES);
                //

                m_jpegtables_length = SIZE_OF_JPEGTABLES;
                m_jpegtables = new byte[m_jpegtables_length];
            }

            /*
             * Mark the YCBCRSAMPLES as present even if it is not
             * see: JPEGFixupTestSubsampling().
             */
            m_tif.setFieldBit(FieldBit.YCbCrSubsampling);
            return true;
        }