private static void testAdobeJPG() { JpegDecoder jpegLibraryDecoder = new JpegDecoder(); byte[] rawTileBuffer = File.ReadAllBytes("sof3.jpg"); int tileWidth = 256; int tileHeight = 240; byte[] tileBuff = new byte[tileWidth * tileHeight * 2]; ReadOnlyMemory <byte> rawTileReadOnlyMemory; rawTileReadOnlyMemory = new ReadOnlyMemory <byte>(rawTileBuffer); jpegLibraryDecoder.SetInput(rawTileReadOnlyMemory); //jpegLibraryDecoder.SetFrameHeader() jpegLibraryDecoder.Identify(); // fails to identify. missing markers or whatever: Failed to decode JPEG data at offset 91149. No marker found.' jpegLibraryDecoder.SetOutputWriter(new JpegDecode.JpegBufferOutputWriterGreaterThan8Bit(tileWidth / 2, tileHeight, jpegLibraryDecoder.Precision, 2, tileBuff, 16)); jpegLibraryDecoder.Decode(); File.WriteAllBytes("sof3-decodetest.raw", tileBuff); }
public void JpegEncoderDecoderTest() { // Encode and decode a basic raster structure. var colorModel = new ColorModel(); colorModel.ColorSpace = ColorSpace.YCbCr; colorModel.Opaque = true; byte[][][] originalRaster = GetRaster(); var image = new Image(colorModel, originalRaster); var stream = new MemoryStream(); var encoder = new JpegEncoder(image, 50, stream); encoder.Encode(); stream.Seek(0, SeekOrigin.Begin); var decoder = new JpegDecoder(stream); DecodedJpeg decodedImage = decoder.Decode(); // Check that the returned raster structure looks something like what we passed in. for (int i = 0; i < 3; i++) { for (int j = 0; j < width; j++) { for (int k = 0; k < height; k++) { // Tune this. int diff = Math.Abs(decodedImage.Image.Raster[i][j][k] - originalRaster[i][j][k]); Assert.IsTrue(diff < 5); } } } ClientLogger.Debug("Finished JpegEncoderDecoder test."); }
public void TestJpegLibrary() { var decoder = new JpegDecoder(); decoder.SetInput(_inputBytes); decoder.Identify(); int width = decoder.Width; int height = decoder.Height; Rgba32[] rgba = new Rgba32[width * height]; byte[] ycbcr = ArrayPool <byte> .Shared.Rent(3 *rgba.Length); try { var outputWriter = new JpegBufferOutputWriter(decoder.Width, decoder.Height, 3, ycbcr); decoder.SetOutputWriter(outputWriter); decoder.Decode(); JpegYCbCrToRgbConverter.Shared.ConvertYCbCr8ToRgba32(ycbcr, MemoryMarshal.AsBytes(rgba.AsSpan()), decoder.Width * decoder.Height); } finally { ArrayPool <byte> .Shared.Return(ycbcr); } }
public static byte[] DecodeJpeg(Stream sourceStream) { // Decode JPEG from stream var decoder = new JpegDecoder(sourceStream); var jpegDecoded = decoder.Decode(); var img = jpegDecoded.Image; img.ChangeColorSpace(ColorSpace.Rgb); // Init Buffer int w = img.Width; int h = img.Height; var result = new byte[w * h * 4]; byte[][][] pixelsFromJpeg = img.Raster; // Copy FluxJpeg buffer into WriteableBitmap int i = 0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { result[i++] = pixelsFromJpeg[2][x][y]; // B result[i++] = pixelsFromJpeg[1][x][y]; // G result[i++] = pixelsFromJpeg[0][x][y]; // R result[i++] = 0xFF; } } return(result); }
static Image Resize(string pathIn, int edge) { JpegDecoder decoder = new JpegDecoder(File.Open(pathIn, FileMode.Open)); DecodedJpeg jpeg = decoder.Decode(); ImageResizer resizer = new ImageResizer(jpeg.Image); return(resizer.ResizeToScale(edge, ResamplingFilters.LowpassAntiAlias)); }
public static Image FromFile(string filename) { //TODO: review here //should not depend on the extension string fileext = IO.Path.GetExtension(filename).ToLower(); switch (fileext) { default: throw new NotSupportedException(); case ".jpg": { JpegDecoder jpegDec = new JpegDecoder(); ImageTools.ExtendedImage outputImg = new ImageTools.ExtendedImage(); using (System.IO.FileStream fs = new IO.FileStream(filename, IO.FileMode.Open)) { jpegDec.Decode(outputImg, fs); } //return bitmap return(new Bitmap(outputImg.PixelWidth, outputImg.PixelHeight, outputImg.Pixels, outputImg.DensityXInt32, outputImg.DensityYInt32)); } case ".gif": { GifDecoder gifDec = new GifDecoder(); ImageTools.ExtendedImage outputImg = new ImageTools.ExtendedImage(); using (System.IO.FileStream fs = new IO.FileStream(filename, IO.FileMode.Open)) { gifDec.Decode(outputImg, fs); } //return bitmap return(new Bitmap(outputImg.PixelWidth, outputImg.PixelHeight, outputImg.Pixels, outputImg.DensityXInt32, outputImg.DensityYInt32)); } case ".png": { ImageTools.IO.Png.PngDecoder pngDecoder = new PngDecoder(); //HjgPngDecoder pngDecoder = new HjgPngDecoder(); //PngDecoder pngDecoder = new PngDecoder(); ImageTools.ExtendedImage outputImg = new ImageTools.ExtendedImage(); using (System.IO.FileStream fs = new IO.FileStream(filename, IO.FileMode.Open)) { pngDecoder.Decode(outputImg, fs); } Bitmap bmp = new Bitmap(outputImg.PixelWidth, outputImg.PixelHeight, outputImg.Pixels, outputImg.DensityXInt32, outputImg.DensityYInt32); bmp.PixelFormat = Imaging.PixelFormat.Format32bppArgb; return(bmp); } } return(null); }
private static MemoryStream JpegDecode(MemoryStream jpegData) { var byteStream = new MemoryStream(); JpegDecoder d = new JpegDecoder(); var img = d.Decode(new Configuration(new JpegConfigurationModule()), jpegData); img.SaveAsBmp(byteStream, new SixLabors.ImageSharp.Formats.Bmp.BmpEncoder()); //using SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(jpegData, new JpegDecoder()); // image.SaveAsBmp(byteStream); return(byteStream); }
public void Decode_VerifyQuality(string imagePath, int quality) { var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { using (Image image = JpegDecoder.Decode(Configuration.Default, stream)) { JpegMetadata meta = image.Metadata.GetJpegMetadata(); Assert.Equal(quality, meta.Quality); } } }
public static Task <int> DebugDump(FileInfo source, string output, CancellationToken cancellationToken) { if (source is null || source.Length == 0) { Console.WriteLine("Input file are not specified."); return(Task.FromResult(1)); } if (string.IsNullOrEmpty(output)) { output = source.FullName; } byte[] input = File.ReadAllBytes(source.FullName); var decoder = new JpegDecoder(); decoder.SetInput(input); decoder.Identify(); int numberOfComponents = decoder.NumberOfComponents; if (numberOfComponents > 4) { throw new NotSupportedException("Number of components greater than 4 is not supported."); } ushort[] buffer = new ushort[decoder.Width * decoder.Height * 4]; var outputWriter = new JpegExtendingOutputWriter(decoder.Width, decoder.Height, 4, decoder.Precision, buffer); decoder.SetOutputWriter(outputWriter); decoder.Decode(); // We use RGBA PNG image to store 4 components. // Its content may be Grayscale, YCbCr or others. Rgba32[] pixels = new Rgba32[decoder.Width * decoder.Height]; Array.Fill(pixels, new Rgba32(255, 255, 255, 255)); using var image = Image.WrapMemory(pixels.AsMemory(), decoder.Width, decoder.Height); // high bits CopyHighBits(buffer, pixels, numberOfComponents); image.Save(output + ".high.png"); // apply prediction ApplyPrediction(buffer); // low bits CopyLowBits(buffer, pixels, numberOfComponents); image.Save(output + ".low-diff.png"); return(Task.FromResult(0)); }
public void Decode_VerifyQuality(string imagePath, int quality) { var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { var decoder = new JpegDecoder(); using (Image <Rgba32> image = decoder.Decode <Rgba32>(Configuration.Default, stream)) { JpegMetaData meta = image.MetaData.GetFormatMetaData(JpegFormat.Instance); Assert.Equal(quality, meta.Quality); } } }
public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) { var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { var decoder = new JpegDecoder(); using (Image <Rgba32> image = decoder.Decode <Rgba32>(Configuration.Default, stream)) { ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); } } }
public void TestDecode(string path) { byte[] jpegBytes = File.ReadAllBytes(path); var decoder = new JpegDecoder(); decoder.SetInput(jpegBytes); decoder.Identify(); ushort[] buffer = new ushort[decoder.Width * decoder.Height * 4]; var outputWriter = new JpegExtendingOutputWriter(decoder.Width, decoder.Height, 4, decoder.Precision, buffer); decoder.SetOutputWriter(outputWriter); decoder.Decode(); ushort[] reference = ImageHelper.LoadBuffer(path, decoder.Width, decoder.Height, decoder.NumberOfComponents); Assert.True(reference.AsSpan().SequenceEqual(buffer)); }
private static void testAdobeJPGEncode() { int tileWidth = 256; int tileHeight = 240; byte[] rawReferenceData = File.ReadAllBytes("rawToEncode-DNG.raw"); UInt16[] rawReferenceDataUInt16 = new UInt16[rawReferenceData.Length / 2]; for (int i = 0; i < rawReferenceDataUInt16.Length; i++) { rawReferenceDataUInt16[i] = BitConverter.ToUInt16(rawReferenceData, i * 2); } dng_stream whatever = new dng_stream(); DNGLosslessEncoder.EncodeLosslessJPEG(rawReferenceDataUInt16, (uint)tileHeight, (uint)tileWidth / 2, 2, 16, tileWidth, 2, whatever); File.WriteAllBytes("encodedTest.jpg", whatever.toByteArray()); // Try decode again JpegDecoder jpegLibraryDecoder = new JpegDecoder(); byte[] rawTileBuffer = File.ReadAllBytes("encodedTest.jpg"); byte[] tileBuff = new byte[tileWidth * tileHeight * 2]; ReadOnlyMemory <byte> rawTileReadOnlyMemory; rawTileReadOnlyMemory = new ReadOnlyMemory <byte>(rawTileBuffer); jpegLibraryDecoder.SetInput(rawTileReadOnlyMemory); //jpegLibraryDecoder.SetFrameHeader() jpegLibraryDecoder.Identify(); // fails to identify. missing markers or whatever: Failed to decode JPEG data at offset 91149. No marker found.' jpegLibraryDecoder.SetOutputWriter(new JpegDecode.JpegBufferOutputWriterGreaterThan8Bit(tileWidth / 2, tileHeight, jpegLibraryDecoder.Precision, 2, tileBuff, 16)); jpegLibraryDecoder.Decode(); File.WriteAllBytes("sof3-encodedecodetest.raw", tileBuff); }
public void Setup() { var ms = new MemoryStream(); using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("JpegLibrary.Benchmarks.Resources.HETissueSlide.jpg")) { resourceStream.CopyTo(ms); } ms.Seek(0, SeekOrigin.Begin); // Load the image and expand it using var baseImage = Image.Load(ms); using var image = new Image <Rgba32>(baseImage.Width * 4, baseImage.Height * 4); image.Mutate(ctx => { ctx.DrawImage(baseImage, new Point(0, 0), opacity: 1); ctx.DrawImage(baseImage, new Point(0, baseImage.Height), opacity: 1); ctx.DrawImage(baseImage, new Point(baseImage.Width, 0), opacity: 1); ctx.DrawImage(baseImage, new Point(baseImage.Width, baseImage.Height), opacity: 1); }); ms.Seek(0, SeekOrigin.Begin); ms.SetLength(0); image.SaveAsJpeg(ms); byte[] inputBytes = ms.ToArray(); var decoder = new JpegDecoder(); decoder.SetInput(inputBytes); decoder.Identify(); _width = decoder.Width; _height = decoder.Height; byte[] ycbcr = new byte[3 * _width * _height]; decoder.SetOutputWriter(new JpegBufferOutputWriter(_width, _height, 3, ycbcr)); decoder.Decode(); _rgba = new Rgba32[_width * _height]; JpegYCbCrToRgbConverter.Shared.ConvertYCbCr8ToRgba32(ycbcr, MemoryMarshal.AsBytes(_rgba.AsSpan()), _width * _height); }
override public byte[] getRawImageData(int index) { using (Tiff input = Tiff.Open(paths[index], "r")) { // Try to make Adobe DNG work bool subIFDTagExists = input.GetField(TIFFTAG_SUBIFDS) != null; if (subIFDTagExists) { UInt64 offsetOfSubIFD = (UInt64)input.GetField(TIFFTAG_SUBIFDS)[1].TolongArray()[0]; input.SetSubDirectory((long)offsetOfSubIFD); } if (input.IsTiled()) { if (compressedFileCacheIndex == index) { return((byte[])compressedFileCache.Clone()); } int tileWidth = input.GetField(TiffTag.TILEWIDTH)[0].ToInt(); int tileHeight = input.GetField(TiffTag.TILELENGTH)[0].ToInt(); byte[] buffer = new byte[width * height * 2]; long tileSize = input.TileSize(); byte[] tileBuff = new byte[tileSize]; byte[] tileBuffMessy = new byte[tileSize]; JpegDecoder jpegLibraryDecoder = new JpegDecoder(); long rawTileSize; byte[] rawTileBuffer; int tileIndex; ReadOnlyMemory <byte> rawTileReadOnlyMemory; int row, col, x, y; bool isSOF3Stuff = false; for (row = 0; row < height; row += tileHeight) { for (col = 0; col < width; col += tileWidth) { // Read the tile if (isSOF3Stuff || input.ReadTile(tileBuff, 0, col, row, 0, 0) < 0) { isSOF3Stuff = true; // This means the normal tile reading failed, so we try something else. tileIndex = input.ComputeTile(col, row, 0, 0); rawTileSize = input.RawTileSize(tileIndex); rawTileBuffer = new byte[rawTileSize]; input.ReadRawTile(tileIndex, rawTileBuffer, 0, (int)rawTileSize); //File.WriteAllBytes("col"+col+"_row"+row+"_sof3.jpg",rawTileBuffer); rawTileReadOnlyMemory = new ReadOnlyMemory <byte>(rawTileBuffer); jpegLibraryDecoder.SetInput(rawTileReadOnlyMemory); //jpegLibraryDecoder.SetFrameHeader() jpegLibraryDecoder.Identify(); // fails to identify. missing markers or whatever: Failed to decode JPEG data at offset 91149. No marker found.' // Hyper messy. Need to give him the wrong width bc reasons... (he thinks its 2 components and only half the width. Whatever I guess) jpegLibraryDecoder.SetOutputWriter(new JpegDecode.JpegBufferOutputWriterGreaterThan8Bit(tileWidth / 2, tileHeight, jpegLibraryDecoder.Precision, 2, tileBuff, 16)); jpegLibraryDecoder.Decode(); //throw new Exception("Error reading data"); /* * // Translate jpegLibrary-ish to normal bayer stuff (whatever that f*****g means) * for(int yTile = 0; yTile < tileHeight; yTile++) * { * for (int xTile = 0; xTile < tileWidth; xTile++) * { * tileBuff[yTile * tileWidth *2 + xTile * 2] = tileBuffMessy[yTile * tileWidth *2 + xTile * 2]; * tileBuff[yTile * tileWidth *2 + xTile * 2+1] = tileBuffMessy[yTile * tileWidth *2 + xTile * 2+1]; * } * }*/ } int indexTileStuff = 0; // Iterate the rows in the tile for (y = row; y < row + tileHeight; y++) { if (y >= height) { break; } for (x = col; x < col + tileWidth; x++) { if (x >= width) { continue; } buffer[y * width * 2 + x * 2] = tileBuff[(y - row) * tileWidth * 2 + (x - col) * 2]; buffer[y * width * 2 + x * 2 + 1] = tileBuff[(y - row) * tileWidth * 2 + (x - col) * 2 + 1]; } } /*for (var i = 0; i < tileHeight && i + row < height; i++) * { * var length = tileWidth; * * // Index of the first position in the row * var position = (row + i) * tileWidth + col; * * // Check we are not outside the image * if (col + length > width) * { * length = width - col; * } * for (var p = 0; p < length; p++) * { * buffer[position + p] = buffer[indexTileStuff * 2 + p * 2]; * } * * * index += tileWidth; * * }*/ } } compressedFileCache = (byte[])buffer.Clone(); compressedFileCacheIndex = index; return(buffer); } else { byte[] buffer = new byte[input.StripSize() * input.NumberOfStrips()]; int bufferoffset = 0; int stripsize = input.StripSize(); int stripcount = input.NumberOfStrips(); for (int i = 0; i < stripcount; i++) { int read = input.ReadEncodedStrip(i, buffer, bufferoffset, stripsize); // This throws an error with Adobe-created DNG files if (read == -1) { throw new Exception("Error on decoding strip " + i + " of " + input.FileName()); } bufferoffset += read; } return(buffer); } } }
public void Decode(DcmDataset dataset, DcmPixelData oldPixelData, DcmPixelData newPixelData, DcmCodecParameters parameters) { if (oldPixelData.NumberOfFrames == 0) { return; } // Determine JPEG image precision and assert that the implemented codec supports this precision int precision; try { precision = JpegHelper.ScanHeaderForBitDepth(oldPixelData); } catch (DicomCodecException) { precision = oldPixelData.BitsStored; } AssertImagePrecision(precision); // Ensure consistency in the new pixel data header if (precision > 8) { newPixelData.BitsAllocated = 16; } else if (newPixelData.BitsStored <= 8) { newPixelData.BitsAllocated = 8; } // Set up new pixel data specifics newPixelData.PhotometricInterpretation = newPixelData.PhotometricInterpretation.Equals("YBR_FULL_422") || newPixelData.PhotometricInterpretation.Equals("YBR_PARTIAL_422") ? "YBR_FULL" : oldPixelData.PhotometricInterpretation; if (newPixelData.PhotometricInterpretation.Equals("YBR_FULL")) { newPixelData.PlanarConfiguration = 1; } try { for (int j = 0; j < oldPixelData.NumberOfFrames; ++j) { var frameData = new byte[newPixelData.UncompressedFrameSize]; var jpegStream = new MemoryStream(oldPixelData.GetFrameDataU8(j)); // Decode JPEG from stream var decoder = new JpegDecoder(jpegStream); var jpegDecoded = decoder.Decode(); var img = jpegDecoded.Image; // Init Buffer int w = img.Width; int h = img.Height; var pixelsFromJpeg = img.Raster; // Copy FluxJpeg buffer into frame data array /* * int comps = pixelsFromJpeg.GetLength(0); * int preIncr = newPixelData.BytesAllocated - comps; * * if (preIncr < 0) * throw new InvalidOperationException( * String.Format("Number of JPEG components: {0} exceeds number of bytes allocated: {1}", * comps, newPixelData.BytesAllocated)); */ int i = 0; for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { var pixel = pixelsFromJpeg[0][x, y]; frameData[i++] = (byte)((pixel >> 8) & 0xff); frameData[i++] = (byte)(pixel & 0xff); // for (int k = 0; k < preIncr; ++k) frameData[i++] = 0xff; // for (int k = 0; k < comps; ++k) frameData[i++] = pixelsFromJpeg[k][x, y]; } } oldPixelData.Unload(); if (newPixelData.IsPlanar) { DcmCodecHelper.ChangePlanarConfiguration(frameData, frameData.Length / newPixelData.BytesAllocated, newPixelData.BitsAllocated, newPixelData.SamplesPerPixel, 0); } newPixelData.AddFrame(frameData); } } catch (Exception e) { Debug.Log.Error("Failed to decode JPEG image: {0}, reason: {1}", e.StackTrace, e.Message); } }
override public byte[] getRawImageData(int index) { Dictionary <UInt32, byte[]> tagData = readCRITagData(paths[0]); if (tagData.ContainsKey((UInt32)Key.FrameData)) { // Detect compression // Only horizontal tiles are supported so far. Assuming there is no vertical tiling. if (tagData.ContainsKey((UInt32)Key.TileSizes)) { byte[] decodedOutputBuffer = new byte[width * height * 2]; byte[] tileSizeData = tagData[(UInt32)Key.TileSizes]; int tileCount = tileSizeData.Length / 8; // The tilesizes are saved as Uint64s I think, so dividing by 8 should give the right number. UInt64 totalSizeFromTileSizes = 0; UInt64[] tileSizes = new UInt64[tileCount]; for (int i = 0; i < tileCount; i++) { tileSizes[i] = BitConverter.ToUInt64(tileSizeData, i * 8); totalSizeFromTileSizes += tileSizes[i]; } byte[] compressedData = tagData[(UInt32)Key.FrameData]; JpegDecoder jpegLibraryDecoder = new JpegDecoder(); ReadOnlyMemory <byte> rawTileReadOnlyMemory; byte[] tmpBuffer; UInt64 alreadyRead = 0; UInt32 horizOffset = 0; foreach (UInt64 tileSize in tileSizes) { tmpBuffer = new byte[tileSize]; Array.Copy(compressedData, (int)alreadyRead, tmpBuffer, 0, (int)tileSize); alreadyRead += tileSize; rawTileReadOnlyMemory = new ReadOnlyMemory <byte>(tmpBuffer); jpegLibraryDecoder.SetInput(rawTileReadOnlyMemory); //jpegLibraryDecoder.SetFrameHeader() jpegLibraryDecoder.Identify(); // fails to identify. missing markers or whatever: Failed to decode JPEG data at offset 91149. No marker found.' int tileActualWidth = jpegLibraryDecoder.Width / 2; int tileActualHeight = jpegLibraryDecoder.Height * 2; byte[] tileBuff = new byte[jpegLibraryDecoder.Width * jpegLibraryDecoder.Height * 2]; jpegLibraryDecoder.SetOutputWriter(new JpegDecode.JpegBufferOutputWriterGreaterThan8BitCRI(jpegLibraryDecoder.Width, jpegLibraryDecoder.Height, jpegLibraryDecoder.Precision - 1, 1, tileBuff, 16)); jpegLibraryDecoder.Decode(); int actualX; for (int y = 0; y < tileActualHeight; y++) { for (int x = 0; x < tileActualWidth; x++) { actualX = (Int32)horizOffset + x; decodedOutputBuffer[y * width * 2 + actualX * 2] = tileBuff[y * tileActualWidth * 2 + (x) * 2]; decodedOutputBuffer[y * width * 2 + actualX * 2 + 1] = tileBuff[y * tileActualWidth * 2 + (x) * 2 + 1]; } } horizOffset += (uint)tileActualWidth; } File.WriteAllBytes("decoded raw cri" + width + " " + height + ".raw", decodedOutputBuffer); return(decodedOutputBuffer); } else { // Presuming uncompressed return(tagData[(UInt32)Key.FrameData]); } //File.WriteAllBytes("rawcri.jpg", tagData[(UInt32)Key.FrameData]); } else { throw new Exception("CRI file contains no image data apparently."); } }
public static Task <int> Decode(FileInfo source, string output) { using var writer = new MemoryPoolBufferWriter(); using (FileStream stream = source.OpenRead()) { ReadAllBytes(stream, writer); } var decoder = new JpegDecoder(); decoder.SetInput(writer.GetReadOnlySequence()); decoder.Identify(); if (decoder.NumberOfComponents != 1 && decoder.NumberOfComponents != 3) { // We only support Grayscale and YCbCr. throw new NotSupportedException("This color space is not supported"); } int width = decoder.Width; int height = decoder.Height; byte[] ycbcr = new byte[width * height * 3]; if (decoder.Precision == 8) { // This is the most common case for JPEG. // We use the fatest implement. decoder.SetOutputWriter(new JpegBufferOutputWriter8Bit(width, height, 3, ycbcr)); } else if (decoder.Precision < 8) { decoder.SetOutputWriter(new JpegBufferOutputWriterLessThan8Bit(width, height, decoder.Precision, 3, ycbcr)); } else { decoder.SetOutputWriter(new JpegBufferOutputWriterGreaterThan8Bit(width, height, decoder.Precision, 3, ycbcr)); } decoder.Decode(); if (decoder.NumberOfComponents == 1) { // For grayscale image, we need to fill Cb and Cr in the YCbCr buffer. for (int i = 0; i < ycbcr.Length; i += 3) { ycbcr[i + 1] = 128; ycbcr[i + 2] = 128; } } using var image = new Image <Rgb24>(width, height); // Convert YCbCr to RGB for (int i = 0; i < height; i++) { JpegYCbCrToRgbConverter.Shared.ConvertYCbCr8ToRgb24(ycbcr.AsSpan(i * width * 3, width * 3), MemoryMarshal.AsBytes(image.GetPixelRowSpan(i)), width); } image.Save(output); return(Task.FromResult(0)); }
public async ValueTask InvokeAsync(TiffImageDecoderContext context, ITiffImageDecoderPipelineNode next) { MemoryPool <byte> memoryPool = context.MemoryPool ?? MemoryPool <byte> .Shared; TiffFileContentReader contentReader = context.ContentReader ?? throw new InvalidOperationException(); IMemoryOwner <byte>?dataHandle = null; Memory <byte> data; try { const int BufferSize = 65536; using (var bufferWriter = new MemoryPoolBufferWriter(memoryPool)) { // Read JPEG stream TiffStreamRegion streamRegion = _streamRegion; do { int readSize = Math.Min(streamRegion.Length, BufferSize); Memory <byte> memory = bufferWriter.GetMemory(readSize); memory = memory.Slice(0, Math.Min(streamRegion.Length, memory.Length)); readSize = await contentReader.ReadAsync(streamRegion.Offset, memory, context.CancellationToken).ConfigureAwait(false); bufferWriter.Advance(readSize); streamRegion = new TiffStreamRegion(streamRegion.Offset + readSize, streamRegion.Length - readSize); } while (streamRegion.Length > 0); // Identify the image var decoder = new JpegDecoder(); decoder.MemoryPool = memoryPool; decoder.SetInput(bufferWriter.GetReadOnlySequence()); decoder.Identify(); if (decoder.Width != context.SourceImageSize.Width || decoder.Height != context.SourceImageSize.Height) { throw new InvalidOperationException("The image size does not match."); } if (decoder.Precision != 8) { throw new InvalidOperationException("Only 8-bit JPEG is supported."); } // Adjust buffer size and reading region to reduce buffer size int skippedWidth = context.SourceReadOffset.X / 8 * 8; int skippedHeight = context.SourceReadOffset.Y / 8 * 8; context.SourceReadOffset = new TiffPoint(context.SourceReadOffset.X % 8, context.SourceReadOffset.Y % 8); int bufferWidth = context.SourceReadOffset.X + context.ReadSize.Width; int bufferHeight = context.SourceReadOffset.Y + context.ReadSize.Height; context.SourceImageSize = new TiffSize(bufferWidth, bufferHeight); // Allocate buffer and decode image int dataSize = bufferWidth * bufferHeight * decoder.NumberOfComponents; dataHandle = memoryPool.Rent(dataSize); data = dataHandle.Memory.Slice(0, dataSize); decoder.SetOutputWriter(new LegacyJpegBufferOutputWriter(skippedWidth, bufferWidth, skippedHeight, bufferHeight, decoder.NumberOfComponents, data)); decoder.Decode(); } // Pass the buffer to the next middleware context.UncompressedData = data; await next.RunAsync(context).ConfigureAwait(false); context.UncompressedData = null; } finally { dataHandle?.Dispose(); } }
/// <inheritdoc /> public void Decompress(TiffDecompressionContext context, ReadOnlyMemory <byte> input, Memory <byte> output) { if (context is null) { throw new ArgumentNullException(nameof(context)); } // Identify this block JpegDecoder decoder = Interlocked.Exchange(ref _decoder, null) ?? LoadJpegDecoder(); decoder.MemoryPool = context.MemoryPool; decoder.SetInput(input); decoder.Identify(); // Validate we are capable of decoding this. TiffSize outputBufferSize = context.ImageSize; if (decoder.Width < outputBufferSize.Width || decoder.Height < outputBufferSize.Height) { throw new InvalidDataException("Image dimension is too small."); } // Check number of components if (decoder.NumberOfComponents != _numberOfComponents) { throw new InvalidDataException($"Expect {_numberOfComponents} components, but got {decoder.NumberOfComponents} components in the JPEG stream."); } JpegBlockOutputWriter outputWriter; if (decoder.Precision == 8) { if (context.BitsPerSample.GetFirstOrDefault() != 8) { throw new InvalidDataException("Precision of 8 bit is not expected."); } outputWriter = new JpegBuffer8BitOutputWriter(outputBufferSize.Width, context.SkippedScanlines, context.SkippedScanlines + context.RequestedScanlines, decoder.NumberOfComponents, output); } else if (decoder.Precision < 8) { if (context.BitsPerSample.GetFirstOrDefault() != 8) { throw new InvalidDataException($"Precision of {decoder.Precision} bit is not expected."); } outputWriter = new JpegBufferAny8BitOutputWriter(outputBufferSize.Width, context.SkippedScanlines, context.SkippedScanlines + context.RequestedScanlines, decoder.NumberOfComponents, decoder.Precision, output); } else if (decoder.Precision <= 16) { if (context.BitsPerSample.GetFirstOrDefault() != 16) { throw new InvalidDataException($"Precision of {decoder.Precision} bit is not expected."); } outputWriter = new JpegBufferAny16BitOutputWriter(outputBufferSize.Width, context.SkippedScanlines, context.SkippedScanlines + context.RequestedScanlines, decoder.NumberOfComponents, decoder.Precision, output); } else { throw new InvalidDataException($"Precision of {decoder.Precision} bit is not expected."); } // Decode decoder.SetOutputWriter(outputWriter); decoder.Decode(); // Reset state decoder.ResetInput(); decoder.ResetHeader(); decoder.ResetOutputWriter(); // Cache the instances Interlocked.CompareExchange(ref _decoder, decoder, null); }