示例#1
0
        /// <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));
        }
示例#5
0
        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);
        }
示例#6
0
        public void EquatableDifferentObjects()
        {
            var a = new JpegLSMetadataInfo();
            var b = new JpegLSMetadataInfo {
                Height = 2
            };

            Assert.IsFalse(a.Equals(b));
            Assert.IsFalse(a.Equals((object)b));
        }
示例#7
0
        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);
        }
示例#9
0
        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());
        }
示例#10
0
        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);
        }
示例#11
0
        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());
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
        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;
        }
示例#15
0
        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);
        }
示例#16
0
        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);
        }
示例#17
0
        /* 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);
        }
示例#18
0
        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);
        }
示例#19
0
        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);
        }
示例#20
0
        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();
        }
示例#21
0
        /// <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;
        }