+ /// Allocate and fill in the sample_range_limit table.
+ ///
+ /// Several decompression processes need to range-limit values to the range
+ /// 0..MAXJSAMPLE; the input value may fall somewhat outside this range
+ /// due to noise introduced by quantization, roundoff error, etc. These
+ /// processes are inner loops and need to be as fast as possible. On most
+ /// machines, particularly CPUs with pipelines or instruction prefetch,
+ /// a (subscript-check-less) C table lookup
+ /// x = sample_range_limit[x];
+ /// is faster than explicit tests
+ ///
+ /// if (x & 0)
+ /// x = 0;
+ /// else if (x > MAXJSAMPLE)
+ /// x = MAXJSAMPLE;
+ ///
+ /// These processes all use a common table prepared by the routine below.
+ ///
+ /// For most steps we can mathematically guarantee that the initial value
+ /// of x is within MAXJSAMPLE + 1 of the legal range, so a table running from
+ /// -(MAXJSAMPLE + 1) to 2 * MAXJSAMPLE + 1 is sufficient. But for the initial
+ /// limiting step (just after the IDCT), a wildly out-of-range value is
+ /// possible if the input data is corrupt. To avoid any chance of indexing
+ /// off the end of memory and getting a bad-pointer trap, we perform the
+ /// post-IDCT limiting thus: x = range_limit[x & MASK];
+ /// where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
+ /// samples. Under normal circumstances this is more than enough range and
+ /// a correct output will be generated; with bogus input data the mask will
+ /// cause wraparound, and we will safely generate a bogus-but-in-range output.
+ /// For the post-IDCT step, we want to convert the data from signed to unsigned
+ /// representation by adding CENTERJSAMPLE at the same time that we limit it.
+ /// So the post-IDCT limiting table ends up looking like this:
+ ///
+ /// CENTERJSAMPLE, CENTERJSAMPLE + 1, ..., MAXJSAMPLE,
+ /// MAXJSAMPLE (repeat 2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE times),
+ /// 0 (repeat 2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE times),
+ /// 0, 1, ..., CENTERJSAMPLE - 1
+ ///
+ /// Negative inputs select values from the upper half of the table after
+ /// masking.
+ ///
+ /// We can save some space by overlapping the start of the post-IDCT table
+ /// with the simpler range limiting table. The post-IDCT table begins at
+ /// sample_range_limit + CENTERJSAMPLE.
+ ///
+ /// Note that the table is allocated in near data space on PCs; it's small
+ /// enough and used often enough to justify this.
+ ///
+ private void prepare_range_limit_table()
+ {
+ byte[] table = new byte[5 * (JpegConstants.MAXJSAMPLE + 1) + JpegConstants.CENTERJSAMPLE];
+
+ /* allow negative subscripts of simple table */
+ int tableOffset = JpegConstants.MAXJSAMPLE + 1;
+ m_cinfo.m_sample_range_limit = table;
+ m_cinfo.m_sampleRangeLimitOffset = tableOffset;
+
+ /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+ Array.Clear(table, 0, JpegConstants.MAXJSAMPLE + 1);
+
+ /* Main part of "simple" table: limit[x] = x */
+ for (int i = 0; i <= JpegConstants.MAXJSAMPLE; i++)
+ table[tableOffset + i] = (byte) i;
+
+ tableOffset += JpegConstants.CENTERJSAMPLE; /* Point to where post-IDCT table starts */
+
+ /* End of simple table, rest of first half of post-IDCT table */
+ for (int i = JpegConstants.CENTERJSAMPLE; i < 2 * (JpegConstants.MAXJSAMPLE + 1); i++)
+ table[tableOffset + i] = JpegConstants.MAXJSAMPLE;
+
+ /* Second half of post-IDCT table */
+ Array.Clear(table, tableOffset + 2 * (JpegConstants.MAXJSAMPLE + 1),
+ 2 * (JpegConstants.MAXJSAMPLE + 1) - JpegConstants.CENTERJSAMPLE);
+
+ Buffer.BlockCopy(m_cinfo.m_sample_range_limit, 0, table,
+ tableOffset + 4 * (JpegConstants.MAXJSAMPLE + 1) - JpegConstants.CENTERJSAMPLE, JpegConstants.CENTERJSAMPLE);
+ }
+ }
+}
diff --git a/src/ImageProcessor/Formats/Jpg/LibJpeg/Classic/Internal/jpeg_downsampler.cs b/src/ImageProcessor/Formats/Jpg/LibJpeg/Classic/Internal/jpeg_downsampler.cs
new file mode 100644
index 000000000..192f88100
--- /dev/null
+++ b/src/ImageProcessor/Formats/Jpg/LibJpeg/Classic/Internal/jpeg_downsampler.cs
@@ -0,0 +1,546 @@
+/* Copyright (C) 2008-2011, Bit Miracle
+ * http://www.bitmiracle.com
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ */
+
+/*
+ * This file contains downsampling routines.
+ *
+ * Downsampling input data is counted in "row groups". A row group
+ * is defined to be max_v_samp_factor pixel rows of each component,
+ * from which the downsampler produces v_samp_factor sample rows.
+ * A single row group is processed in each call to the downsampler module.
+ *
+ * The downsampler is responsible for edge-expansion of its output data
+ * to fill an integral number of DCT blocks horizontally. The source buffer
+ * may be modified if it is helpful for this purpose (the source buffer is
+ * allocated wide enough to correspond to the desired output width).
+ * The caller (the prep controller) is responsible for vertical padding.
+ *
+ * The downsampler may request "context rows" by setting need_context_rows
+ * during startup. In this case, the input arrays will contain at least
+ * one row group's worth of pixels above and below the passed-in data;
+ * the caller will create dummy rows at image top and bottom by replicating
+ * the first or last real pixel row.
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ *
+ * The downsampling algorithm used here is a simple average of the source
+ * pixels covered by the output pixel. The hi-falutin sampling literature
+ * refers to this as a "box filter". In general the characteristics of a box
+ * filter are not very good, but for the specific cases we normally use (1:1
+ * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
+ * nearly so bad. If you intend to use other sampling ratios, you'd be well
+ * advised to improve this code.
+ *
+ * A simple input-smoothing capability is provided. This is mainly intended
+ * for cleaning up color-dithered GIF input files (if you find it inadequate,
+ * we suggest using an external filtering program such as pnmconvol). When
+ * enabled, each input pixel P is replaced by a weighted sum of itself and its
+ * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
+ * where SF = (smoothing_factor / 1024).
+ * Currently, smoothing is only supported for 2h2v sampling factors.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BitMiracle.LibJpeg.Classic.Internal
+{
+ ///