/// <summary> /// One-liner to save Bitmaps to JPEG using LibJpeg. /// </summary> /// <param name="image">Bitmap</param> /// <param name="filename">Path to save to. Creates or overwrites if existing.</param> /// <param name="compression">Compression parameters.</param> public void Save(Bitmap image, string filename, CompressionParameters compression = null) { using (var jpeg = new JpegImage(image)) { jpeg.Save(filename, compression); } }
public Image Decode(Stream stream) { JpegImage jpg = new JpegImage(stream); int pixelWidth = jpg.Width; int pixelHeight = jpg.Height; byte[] pixels = new byte[pixelWidth * pixelHeight * 4]; if (!(jpg.Colorspace == Colorspace.RGB && jpg.BitsPerComponent == 8)) { throw new NotSupportedException("JpegDecoder only support RGB color space."); } for (int y = 0; y < pixelHeight; y++) { SampleRow row = jpg.GetRow(y); for (int x = 0; x < pixelWidth; x++) { Sample sample = row.GetAt(x); int offset = (y * pixelWidth + x) * 4; pixels[offset + 0] = (byte)sample[2]; pixels[offset + 1] = (byte)sample[1]; pixels[offset + 2] = (byte)sample[0]; pixels[offset + 3] = (byte)255; } } return new Image(pixelWidth, pixelHeight, pixels); }
public void Encode(Image image, Stream stream) { int pixelWidth = image.Width; int pixelHeight = image.Height; byte[] sourcePixels = image.Pixels; SampleRow[] rows = new SampleRow[pixelHeight]; for (int y = 0; y < pixelHeight; y++) { byte[] samples = new byte[pixelWidth * 3]; for (int x = 0; x < pixelWidth; x++) { int start = x * 3; int source = (y * pixelWidth + x) * 4; samples[start] = sourcePixels[source + 2]; samples[start + 1] = sourcePixels[source + 1]; samples[start + 2] = sourcePixels[source]; } rows[y] = new SampleRow(samples, pixelWidth, 8, 3); } JpegImage jpg = new JpegImage(rows, Colorspace.RGB); jpg.WriteJpeg(stream, new CompressionParameters { Quality = Quality }); }
/// <inheritdoc/> public void Encode(ImageBase image, Stream stream) { Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); int imageWidth = image.Width; int imageHeight = image.Height; SampleRow[] rows = new SampleRow[imageHeight]; Parallel.For( 0, imageHeight, y => { byte[] samples = new byte[imageWidth * 3]; for (int x = 0; x < imageWidth; x++) { Bgra32 color = Color.ToNonPremultiplied(image[x, y]); int start = x * 3; samples[start] = color.R; samples[start + 1] = color.G; samples[start + 2] = color.B; } rows[y] = new SampleRow(samples, imageWidth, 8, 3); }); using (JpegImage jpg = new JpegImage(rows, Colorspace.RGB)) { jpg.WriteJpeg(stream, new CompressionParameters { Quality = this.Quality }); } }
/// <summary> /// One-liner to save Bitmaps to JPEG using LibJpeg. /// </summary> /// <param name="image">Bitmap</param> /// <param name="filename">Path to save to. Creates or overwrites if existing.</param> /// <param name="compression">Compression parameters.</param> public void Save(Bitmap image, string filename, CompressionParameters compression = null) { using(var jpeg = new JpegImage(image)) { jpeg.Save(filename, compression); } }
public override Image Load(Stream s) { BitMiracle.LibJpeg.JpegImage j = new BitMiracle.LibJpeg.JpegImage(s); Image i = (Image)j.ToBitmap(); j.Dispose(); System.GC.Collect(); return i; }
public override Image Load(Stream s) { BitMiracle.LibJpeg.JpegImage j = new BitMiracle.LibJpeg.JpegImage(s); Image i = (Image)j.ToBitmap(); j.Dispose(); System.GC.Collect(); return(i); }
public override void Save(Image i, Stream dest) { BitMiracle.LibJpeg.JpegImage j = BitMiracle.LibJpeg.JpegImage.FromBitmap((System.Drawing.Bitmap)i); CompressionParameters c = new CompressionParameters(); c.Quality = 100; c.SimpleProgressive = false; j.WriteJpeg(dest, c); j.Dispose(); System.GC.Collect(); }
public void TestDecompressionFromCMYKJpeg() { using (JpegImage jpeg = new JpegImage(m_testcase + "ammerland.jpg")) { Assert.AreEqual(jpeg.BitsPerComponent, 8); Assert.AreEqual(jpeg.ComponentsPerSample, 4); Assert.AreEqual(jpeg.Colorspace, Colorspace.CMYK); Assert.AreEqual(jpeg.Width, 315); Assert.AreEqual(jpeg.Height, 349); testBitmapOutput(jpeg, "ammerland.bmp", m_expectedResults); } }
public void TestCompressionResultsSameAsForCJpeg() { using (JpegImage jpeg = new JpegImage(Path.Combine(m_testcase, "test24.bmp"))) { testJpegOutput(jpeg, "test24.jpg", m_expectedResults); CompressionParameters parameters = new CompressionParameters(); parameters.Quality = 25; testJpegOutput(jpeg, parameters, "test24_25.jpg", m_expectedResults); parameters = new CompressionParameters(); parameters.SimpleProgressive = true; testJpegOutput(jpeg, parameters, "test24_prog.jpg", m_expectedResults); } }
private static JpegImage createImageFromPixels() { byte[] rowData = new byte[96]; for (int i = 0; i < rowData.Length; ++i) { if (i < 5) rowData[i] = 0xE4; else if (i < 15) rowData[i] = 0xAB; else if (i < 35) rowData[i] = 0x00; else if (i < 55) rowData[i] = 0x65; else rowData[i] = 0xF0; } const int width = 24; const int height = 25; const byte bitsPerComponent = 8; const byte componentsPerSample = 4; const Colorspace colorspace = Colorspace.CMYK; SampleRow row = new SampleRow(rowData, width, bitsPerComponent, componentsPerSample); SampleRow[] rows = new SampleRow[height]; for (int i = 0; i < rows.Length; ++i) rows[i] = row; JpegImage jpegImage = new JpegImage(rows, colorspace); Assert.AreEqual(jpegImage.Width, width); Assert.AreEqual(jpegImage.Height, rows.Length); Assert.AreEqual(jpegImage.BitsPerComponent, bitsPerComponent); Assert.AreEqual(jpegImage.ComponentsPerSample, componentsPerSample); Assert.AreEqual(jpegImage.Colorspace, colorspace); return jpegImage; }
internal DecompressorToJpegImage(JpegImage jpegImage) { m_jpegImage = jpegImage; }
private static void testBitmapFromFile(string sourceFileName, string bitmapFileName, string folderWithExpectedResults) { using (JpegImage jpeg = new JpegImage(sourceFileName)) { testBitmapOutput(jpeg, bitmapFileName, folderWithExpectedResults); } }
private static void testBitmapOutput(JpegImage jpeg, string bitmapFileName, string folderWithExpectedResults) { using (FileStream output = new FileStream(bitmapFileName, FileMode.Create)) jpeg.WriteBitmap(output); FileAssert.AreEqual(bitmapFileName, Path.Combine(folderWithExpectedResults, bitmapFileName)); }
private static void testJpegOutput(JpegImage jpeg, string jpegFileName, string folderWithExpectedResults) { testJpegOutput(jpeg, new CompressionParameters(), jpegFileName, folderWithExpectedResults); }
private static void testJpegOutput(JpegImage jpeg, CompressionParameters parameters, string jpegFileName, string folderWithExpectedResults) { using (FileStream output = new FileStream(jpegFileName, FileMode.Create)) jpeg.WriteJpeg(output, parameters); FileAssert.AreEqual(jpegFileName, Path.Combine(folderWithExpectedResults, jpegFileName)); }
private static void testJpegOutput(JpegImage jpeg, string jpegFileName, string folderWithExpectedResults) { testJpegOutput(jpeg, new CompressionParameters { Subsampling = Subsampling.LowDetail_4_1_1 }, jpegFileName, folderWithExpectedResults); }
private static void testJpegFromFile(string fileName, string jpegFileName, string folderWithExpectedResults) { using (JpegImage jpeg = new JpegImage(fileName)) { testJpegOutput(jpeg, jpegFileName, folderWithExpectedResults); } }
/// <summary> /// Decodes the image from the specified stream and sets /// the data to image. /// </summary> /// <param name="image">The image, where the data should be set to. /// Cannot be null (Nothing in Visual Basic).</param> /// <param name="stream">The stream, where the image should be /// decoded from. Cannot be null (Nothing in Visual Basic).</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="image"/> is null (Nothing in Visual Basic).</para> /// <para>- or -</para> /// <para><paramref name="stream"/> is null (Nothing in Visual Basic).</para> /// </exception> public void Decode(Image image, Stream stream) { Guard.NotNull(image, "image"); Guard.NotNull(stream, "stream"); JpegImage jpg = new JpegImage(stream); int pixelWidth = jpg.Width; int pixelHeight = jpg.Height; float[] pixels = new float[pixelWidth * pixelHeight * 4]; if (jpg.Colorspace == Colorspace.RGB && jpg.BitsPerComponent == 8) { Parallel.For( 0, pixelHeight, y => { SampleRow row = jpg.GetRow(y); for (int x = 0; x < pixelWidth; x++) { Sample sample = row.GetAt(x); int offset = ((y * pixelWidth) + x) * 4; pixels[offset + 0] = sample[0] / 255f; pixels[offset + 1] = sample[1] / 255f; pixels[offset + 2] = sample[2] / 255f; pixels[offset + 3] = 1; } }); } else if (jpg.Colorspace == Colorspace.Grayscale && jpg.BitsPerComponent == 8) { Parallel.For( 0, pixelHeight, y => { SampleRow row = jpg.GetRow(y); for (int x = 0; x < pixelWidth; x++) { Sample sample = row.GetAt(x); int offset = ((y * pixelWidth) + x) * 4; pixels[offset + 0] = sample[0] / 255f; pixels[offset + 1] = sample[0] / 255f; pixels[offset + 2] = sample[0] / 255f; pixels[offset + 3] = 1; } }); } else { throw new NotSupportedException("JpegDecoder only supports RGB and Grayscale color spaces."); } image.SetPixels(pixelWidth, pixelHeight, pixels); jpg.Dispose(); }
public void TestCreateFromPixelsAndRecompress() { using (JpegImage jpegImage = createImageFromPixels()) { CompressionParameters compressionParameters = new CompressionParameters(); compressionParameters.Quality = 20; const string output = "JpegImageFromPixels_20.jpg"; testJpegOutput(jpegImage, compressionParameters, output, m_expectedResults); using (JpegImage recompressedImage = new JpegImage(output)) { Assert.AreEqual(recompressedImage.Colorspace, jpegImage.Colorspace); } } }
public void TestGrayscaleJpegToBitmap() { using (JpegImage jpegImage = new JpegImage(m_testcase + "turkey.jpg")) { testBitmapOutput(jpegImage, "turkey.png", m_expectedResults); } }
internal static void Decode( DicomPixelData oldPixelData, DicomPixelData newPixelData, DicomJpegParams parameters) { var pixelCount = oldPixelData.Height * oldPixelData.Width; if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrIct || newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrRct) { newPixelData.PhotometricInterpretation = PhotometricInterpretation.Rgb; } if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull422 || newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial422) { newPixelData.PhotometricInterpretation = PhotometricInterpretation.YbrFull; } if (newPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull) { newPixelData.PlanarConfiguration = PlanarConfiguration.Planar; } for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++) { var jpegData = oldPixelData.GetFrame(frame); // Destination frame should be of even length var frameSize = newPixelData.UncompressedFrameSize; if ((frameSize & 1) == 1) ++frameSize; var destArray = new byte[frameSize]; using (var stream = new MemoryStream(jpegData.Data)) { var decoder = new JpegImage(stream); var w = decoder.Width; var h = decoder.Height; for (var c = 0; c < decoder.ComponentsPerSample; c++) { var pos = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * pixelCount) : c; var offset = newPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? 1 : decoder.ComponentsPerSample; if (newPixelData.BytesAllocated == 1) { for (var y = 0; y < h; ++y) { var row = decoder.GetRow(y); for (var x = 0; x < w; ++x) { destArray[pos] = (byte)row[x][c]; pos += offset; } } } #if SUPPORT16BIT else if (newPixelData.BytesAllocated == 2) { var destArray16 = new short[frameSize >> 1]; for (var y = 0; y < h; ++y) { var row = decoder.GetRow(y); for (var x = 0; x < w; ++x) { destArray16[pos] = row[x][c]; pos += offset; } } Buffer.BlockCopy(destArray16, 0, destArray, 0, frameSize); } #endif else { throw new InvalidOperationException( $"JPEG module does not support Bits Allocated == {newPixelData.BitsAllocated}!"); } } newPixelData.AddFrame(new MemoryByteBuffer(destArray)); } } }
internal static void Encode( DicomPixelData oldPixelData, DicomPixelData newPixelData, DicomJpegParams parameters) { if ((oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrFull422) || (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial422) || (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.YbrPartial420)) { throw new InvalidOperationException( "Photometric Interpretation '" + oldPixelData.PhotometricInterpretation + "' not supported by JPEG encoder"); } var w = oldPixelData.Width; var h = oldPixelData.Height; for (var frame = 0; frame < oldPixelData.NumberOfFrames; frame++) { var frameData = oldPixelData.GetFrame(frame); var nc = oldPixelData.SamplesPerPixel; var sgnd = oldPixelData.PixelRepresentation == PixelRepresentation.Signed; var rows = Enumerable.Range(0, h).Select(i => new short[w, nc]).ToArray(); for (var c = 0; c < nc; c++) { var pos = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? (c * w * h) : c; var offset = oldPixelData.PlanarConfiguration == PlanarConfiguration.Planar ? 1 : nc; if (oldPixelData.BytesAllocated == 1) { var data = frameData.Data; if (sgnd) { if (oldPixelData.BitsStored < 8) { var sign = (byte)(1 << oldPixelData.HighBit); var mask = (byte)(0xff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored)); for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { var pixel = (sbyte)data[pos]; rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel); pos += offset; } } } else { for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { rows[y][x, c] = (sbyte)data[pos]; pos += offset; } } } } else { for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { rows[y][x, c] = data[pos]; pos += offset; } } } } #if SUPPORT16BIT else if (oldPixelData.BytesAllocated == 2) { if (sgnd) { if (oldPixelData.BitsStored < 16) { var frameData16 = new ushort[w * h]; Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size); var sign = (ushort)(1 << oldPixelData.HighBit); var mask = (ushort)(0xffff >> (oldPixelData.BitsAllocated - oldPixelData.BitsStored)); for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { var pixel = frameData16[pos]; rows[y][x, c] = (short)((pixel & sign) > 0 ? -(((-pixel) & mask) + 1) : pixel); pos += offset; } } } else { var frameData16 = new short[w * h]; Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size); for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { rows[y][x, c] = frameData16[pos]; pos += offset; } } } } else { var frameData16 = new ushort[w * h]; Buffer.BlockCopy(frameData.Data, 0, frameData16, 0, (int)frameData.Size); for (var y = 0; y < h; ++y) { for (var x = 0; x < w; ++x) { rows[y][x, c] = (short)frameData16[pos]; pos += offset; } } } } #endif else { throw new InvalidOperationException( $"JPEG codec does not support Bits Allocated == {oldPixelData.BitsAllocated}"); } } try { using (var stream = new MemoryStream()) { var sampleRows = rows.Select( row => new SampleRow( ToRawRow(row, oldPixelData.BitsAllocated), w, (byte)oldPixelData.BitsStored, (byte)nc)).ToArray(); var colorSpace = GetColorSpace(oldPixelData.PhotometricInterpretation); using (var encoder = new JpegImage(sampleRows, colorSpace)) { encoder.WriteJpeg(stream, ToCompressionParameters(parameters)); } newPixelData.AddFrame(new MemoryByteBuffer(stream.ToArray())); } } catch (Exception e) { throw new InvalidOperationException("Unable to JPEG encode image", e); } } if (oldPixelData.PhotometricInterpretation == PhotometricInterpretation.Rgb) { newPixelData.PlanarConfiguration = PlanarConfiguration.Interleaved; } }
/// <summary> /// Decodes the image from the specified stream and sets /// the data to image. /// </summary> /// <param name="image">The image, where the data should be set to. /// Cannot be null (Nothing in Visual Basic).</param> /// <param name="stream">The stream, where the image should be /// decoded from. Cannot be null (Nothing in Visual Basic).</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="image"/> is null (Nothing in Visual Basic).</para> /// <para>- or -</para> /// <para><paramref name="stream"/> is null (Nothing in Visual Basic).</para> /// </exception> public void Decode(ExtendedImage image, Stream stream) { Guard.NotNull(image, "image"); Guard.NotNull(stream, "stream"); if (UseLegacyLibrary) { FluxCoreJpegDecoder fluxCoreJpegDecoder = new FluxCoreJpegDecoder(stream); DecodedJpeg jpg = fluxCoreJpegDecoder.Decode(); jpg.Image.ChangeColorSpace(ColorSpace.RGB); int pixelWidth = jpg.Image.Width; int pixelHeight = jpg.Image.Height; byte[] pixels = new byte[pixelWidth * pixelHeight * 4]; byte[][,] sourcePixels = jpg.Image.Raster; for (int y = 0; y < pixelHeight; y++) { for (int x = 0; x < pixelWidth; x++) { int offset = (y * pixelWidth + x) * 4; pixels[offset + 0] = sourcePixels[0][x, y]; pixels[offset + 1] = sourcePixels[1][x, y]; pixels[offset + 2] = sourcePixels[2][x, y]; pixels[offset + 3] = (byte)255; } } //------- // image.DensityXInt32 = jpg.Image.DensityX; image.DensityYInt32 = jpg.Image.DensityY; image.SetPixels(pixelWidth, pixelHeight, pixels); } else { JpegImage jpg = new JpegImage(stream); int pixelWidth = jpg.Width; int pixelHeight = jpg.Height; byte[] pixels = new byte[pixelWidth * pixelHeight * 4]; if (!(jpg.Colorspace == Colorspace.RGB && jpg.BitsPerComponent == 8)) { throw new UnsupportedImageFormatException(); } for (int y = 0; y < pixelHeight; y++) { SampleRow row = jpg.GetRow(y); for (int x = 0; x < pixelWidth; x++) { //Sample sample = row.GetAt(x); int offset = (y * pixelWidth + x) * 4; row.GetComponentsAt(x, out pixels[offset + 0], out pixels[offset + 1], out pixels[offset + 2]); //r = (byte)sample[0]; //g = (byte)sample[1]; //b = (byte)sample[2]; //pixels[offset + 0] = r; //pixels[offset + 1] = g; //pixels[offset + 2] = b; pixels[offset + 3] = (byte)255; } } image.SetPixels(pixelWidth, pixelHeight, pixels); } }
private static void testJpegFromBitmap(Bitmap bmp, string jpegFileName) { using (JpegImage jpeg = new JpegImage(bmp)) { Assert.AreEqual(jpeg.Width, bmp.Width); Assert.AreEqual(jpeg.Height, bmp.Height); Assert.AreEqual(jpeg.ComponentsPerSample, 3);//Number of components in Bitmap using (FileStream output = new FileStream(jpegFileName, FileMode.Create)) jpeg.WriteJpeg(output); } FileAssert.AreEqual(jpegFileName, Path.Combine(m_expectedResults, jpegFileName)); }