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); }
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" ); } }
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(); }
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); } }
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"); } }
/// <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)); }
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); } }
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(); } }
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); } }
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"); } }
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}"); }
// 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" ); } }
/// <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(); }
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); }
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; }); }); }
public void EncodeBaseline_IsNotBoundToSinglePixelType <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample, int quality) where TPixel : struct, IPixel <TPixel> { TestJpegEncoderCore(provider, subsample, quality); }
public void EncodeBaseline_WorksWithDifferentSizes <TPixel>(TestImageProvider <TPixel> provider, JpegSubsample subsample, int quality) where TPixel : struct, IPixel <TPixel> { TestJpegEncoderCore(provider, subsample, quality); }
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); } } }
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); } }
/// <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(); }
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); } }
// 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(); }
/// <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(); }
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); }