public void CanSetEncoder()
        {
            using var image     = new Image <Rgba32>(1, 1);
            using var formatted = new FormattedImage(image, PngFormat.Instance);

            Assert.NotNull(formatted.Format);
            Assert.Equal(PngFormat.Instance, formatted.Format);

            Assert.Throws <ArgumentNullException>(() => formatted.Encoder = null);
            Assert.Throws <ArgumentException>(() => formatted.Encoder     = new JpegEncoder());

            formatted.Format = JpegFormat.Instance;
            Assert.Equal(typeof(JpegEncoder), formatted.Encoder.GetType());

            JpegSubsample current = ((JpegEncoder)formatted.Encoder).Subsample.GetValueOrDefault();

            Assert.Equal(JpegSubsample.Ratio444, current);
            formatted.Encoder = new JpegEncoder {
                Subsample = JpegSubsample.Ratio420
            };

            JpegSubsample replacement = ((JpegEncoder)formatted.Encoder).Subsample.GetValueOrDefault();

            Assert.NotEqual(current, replacement);
            Assert.Equal(JpegSubsample.Ratio420, replacement);
        }
Esempio n. 2
0
        public void DecodeGenerated_SaveBmp <TPixel>(
            TestImageProvider <TPixel> provider,
            JpegSubsample subsample,
            int quality)
            where TPixel : struct, IPixel <TPixel>
        {
            byte[] data;
            using (Image <TPixel> image = provider.GetImage())
            {
                JpegEncoder encoder = new JpegEncoder {
                    Subsample = subsample, Quality = quality
                };

                data = new byte[65536];
                using (MemoryStream ms = new MemoryStream(data))
                {
                    image.Save(ms, encoder);
                }
            }

            // TODO: Automatic image comparers could help here a lot :P
            Image <TPixel> mirror = provider.Factory.CreateImage(data);

            provider.Utility.TestName += $"_{subsample}_Q{quality}";
            provider.Utility.SaveTestOutputFile(mirror, "bmp");
        }
        public void EncodeJpeg(int executionCount, int quality, JpegSubsample subsample)
        {
            string[] testFiles = TestImages.Bmp.All
                                 .Concat(new[] { TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk })
                                 .ToArray();

            Image <Rgba32>[] testImages =
                testFiles.Select(
                    tf => TestImageProvider <Rgba32> .File(tf, pixelTypeOverride: PixelTypes.StandardImageClass).GetImage())
                .ToArray();

            using (MemoryStream ms = new MemoryStream())
            {
                this.Measure(executionCount,
                             () =>
                {
                    foreach (Image <Rgba32> img in testImages)
                    {
                        JpegEncoder encoder        = new JpegEncoder();
                        JpegEncoderOptions options = new JpegEncoderOptions {
                            Quality = quality, Subsample = subsample
                        };
                        img.Save(ms, encoder, options);
                        ms.Seek(0, SeekOrigin.Begin);
                    }
                },
                             // ReSharper disable once ExplicitCallerInfoArgument
                             $@"Encode {testFiles.Length} images"
                             );
            }
        }
