/// <summary> /// Compresses the specified image passed in the source pixel buffer. /// </summary> /// <param name="info">The meta info that describes the format and type of the pixels.</param> /// <param name="pixels">An array of bytes that represents the content of a bitmap image.</param> /// <param name="pixelCount">The number of pixel in the pixel array.</param> /// <param name="jfifHeader">if set to <c>true</c> a JFIF header will be added to the encoded byte stream.</param> /// <returns>An arraySegment with a reference to the byte array with the compressed data in the JPEG-LS format.</returns> /// <exception cref="InternalBufferOverflowException">The compressed output doesn't fit into the maximum defined output buffer.</exception> public static ArraySegment<byte> Compress(JpegLSMetadataInfo info, byte[] pixels, int pixelCount, bool jfifHeader) { if (info == null) throw new ArgumentNullException("info"); if (info.Width <= 0 || info.Width > 65535) throw new ArgumentException("Width property needs to be in the range <0, 65535>", "info"); if (info.Height <= 0 || info.Height > 65535) throw new ArgumentException("Height property needs to be in the range <0, 65535>", "info"); if (pixels == null) throw new ArgumentNullException("pixels"); if (pixelCount <= 0 || pixelCount > pixels.Length) throw new ArgumentException("pixelCount <= 0 || pixelCount > pixels.Length", "pixelCount"); Contract.EndContractBlock(); const int JpegLSHeaderLength = 100; // Assume compressed size <= uncompressed size (covers 99% of the cases). var buffer = new byte[pixels.Length + JpegLSHeaderLength]; int compressedCount; if (!TryCompress(info, pixels, pixels.Length, jfifHeader, buffer, buffer.Length, out compressedCount)) { // Increase output buffer to hold compressed data. buffer = new byte[(int)(pixels.Length * 1.5) + JpegLSHeaderLength]; Contract.Assume(info.Width <= 65535); Contract.Assume(info.Height <= 65535); if (!TryCompress(info, pixels, pixels.Length, jfifHeader, buffer, buffer.Length, out compressedCount)) throw new InternalBufferOverflowException("Compression failed: compressed output larger then 1.5 * input."); } Contract.Assume(buffer.Length >= compressedCount); return new ArraySegment<byte>(buffer, 0, compressedCount); }
public void EquatableWithNull() { var a = new JpegLSMetadataInfo(); Assert.IsFalse(a.Equals(null)); Assert.IsFalse(a.Equals((object)null)); }
public void EquatableWithNull() { var a = new JpegLSMetadataInfo(); JpegLSMetadataInfo b = null; Assert.IsFalse(a.Equals(b)); Assert.IsFalse(a.Equals((object)null)); }
public void EquatableDifferentObjects() { var a = new JpegLSMetadataInfo(); var b = new JpegLSMetadataInfo { Height = 2 }; Assert.IsFalse(a.Equals(b)); Assert.IsFalse(a.Equals((object)b)); }
public void GetMetadataInfoFromNearLosslessEncodedColorImage() { var source = ReadAllBytes("T8C0E3.JLS"); var info = JpegLSCodec.GetMetadataInfo(source); var expected = new JpegLSMetadataInfo { Height = 256, Width = 256, BitsPerComponent = 8, ComponentCount = 3, AllowedLossyError = 3 }; Assert.AreEqual(expected, info); }
public void ConstructDefault() { var info = new JpegLSMetadataInfo(); Assert.AreEqual(1, info.Width); Assert.AreEqual(1, info.Height); Assert.AreEqual(1, info.ComponentCount); Assert.AreEqual(2, info.BitsPerComponent); Assert.AreEqual(0, info.AllowedLossyError); Assert.AreEqual(JpegLSInterleaveMode.None, info.InterleaveMode); }
public void EquatableSameObjects() { var a = new JpegLSMetadataInfo(); var b = new JpegLSMetadataInfo(); Assert.IsTrue(a.Equals(b)); Assert.IsTrue(a.Equals((object)b)); Assert.AreEqual(a, b); Assert.AreEqual(b, a); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
private static int Main(string[] args) { // This sample demonstrates how to convert 8 bit monochrome images and 24 bit color images to a .jls // The input path should be a absolute path to a file format .NET can read (.bmp, .png, etc). string inputPath; if (!TryParseArguments(args, out inputPath)) { Console.WriteLine("Usage: Converter <path to image file>"); return(Failure); } try { // Load the image file and get the first frame. var decoder = BitmapDecoder.Create(new Uri(inputPath, UriKind.Absolute), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); var frame = decoder.Frames[0]; int componentCount; if (!TryGetComponentCount(frame.Format, out componentCount)) { Console.WriteLine("Input has format: {0}, which is not supported", frame.Format); return(Failure); } var uncompressedPixels = new byte[frame.PixelWidth * frame.PixelHeight * componentCount]; frame.CopyPixels(uncompressedPixels, frame.PixelWidth * componentCount, 0); // Prepare the 'info' metadata that describes the pixels in the byte buffer. var info = new JpegLSMetadataInfo(frame.PixelWidth, frame.PixelHeight, 8, componentCount); if (componentCount == 3) { info.InterleaveMode = JpegLSInterleaveMode.Line; // PixelFormat is Bgr24. CharLS expects RGB byte stream. // By enabling this CharLS will transform input before decoding. info.OutputBgr = true; } // Compress. var compressedPixels = JpegLSCodec.Compress(info, uncompressedPixels, true); Save(compressedPixels.Array, compressedPixels.Count, GetOutputPath(inputPath)); } catch (FileNotFoundException e) { Console.WriteLine("Error: " + e.Message); } return(Success); }
public void CompressOneByOneColor() { var info = new JpegLSMetadataInfo(1, 1, 8, 3); var uncompressedOriginal = new byte[] { 77, 33, 255 }; var compressedSegment = JpegLSCodec.Compress(info, uncompressedOriginal); var compressed = new byte[compressedSegment.Count]; Array.Copy(compressedSegment.Array, compressed, compressed.Length); var uncompressed = JpegLSCodec.Decompress(compressed); Assert.AreEqual(info.UncompressedSize, uncompressed.Length); Assert.AreEqual(uncompressedOriginal, uncompressed); }
private static int Main(string[] args) { // This sample demonstrates how to convert 8 bit monochrome images and 24 bit color images to a .jls // The input path should be a absolute path to a file format .NET can read (.bmp, .png, etc). string inputPath; if (!TryParseArguments(args, out inputPath)) { Console.WriteLine("Usage: Converter <path to image file>"); return Failure; } try { // Load the image file and get the first frame. var decoder = BitmapDecoder.Create(new Uri(inputPath, UriKind.Absolute), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); var frame = decoder.Frames[0]; int componentCount; if (!TryGetComponentCount(frame.Format, out componentCount)) { Console.WriteLine("Input has format: {0}, which is not supported", frame.Format); return Failure; } var uncompressedPixels = new byte[frame.PixelWidth * frame.PixelHeight * componentCount]; frame.CopyPixels(uncompressedPixels, frame.PixelWidth * componentCount, 0); // Prepare the 'info' metadata that describes the pixels in the byte buffer. var info = new JpegLSMetadataInfo(frame.PixelWidth, frame.PixelHeight, 8, componentCount); if (componentCount == 3) { info.InterleaveMode = JpegLSInterleaveMode.Line; // PixelFormat is Bgr24. CharLS expects RGB byte stream. // By enabling this CharLS will transform input before decoding. info.OutputBgr = true; } // Compress. var compressedPixels = JpegLSCodec.Compress(info, uncompressedPixels, true); Save(compressedPixels.Array, compressedPixels.Count, GetOutputPath(inputPath)); } catch (FileNotFoundException e) { Console.WriteLine("Error: " + e.Message); } return Success; }
public void CompressOneByOneBlackAndWhite() { var info = new JpegLSMetadataInfo(1, 1, 1, 1); var uncompressedOriginal = new byte[] { 1 }; var compressedSegment = JpegLSCodec.Compress(info, uncompressedOriginal); var compressed = new byte[compressedSegment.Count]; Array.Copy(compressedSegment.Array, compressed, compressed.Length); var uncompressed = JpegLSCodec.Decompress(compressed); Assert.AreEqual(info.UncompressedSize, uncompressed.Length); Assert.AreEqual(uncompressedOriginal, uncompressed); }
public void ConstructAndModify() { var info = new JpegLSMetadataInfo { BytesPerLine = 2, InterleaveMode = JpegLSInterleaveMode.Sample, OutputBgr = true }; Assert.AreEqual(2, info.BytesPerLine); Assert.AreEqual(JpegLSInterleaveMode.Sample, info.InterleaveMode); Assert.IsTrue(info.OutputBgr); info.InterleaveMode = JpegLSInterleaveMode.Line; Assert.AreEqual(JpegLSInterleaveMode.Line, info.InterleaveMode); }
/* Design notes: - The words compress/decompress are used as these are the terms used by the .NET BCLs (System.IO.Compression namespace) The CharLS C API uses the terms encode/decode. - The input/output buffers parameters are using the common .NET order, which is different the CharLS C API. */ /// <summary> /// Compresses the specified image passed in the source pixel buffer. /// </summary> /// <param name="info">The meta info that describes the format and type of the pixels.</param> /// <param name="pixels">An array of bytes that represents the content of a bitmap image.</param> /// <param name="jfifHeader">if set to <c>true</c> a JFIF header will be added to the encoded byte stream.</param> /// <returns>An arraySegment with a reference to the byte array with the compressed data in the JPEG-LS format.</returns> /// <exception cref="InternalBufferOverflowException">The compressed output doesn't fit into the maximum defined output buffer.</exception> public static ArraySegment<byte> Compress(JpegLSMetadataInfo info, byte[] pixels, bool jfifHeader = false) { if (info == null) throw new ArgumentNullException("info"); if (info.Width <= 0 || info.Width > 65535) throw new ArgumentException("Width property needs to be in the range <0, 65535>", "info"); if (info.Height <= 0 || info.Height > 65535) throw new ArgumentException("Height property needs to be in the range <0, 65535>", "info"); if (pixels == null) throw new ArgumentNullException("pixels"); Contract.EndContractBlock(); var pixelCount = pixels.Length; Contract.Assume(pixelCount > 0 && pixelCount <= pixels.Length); return Compress(info, pixels, pixelCount, jfifHeader); }
public void Compress() { var info = new JpegLSMetadataInfo(256, 256, 8, 3); var uncompressedOriginal = ReadAllBytes("TEST8.PPM", 15); uncompressedOriginal = TripletToPlanar(uncompressedOriginal, info.Width, info.Height); var compressedSegment = JpegLSCodec.Compress(info, uncompressedOriginal); var compressed = new byte[compressedSegment.Count]; Array.Copy(compressedSegment.Array, compressed, compressed.Length); var compressedInfo = JpegLSCodec.GetMetadataInfo(compressed); Assert.AreEqual(info, compressedInfo); var uncompressed = JpegLSCodec.Decompress(compressed); Assert.AreEqual(info.UncompressedSize, uncompressed.Length); Assert.AreEqual(uncompressedOriginal, uncompressed); }
private static PixelFormat GetPixelFormat(JpegLSMetadataInfo info) { switch (info.ComponentCount) { case 1: switch (info.BitsPerComponent) { case 8: return PixelFormats.Gray8; } break; case 3: switch (info.BitsPerComponent) { case 8: return PixelFormats.Rgb24; } break; } throw new NotSupportedException(); }
/// <summary> /// Tries the compress the array with pixels into the provided buffer. /// </summary> /// <param name="info">The meta info that describes the format and type of the pixels.</param> /// <param name="pixels">An array of bytes that represents the content of a bitmap image.</param> /// <param name="pixelCount">The number of pixel in the pixel array.</param> /// <param name="jfifHeader">if set to <c>true</c> a JFIF header will be added to the encoded byte stream.</param> /// <param name="destination">The destination buffer that will hold the JPEG-LS compressed (encoded) bit stream.</param> /// <param name="destinationLength">Length of the destination buffer that can be used (can be less then the length of the destination array).</param> /// <param name="compressedCount">The number of bytes that have been compressed (encoded) into the destination array.</param> /// <returns><c>true</c> when the compressed bit stream fits into the destination array, otherwise <c>false</c>.</returns> public static bool TryCompress(JpegLSMetadataInfo info, byte[] pixels, int pixelCount, bool jfifHeader, byte[] destination, int destinationLength, out int compressedCount) { if (info == null) throw new ArgumentNullException("info"); if (info.Width <= 0 || info.Width > 65535) throw new ArgumentException("Width property needs to be in the range <0, 65535>", "info"); if (info.Height <= 0 || info.Height > 65535) throw new ArgumentException("Height property needs to be in the range <0, 65535>", "info"); if (pixels == null) throw new ArgumentNullException("pixels"); if (pixelCount <= 0 || pixelCount > pixels.Length) throw new ArgumentException("pixelCount <= 0 || pixelCount > pixels.Length", "pixelCount"); if (destination == null) throw new ArgumentNullException("destination"); if (destinationLength <= 0 || destinationLength > destination.Length) throw new ArgumentException("destination <= 0 || destinationCount > destination.Length", "destinationLength"); Contract.Ensures(Contract.ValueAtReturn(out compressedCount) >= 0); var parameters = default(JlsParameters); info.CopyTo(ref parameters); if (jfifHeader) { parameters.Jfif.Version = (1 << 8) + 2; // JFIF version 1.02 parameters.Jfif.Units = 0; // No units, aspect ratio only specified parameters.Jfif.DensityX = 1; // use standard 1:1 aspect ratio. (density should always be set to non-zero values). parameters.Jfif.DensityY = 1; } var errorMessage = new StringBuilder(256); JpegLSError result; if (Environment.Is64BitProcess) { long count; result = SafeNativeMethods.JpegLsEncode64(destination, destinationLength, out count, pixels, pixelCount, ref parameters, errorMessage); compressedCount = (int)count; } else { result = SafeNativeMethods.JpegLsEncode(destination, destinationLength, out compressedCount, pixels, pixelCount, ref parameters, errorMessage); } Contract.Assume(compressedCount >= 0); if (result == JpegLSError.CompressedBufferTooSmall) return false; HandleResult(result, errorMessage); return true; }