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); }
/// <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; }
private bool jpeg_create_decompress_encap() { try { m_libjpeg_jpeg_decompress_struct = new JpegDecompressor(); } catch (Exception) { return false; } return true; }
private bool TIFFjpeg_create_decompress() { /* initialize JPEG error handling */ try { m_decompression = new JpegDecompressor(); m_common = m_decompression; } catch (Exception) { return false; } return true; }
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; }