Esempio n. 4
0
 public void Encode(ImageBase image, Stream stream, int quality, JpegSubsample sample)
 {
     if (image == null || stream == null){
         throw new ArgumentNullException();
     }
     ushort max = JpegConstants.MaxLength;
     if (image.Width >= max || image.Height >= max){
         throw new Exception($"Image is too large to encode at {image.Width}x{image.Height}.");
     }
     outputStream = stream;
     subsample = sample;
     for (int i = 0; i < theHuffmanSpec.Length; i++){
         theHuffmanLut[i] = new HuffmanLut(theHuffmanSpec[i]);
     }
     for (int i = 0; i < nQuantIndex; i++){
         quant[i] = new byte[Block.blockSize];
     }
     if (quality < 1){
         quality = 1;
     }
     if (quality > 100){
         quality = 100;
     }
     int scale;
     if (quality < 50){
         scale = 5000/quality;
     } else{
         scale = 200 - quality*2;
     }
     for (int i = 0; i < nQuantIndex; i++){
         for (int j = 0; j < Block.blockSize; j++){
             int x = unscaledQuant[i, j];
             x = (x*scale + 50)/100;
             if (x < 1){
                 x = 1;
             }
             if (x > 255){
                 x = 255;
             }
             quant[i][j] = (byte) x;
         }
     }
     int componentCount = 3;
     double densityX = ((Image2) image).HorizontalResolution;
     double densityY = ((Image2) image).VerticalResolution;
     WriteApplicationHeader((short) densityX, (short) densityY);
     WriteDqt();
     WriteSof0(image.Width, image.Height, componentCount);
     WriteDht(componentCount);
     using (IPixelAccessor pixels = image.Lock()){
         WriteSos(pixels);
     }
     buffer[0] = 0xff;
     buffer[1] = 0xd9;
     stream.Write(buffer, 0, 2);
     stream.Flush();
 }
Esempio n. 5
0
        public void CompressImagePng(string path, int quality, JpegSubsample jpegSubsample)
        {
            using (var image = SixLabors.ImageSharp.Image.Load(path))
            {
                PngEncoder encoder = new PngEncoder();

                encoder.CompressionLevel = 8;
                //JpegEncoder encoder = new JpegEncoder() { Quality = quality, Subsample = jpegSubsample };
                string outputPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path) + "_转换后" + Path.GetExtension(path));
                int    count      = 0;
                while (File.Exists(outputPath))
                {
                    count++;
                    outputPath = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(path) + count.ToString() + Path.GetExtension(outputPath));
                }
                image.Save(outputPath, encoder);
            }
        }
Esempio n. 6
0
        public void OpenBmp_SaveJpeg <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subSample, int quality)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage())
            {
                ImagingTestCaseUtility utility = provider.Utility;
                utility.TestName += "_" + subSample + "_Q" + quality;

                using (FileStream outputStream = File.OpenWrite(utility.GetTestOutputFileName("jpg")))
                {
                    image.Save(outputStream, new JpegEncoder()
                    {
                        Subsample = subSample,
                        Quality   = quality
                    });
                }
            }
        }
        public void CanEncode <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample, int quality)
            where TPixel : struct, IPixel <TPixel>
        {
            using (var image = provider.GetImage())
            {
                var encoder = new LibJpegTurboEncoder()
                {
                    Subsample = subsample,
                    Quality   = quality
                };
                string        info     = $"{subsample}-Q{quality}";
                ImageComparer comparer = GetComparer(quality, subsample);

                image.Save("/Users/pknopf/test.jpg", encoder);

                // Does DebugSave & load reference CompareToReferenceInput():
                image.VerifyEncoder(provider, "jpeg", info, encoder, comparer, referenceImageExtension: "png");
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Anton's SUPER-SCIENTIFIC tolerance threshold calculation
        /// </summary>
        private static ImageComparer GetComparer(int quality, JpegSubsample subsample)
        {
            float tolerance = 0.015f; // ~1.5%

            if (quality < 50)
            {
                tolerance *= 10f;
            }
            else if (quality < 75 || subsample == JpegSubsample.Ratio420)
            {
                tolerance *= 5f;
                if (subsample == JpegSubsample.Ratio420)
                {
                    tolerance *= 2f;
                }
            }

            return(ImageComparer.Tolerant(tolerance));
        }
Esempio n. 9
0
        public void OpenBmp_SaveJpeg <TColor>(TestImageProvider <TColor> provider, JpegSubsample subSample, int quality)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            Image <TColor> image = provider.GetImage();

            ImagingTestCaseUtility utility = provider.Utility;

            utility.TestName += "_" + subSample + "_Q" + quality;

            using (var outputStream = File.OpenWrite(utility.GetTestOutputFileName("jpg")))
            {
                var encoder = new JpegEncoder()
                {
                    Subsample = subSample,
                    Quality   = quality
                };

                image.Save(outputStream, encoder);
            }
        }
Esempio n. 10
0
        public async Task Encode_IsCancellable(JpegSubsample subsample, int cancellationDelayMs)
        {
            using var image  = new Image <Rgba32>(5000, 5000);
            using var stream = new MemoryStream();
            var cts = new CancellationTokenSource();

            if (cancellationDelayMs == 0)
            {
                cts.Cancel();
            }
            else
            {
                cts.CancelAfter(cancellationDelayMs);
            }

            var encoder = new JpegEncoder()
            {
                Subsample = subsample
            };
            await Assert.ThrowsAsync <TaskCanceledException>(() => image.SaveAsync(stream, encoder, cts.Token));
        }
        public void EncodeJpeg(int executionCount, int quality, JpegSubsample subsample)
        {
            // do not run this on CI even by accident
            if (TestEnvironment.RunsOnCI)
            {
                return;
            }

            string[] testFiles = TestImages.Bmp.Benchmark
                                 .Concat(new[] { TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk }).ToArray();

            Image <Rgba32>[] testImages = testFiles.Select(
                tf => TestImageProvider <Rgba32> .File(tf, pixelTypeOverride: PixelTypes.Rgba32).GetImage()).ToArray();

            using (var ms = new MemoryStream())
            {
                this.Measure(
                    executionCount,
                    () =>
                {
                    foreach (Image <Rgba32> img in testImages)
                    {
                        var options = new JpegEncoder {
                            Quality = quality, Subsample = subsample
                        };
                        img.Save(ms, options);
                        ms.Seek(0, SeekOrigin.Begin);
                    }
                },
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
                               // ReSharper disable once ExplicitCallerInfoArgument
                    $@"Encode {testFiles.Length} images");
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
            }

            foreach (Image <Rgba32> image in testImages)
            {
                image.Dispose();
            }
        }
Esempio n. 12
0
        public void CompressImageJpeg(string path, int quality, JpegSubsample jpegSubsample)
        {
            IImageFormat format;

            using (var image = SixLabors.ImageSharp.Image.Load(path, out format))
            {
                string      extension = ".jpg";
                JpegEncoder encoder   = new JpegEncoder()
                {
                    Quality = quality, Subsample = jpegSubsample
                };

                string outputPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path) + "_转换后" + extension);
                int    count      = 0;
                while (File.Exists(outputPath))
                {
                    count++;
                    outputPath = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(path) + "_转换后" + count.ToString() + extension);
                }
                image.Save(outputPath, encoder);
            }
        }
Esempio n. 13
0
        private static void TestJpegEncoderCore <TPixel>(
            TestImageProvider <TPixel> provider,
            JpegSubsample subsample,
            int quality = 100)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage())
            {
                // There is no alpha in Jpeg!
                image.Mutate(c => c.MakeOpaque());

                var encoder = new JpegEncoder()
                {
                    Subsample = subsample,
                    Quality   = quality
                };
                string        info     = $"{subsample}-Q{quality}";
                ImageComparer comparer = GetComparer(quality, subsample);

                // Does DebugSave & load reference CompareToReferenceInput():
                image.VerifyEncoder(provider, "jpeg", info, encoder, comparer, referenceImageExtension: "png");
            }
        }
Esempio n. 14
0
        public void DecodeGenerated_Orig <TPixel>(
            TestImageProvider <TPixel> provider,
            JpegSubsample subsample,
            int quality)
            where TPixel : struct, IPixel <TPixel>
        {
            byte[] data;
            using (Image <TPixel> image = provider.GetImage())
            {
                var encoder = new JpegEncoder {
                    Subsample = subsample, Quality = quality
                };

                data = new byte[65536];
                using (var ms = new MemoryStream(data))
                {
                    image.Save(ms, encoder);
                }
            }

            var mirror = Image.Load <TPixel>(data, OrigJpegDecoder);

            mirror.DebugSave(provider, $"_{subsample}_Q{quality}");
        }
Esempio n. 15
0
        // Benchmark, enable manually!
        // [Theory]
        // [InlineData(1, 75, JpegSubsample.Ratio420)]
        // [InlineData(30, 75, JpegSubsample.Ratio420)]
        // [InlineData(30, 75, JpegSubsample.Ratio444)]
        // [InlineData(30, 100, JpegSubsample.Ratio444)]
        public void EncodeJpeg(int executionCount, int quality, JpegSubsample subsample)
        {
            // do not run this on CI even by accident
            if (TestEnvironment.RunsOnCI)
            {
                return;
            }

            string[] testFiles = TestImages.Bmp.All
                                 .Concat(new[] { TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk })
                                 .ToArray();

            Image <Rgba32>[] testImages =
                testFiles.Select(
                    tf => TestImageProvider <Rgba32> .File(tf, pixelTypeOverride: PixelTypes.Rgba32).GetImage())
                .ToArray();

            using (MemoryStream ms = new MemoryStream())
            {
                this.Measure(executionCount,
                             () =>
                {
                    foreach (Image <Rgba32> img in testImages)
                    {
                        JpegEncoder options = new JpegEncoder {
                            Quality = quality, Subsample = subsample
                        };
                        img.Save(ms, options);
                        ms.Seek(0, SeekOrigin.Begin);
                    }
                },
                             // ReSharper disable once ExplicitCallerInfoArgument
                             $@"Encode {testFiles.Length} images"
                             );
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Encode writes the image to the jpeg baseline format with the given options.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="image">The image to write from.</param>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="quality">The quality.</param>
        /// <param name="sample">The subsampling mode.</param>
        public void Encode <TColor>(Image <TColor> image, Stream stream, int quality, JpegSubsample sample)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            this.outputStream = stream;
            this.subsample    = sample;

            if (quality < 1)
            {
                quality = 1;
            }

            if (quality > 100)
            {
                quality = 100;
            }

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - (quality * 2);
            }

            // Initialize the quantization tables.
            InitQuantizationTable(0, scale, ref this.luminanceQuantTable);
            InitQuantizationTable(1, scale, ref this.chrominanceQuantTable);

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            this.WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution);

            this.WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDefineQuantizationTables();

            // Write the image dimensions.
            this.WriteStartOfFrame(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDefineHuffmanTables(componentCount);

            // Write the image data.
            using (PixelAccessor <TColor> pixels = image.Lock())
            {
                this.WriteStartOfScan(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.EOI;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 17
0
        public void LoadResizeSave <TColor>(TestImageProvider <TColor> provider, int quality, JpegSubsample subsample)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            Image <TColor> image = provider.GetImage()
                                   .Resize(new ResizeOptions
            {
                Size = new Size(150, 100),
                Mode = ResizeMode.Max
            });

            image.Quality     = quality;
            image.ExifProfile = null; // Reduce the size of the file
            JpegEncoder encoder = new JpegEncoder {
                Subsample = subsample, Quality = quality
            };

            provider.Utility.TestName += $"{subsample}_Q{quality}";
            provider.Utility.SaveTestOutputFile(image, "png");
            provider.Utility.SaveTestOutputFile(image, "jpg", encoder);
        }
Esempio n. 18
0
 public void Encode(ImageBase image, Stream stream, int quality, JpegSubsample sample)
 {
     if (image == null || stream == null){
         throw new ArgumentNullException();
     }
     ushort max = JpegConstants.MaxLength;
     if (image.Width >= max || image.Height >= max){
         throw new Exception($"Image is too large to encode at {image.Width}x{image.Height}.");
     }
     outputStream = stream;
     subsample = sample;
     for (int i = 0; i < theHuffmanSpec.Length; i++){
         theHuffmanLut[i] = new HuffmanLut(theHuffmanSpec[i]);
     }
     for (int i = 0; i < nQuantIndex; i++){
         quant[i] = new byte[Block.blockSize];
     }
     if (quality < 1){
         quality = 1;
     }
     if (quality > 100){
         quality = 100;
     }
     int scale;
     if (quality < 50){
         scale = 5000/quality;
     } else{
         scale = 200 - quality*2;
     }
     for (int i = 0; i < nQuantIndex; i++){
         for (int j = 0; j < Block.blockSize; j++){
             int x = unscaledQuant[i, j];
             x = (x*scale + 50)/100;
             if (x < 1){
                 x = 1;
             }
             if (x > 255){
                 x = 255;
             }
             quant[i][j] = (byte) x;
         }
     }
     int componentCount = 3;
     double densityX = ((Image2) image).HorizontalResolution;
     double densityY = ((Image2) image).VerticalResolution;
     WriteApplicationHeader((short) densityX, (short) densityY);
     WriteDqt();
     WriteSof0(image.Width, image.Height, componentCount);
     WriteDht(componentCount);
     using (IPixelAccessor pixels = image.Lock()){
         WriteSos(pixels);
     }
     buffer[0] = 0xff;
     buffer[1] = 0xd9;
     stream.Write(buffer, 0, 2);
     stream.Flush();
 }
Esempio n. 19
0
        private void btnStart_Click(object sender, EventArgs e)
        {
            int           quality;
            JpegSubsample jpegSubsample = JpegSubsample.Ratio444;

            if (!int.TryParse(this.tbQuality.Text, out quality))
            {
                MessageBox.Show("压缩质量必须是介于0~100的数字");
                return;
            }
            if (quality < 0 || quality > 100)
            {
                MessageBox.Show("压缩质量必须是介于0~100的数字");
                return;
            }

            if (this.rbHigh.Checked)
            {
                jpegSubsample = JpegSubsample.Ratio444;
            }
            else
            {
                jpegSubsample = JpegSubsample.Ratio420;
            }
            if (this.lbFileNames.Items.Count == 0)
            {
                MessageBox.Show("请选择图片!");
                return;
            }
            string[] fileNames = new string[this.lbFileNames.Items.Count];
            for (int i = 0; i < this.lbFileNames.Items.Count; i++)
            {
                fileNames[i] = this.lbFileNames.Items[i].ToString();
            }

            ThreadPool.QueueUserWorkItem(x =>
            {
                ExecuteInMainThread(() =>
                {
                    this.btnBrowser.Enabled = false;
                    this.btnStart.Enabled   = false;
                });

                for (int i = 0; i < fileNames.Length; i++)
                {
                    ShowMessage("正在压缩保存" + Path.GetFileName(fileNames[i]) + "...", false);
                    try
                    {
                        CompressImageJpeg(fileNames[i], quality, jpegSubsample);
                    }
                    catch (Exception ee)
                    {
                        File.AppendAllText("error.txt", DateTime.Now.ToString() + ee.Message + ee.StackTrace + "\r\n");
                    }
                    int processValue = (i + 1) * 100 / fileNames.Length;
                    ExecuteInMainThread(() => this.processBar.Value = processValue);
                }
                ShowMessage("操作完成", false);
                ExecuteInMainThread(() =>
                {
                    this.btnBrowser.Enabled = true;
                    this.btnStart.Enabled   = true;
                });
            });
        }
Esempio n. 20
0
 public void EncodeBaseline_IsNotBoundToSinglePixelType <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample, int quality)
     where TPixel : struct, IPixel <TPixel>
 {
     TestJpegEncoderCore(provider, subsample, quality);
 }
Esempio n. 21
0
 public void EncodeBaseline_WorksWithDifferentSizes <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample, int quality)
     where TPixel : struct, IPixel <TPixel>
 {
     TestJpegEncoderCore(provider, subsample, quality);
 }
Esempio n. 22
0
        public void Benchmark_JpegEncoder <TColor>(TestImageProvider <TColor> provider, JpegSubsample subSample, int quality)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            var image = provider.GetImage();

            using (var outputStream = new MemoryStream())
            {
                var encoder = new JpegEncoder()
                {
                    Subsample = subSample,
                    Quality   = quality
                };

                for (int i = 0; i < BenchmarkExecTimes; i++)
                {
                    image.Save(outputStream, encoder);
                    outputStream.Seek(0, SeekOrigin.Begin);
                }
            }
        }
Esempio n. 23
0
        public void OpenBmp_SaveJpeg <TColor, TPacked>(TestImageFactory <TColor, TPacked> factory, JpegSubsample subSample, int quality)
            where TColor : struct, IPackedPixel <TPacked> where TPacked : struct, IEquatable <TPacked>
        {
            var image = factory.Create();

            var utility = factory.Utility;

            utility.TestName += "_" + subSample + "_Q" + quality;

            using (var outputStream = File.OpenWrite(utility.GetTestOutputFileName("jpg")))
            {
                var encoder = new JpegEncoder()
                {
                    Subsample = subSample,
                    Quality   = quality
                };

                image.Save(outputStream, encoder);
            }
        }
Esempio n. 24
0
        /// <summary>
        /// Encode writes the image to the jpeg baseline format with the given options.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="image">The image to write from.</param>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="quality">The quality.</param>
        /// <param name="sample">The subsampling mode.</param>
        public void Encode <TColor, TPacked>(Image <TColor, TPacked> image, Stream stream, int quality, JpegSubsample sample)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            this.outputStream = stream;
            this.subsample    = sample;

            for (int i = 0; i < QuantizationTableCount; i++)
            {
                this.quant[i] = new byte[Block.BlockSize];
            }

            if (quality < 1)
            {
                quality = 1;
            }

            if (quality > 100)
            {
                quality = 100;
            }

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - (quality * 2);
            }

            // Initialize the quantization tables.
            for (int i = 0; i < QuantizationTableCount; i++)
            {
                for (int j = 0; j < Block.BlockSize; j++)
                {
                    int x = this.unscaledQuant[i, j];
                    x = ((x * scale) + 50) / 100;
                    if (x < 1)
                    {
                        x = 1;
                    }

                    if (x > 255)
                    {
                        x = 255;
                    }

                    this.quant[i][j] = (byte)x;
                }
            }

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            this.WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution);

            this.WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDefineQuantizationTables();

            // Write the image dimensions.
            this.WriteStartOfFrame(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDefineHuffmanTables(componentCount);

            // Write the image data.
            using (PixelAccessor <TColor, TPacked> pixels = image.Lock())
            {
                this.WriteStartOfScan(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.EOI;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 25
0
        public void LoadResizeSave <TPixel>(TestImageProvider <TPixel> provider, int quality, JpegSubsample subsample)
            where TPixel : struct, IPixel <TPixel>
        {
            using (Image <TPixel> image = provider.GetImage(x => x.Resize(new ResizeOptions {
                Size = new Size(150, 100), Mode = ResizeMode.Max
            })))
            {
                image.MetaData.ExifProfile = null; // Reduce the size of the file
                JpegEncoder options = new JpegEncoder {
                    Subsample = subsample, Quality = quality
                };

                provider.Utility.TestName += $"{subsample}_Q{quality}";
                provider.Utility.SaveTestOutputFile(image, "png");
                provider.Utility.SaveTestOutputFile(image, "jpg", options);
            }
        }
Esempio n. 26
0
        // Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given
        // options. Default parameters are used if a nil *Options is passed.
        public void Encode <T, TP>(Image <T, TP> image, Stream stream, int quality, JpegSubsample sample)
            where T : IPackedVector <TP>
            where TP : struct
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            this.outputStream = stream;
            this.subsample    = sample;

            // TODO: This should be static should it not?
            for (int i = 0; i < this.theHuffmanSpec.Length; i++)
            {
                this.theHuffmanLUT[i] = new HuffmanLut(this.theHuffmanSpec[i]);
            }

            for (int i = 0; i < NQuantIndex; i++)
            {
                this.quant[i] = new byte[Block.BlockSize];
            }

            if (quality < 1)
            {
                quality = 1;
            }
            if (quality > 100)
            {
                quality = 100;
            }

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - quality * 2;
            }

            // Initialize the quantization tables.
            for (int i = 0; i < NQuantIndex; i++)
            {
                for (int j = 0; j < Block.BlockSize; j++)
                {
                    int x = this.unscaledQuant[i, j];
                    x = (x * scale + 50) / 100;
                    if (x < 1)
                    {
                        x = 1;
                    }
                    if (x > 255)
                    {
                        x = 255;
                    }
                    this.quant[i][j] = (byte)x;
                }
            }

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution);

            WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDQT();

            // Write the image dimensions.
            this.WriteSOF0(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDHT(componentCount);

            // Write the image data.
            using (IPixelAccessor <T, TP> pixels = image.Lock())
            {
                this.WriteSOS(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = 0xff;
            this.buffer[1] = 0xd9;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 27
0
        /// <summary>
        /// Encode writes the image to the jpeg baseline format with the given options.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="image">The image to write from.</param>
        /// <param name="stream">The stream to write to.</param>
        public void Encode <TPixel>(Image <TPixel> image, Stream stream)
            where TPixel : struct, IPixel <TPixel>
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            ushort max = JpegConstants.MaxLength;

            if (image.Width >= max || image.Height >= max)
            {
                throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
            }

            // Ensure that quality can be set but has a fallback.
            int quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;

            if (quality == 0)
            {
                quality = 75;
            }

            quality = quality.Clamp(1, 100);

            this.outputStream = stream;
            this.subsample    = this.options.Subsample ?? (quality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420);

            // Convert from a quality rating to a scaling factor.
            int scale;

            if (quality < 50)
            {
                scale = 5000 / quality;
            }
            else
            {
                scale = 200 - (quality * 2);
            }

            // Initialize the quantization tables.
            InitQuantizationTable(0, scale, ref this.luminanceQuantTable);
            InitQuantizationTable(1, scale, ref this.chrominanceQuantTable);

            // Compute number of components based on input image type.
            int componentCount = 3;

            // Write the Start Of Image marker.
            this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);

            this.WriteProfiles(image);

            // Write the quantization tables.
            this.WriteDefineQuantizationTables();

            // Write the image dimensions.
            this.WriteStartOfFrame(image.Width, image.Height, componentCount);

            // Write the Huffman tables.
            this.WriteDefineHuffmanTables(componentCount);

            // Write the image data.
            using (PixelAccessor <TPixel> pixels = image.Lock())
            {
                this.WriteStartOfScan(pixels);
            }

            // Write the End Of Image marker.
            this.buffer[0] = JpegConstants.Markers.XFF;
            this.buffer[1] = JpegConstants.Markers.EOI;
            stream.Write(this.buffer, 0, 2);
            stream.Flush();
        }
Esempio n. 28
0
        public void EncodeBaseline_WorksWithDiscontiguousBuffers <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            ImageComparer comparer = subsample == JpegSubsample.Ratio444
                ? ImageComparer.TolerantPercentage(0.1f)
                : ImageComparer.TolerantPercentage(5f);

            provider.LimitAllocatorBufferCapacity().InBytesSqrt(200);
            TestJpegEncoderCore(provider, subsample, 100, JpegColorType.YCbCr, comparer);
        }