C# (CSharp) BitMiracle.LibJpeg.Classic.Internal Namespace

Сlasses

Name Description
ArithEntropyDecoder
ComponentBuffer Encapsulates buffer of image samples for one color component When provided with funny indices (see jpeg_d_main_controller for explanation of what it is) uses them for non-linear row access.
JpegUtils
arith_entropy_decoder
arith_entropy_encoder
bitread_perm_state Bitreading state saved across MCUs
bitread_working_state Bitreading working state within an MCU
d_derived_tbl Derived data constructed for each Huffman table
huff_entropy_decoder Expanded entropy decoder object for Huffman decoding. The savable_state subrecord contains fields that change within an MCU, but must not be updated permanently until we complete the MCU.
huff_entropy_decoder.savable_state
huff_entropy_encoder Expanded entropy encoder object for Huffman encoding.
huff_entropy_encoder.c_derived_tbl
huff_entropy_encoder.savable_state
jpeg_c_main_controller Main buffer control (downsampled-data buffer)
jpeg_c_prep_controller Compression preprocessing (downsampling input buffer control). For the simple (no-context-row) case, we just need to buffer one row group's worth of pixels for the downsampling step. At the bottom of the image, we pad to a full row group by replicating the last pixel row. The downsampler's last output row is then replicated if needed to pad out to a full iMCU row. When providing context rows, we must buffer three row groups' worth of pixels. Three row groups are physically allocated, but the row pointer arrays are made five row groups high, with the extra pointers above and below "wrapping around" to point to the last and first real row groups. This allows the downsampler to access the proper context rows. At the top and bottom of the image, we create dummy context rows by copying the first or last real pixel row. This copying could be avoided by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the trouble on the compression side.
jpeg_color_converter Colorspace conversion
jpeg_color_deconverter Colorspace conversion
jpeg_comp_master Master control module
jpeg_d_coef_controller Coefficient buffer control This code applies interblock smoothing as described by section K.8 of the JPEG standard: the first 5 AC coefficients are estimated from the DC values of a DCT block and its 8 neighboring blocks. We apply smoothing only for progressive JPEG decoding, and only if the coefficients it can estimate are not yet known to full precision.
jpeg_d_main_controller Main buffer control (downsampled-data buffer) In the current system design, the main buffer need never be a full-image buffer; any full-height buffers will be found inside the coefficient or postprocessing controllers. Nonetheless, the main controller is not trivial. Its responsibility is to provide context rows for upsampling/ rescaling, and doing this in an efficient fashion is a bit tricky. Postprocessor input data is counted in "row groups". A row group is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) sample rows of each component. (We require DCT_scaled_size values to be chosen such that these numbers are integers. In practice DCT_scaled_size values will likely be powers of two, so we actually have the stronger condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) Upsampling will typically produce max_v_samp_factor pixel rows from each row group (times any additional scale factor that the upsampler is applying). The coefficient controller will deliver data to us one iMCU row at a time; each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or exactly min_DCT_scaled_size row groups. (This amount of data corresponds to one row of MCUs when the image is fully interleaved.) Note that the number of sample rows varies across components, but the number of row groups does not. Some garbage sample rows may be included in the last iMCU row at the bottom of the image. Depending on the vertical scaling algorithm used, the upsampler may need access to the sample row(s) above and below its current input row group. The upsampler is required to set need_context_rows true at global selection time if so. When need_context_rows is false, this controller can simply obtain one iMCU row at a time from the coefficient controller and dole it out as row groups to the postprocessor. When need_context_rows is true, this controller guarantees that the buffer passed to postprocessing contains at least one row group's worth of samples above and below the row group(s) being processed. Note that the context rows "above" the first passed row group appear at negative row offsets in the passed buffer. At the top and bottom of the image, the required context rows are manufactured by duplicating the first or last real sample row; this avoids having special cases in the upsampling inner loops. The amount of context is fixed at one row group just because that's a convenient number for this controller to work with. The existing upsamplers really only need one sample row of context. An upsampler supporting arbitrary output rescaling might wish for more than one row group of context when shrinking the image; tough, we don't handle that. (This is justified by the assumption that downsizing will be handled mostly by adjusting the DCT_scaled_size values, so that the actual scale factor at the upsample step needn't be much less than one.) To provide the desired context, we have to retain the last two row groups of one iMCU row while reading in the next iMCU row. (The last row group can't be processed until we have another row group for its below-context, and so we have to save the next-to-last group too for its above-context.) We could do this most simply by copying data around in our buffer, but that'd be very slow. We can avoid copying any data by creating a rather strange pointer structure. Here's how it works. We allocate a workspace consisting of M+2 row groups (where M = min_DCT_scaled_size is the number of row groups per iMCU row). We create two sets of redundant pointers to the workspace. Labeling the physical row groups 0 to M+1, the synthesized pointer lists look like this: M+1 M-1 master pointer --> 0 master pointer --> 0 1 1 ... ... M-3 M-3 M-2 M M-1 M+1 M M-2 M+1 M-1 0 0 We read alternate iMCU rows using each master pointer; thus the last two row groups of the previous iMCU row remain un-overwritten in the workspace. The pointer lists are set up so that the required context rows appear to be adjacent to the proper places when we pass the pointer lists to the upsampler. The above pictures describe the normal state of the pointer lists. At top and bottom of the image, we diddle the pointer lists to duplicate the first or last sample row as necessary (this is cheaper than copying sample rows around). This scheme breaks down if M less than 2, ie, min_DCT_scaled_size is 1. In that situation each iMCU row provides only one row group so the buffering logic must be different (eg, we must read two iMCU rows before we can emit the first row group). For now, we simply do not support providing context rows when min_DCT_scaled_size is 1. That combination seems unlikely to be worth providing --- if someone wants a 1/8th-size preview, they probably want it quick and dirty, so a context-free upsampler is sufficient.
jpeg_d_post_controller Decompression postprocessing (color quantization buffer control)
jpeg_decomp_master Master control module
jpeg_downsampler Downsampling
jpeg_entropy_decoder Entropy decoding
jpeg_entropy_encoder Entropy encoding
jpeg_forward_dct Forward DCT (also controls coefficient quantization) A forward DCT routine is given a pointer to an input sample array and a pointer to a work area of type DCTELEM[]; the DCT is to be performed in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT implementations use an array of type FAST_FLOAT, instead.) The input data is to be fetched from the sample array starting at a specified column. (Any row offset needed will be applied to the array pointer before it is passed to the FDCT code.) Note that the number of samples fetched by the FDCT routine is DCT_h_scaled_size * DCT_v_scaled_size. The DCT outputs are returned scaled up by a factor of 8; they therefore have a range of +-8K for 8-bit data, +-128K for 12-bit data. This convention improves accuracy in integer implementations and saves some work in floating-point ones. Each IDCT routine has its own ideas about the best dct_table element type.
jpeg_forward_dct.divisor_table
jpeg_input_controller Input control module
jpeg_inverse_dct An inverse DCT routine is given a pointer to the input JBLOCK and a pointer to an output sample array. The routine must dequantize the input data as well as perform the IDCT; for dequantization, it uses the multiplier table pointed to by componentInfo.dct_table. The output data is to be placed into the sample array starting at a specified column. (Any row offset needed will be applied to the array pointer before it is passed to the IDCT code) Note that the number of samples emitted by the IDCT routine is DCT_scaled_size * DCT_scaled_size. Each IDCT routine has its own ideas about the best dct_table element type. The decompressor input side saves away the appropriate quantization table for each component at the start of the first scan involving that component. (This is necessary in order to correctly decode files that reuse Q-table slots.) When we are ready to make an output pass, the saved Q-table is converted to a multiplier table that will actually be used by the IDCT routine. The multiplier table contents are IDCT-method-dependent. To support application changes in IDCT method between scans, we can remake the multiplier tables if necessary. In buffered-image mode, the first output pass may occur before any data has been seen for some components, and thus before their Q-tables have been saved away. To handle this case, multiplier tables are preset to zeroes; the result of the IDCT will be a neutral gray level.
jpeg_inverse_dct.multiplier_table
jpeg_marker_reader Marker reading and parsing
jpeg_marker_writer Marker writing
jpeg_scan_info The script for encoding a multiple-scan file is an array of these:
jpeg_upsampler Upsampling (note that upsampler must also call color converter)
my_1pass_cquantizer The main purpose of 1-pass quantization is to provide a fast, if not very high quality, colormapped output capability. A 2-pass quantizer usually gives better visual quality; however, for quantized grayscale output this quantizer is perfectly adequate. Dithering is highly recommended with this quantizer, though you can turn it off if you really want to. In 1-pass quantization the colormap must be chosen in advance of seeing the image. We use a map consisting of all combinations of Ncolors[i] color values for the i'th component. The Ncolors[] values are chosen so that their product, the total number of colors, is no more than that requested. (In most cases, the product will be somewhat less.) Since the colormap is orthogonal, the representative value for each color component can be determined without considering the other components; then these indexes can be combined into a colormap index by a standard N-dimensional-array-subscript calculation. Most of the arithmetic involved can be precalculated and stored in the lookup table colorindex[]. colorindex[i][j] maps pixel value j in component i to the nearest representative value (grid plane) for that component; this index is multiplied by the array stride for component i, so that the index of the colormap entry closest to a given pixel value is just sum( colorindex[component-number][pixel-component-value] ) Aside from being fast, this scheme allows for variable spacing between representative values with no additional lookup cost. If gamma correction has been applied in color conversion, it might be wise to adjust the color grid spacing so that the representative colors are equidistant in linear space. At this writing, gamma correction is not implemented, so nothing is done here. Declarations for Floyd-Steinberg dithering. Errors are accumulated into the array fserrors[], at a resolution of 1/16th of a pixel count. The error at a given pixel is propagated to its not-yet-processed neighbors using the standard F-S fractions, ... (here) 7/16 3/16 5/16 1/16 We work left-to-right on even rows, right-to-left on odd rows. We can get away with a single array (holding one row's worth of errors) by using it to store the current row's errors at pixel columns not yet processed, but the next row's errors at columns already processed. We need only a few extra variables to hold the errors immediately around the current column. (If we are lucky, those variables are in registers, but even if not, they're probably cheaper to access than array elements are.) The fserrors[] array is indexed [component#][position]. We provide (#columns + 2) entries per component; the extra entry at each end saves us from special-casing the first and last pixels. Declarations for ordered dithering. We use a standard 16x16 ordered dither array. The basic concept of ordered dithering is described in many references, for instance Dale Schumacher's chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). In place of Schumacher's comparisons against a "threshold" value, we add a "dither" value to the input pixel and then round the result to the nearest output value. The dither value is equivalent to (0.5 - threshold) times the distance between output values. For ordered dithering, we assume that the output colors are equally spaced; if not, results will probably be worse, since the dither may be too much or too little at a given point. The normal calculation would be to form pixel value + dither, range-limit this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. We can skip the separate range-limiting step by extending the colorindex table in both directions.
my_2pass_cquantizer This module implements the well-known Heckbert paradigm for color quantization. Most of the ideas used here can be traced back to Heckbert's seminal paper Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. In the first pass over the image, we accumulate a histogram showing the usage count of each possible color. To keep the histogram to a reasonable size, we reduce the precision of the input; typical practice is to retain 5 or 6 bits per color, so that 8 or 4 different input values are counted in the same histogram cell. Next, the color-selection step begins with a box representing the whole color space, and repeatedly splits the "largest" remaining box until we have as many boxes as desired colors. Then the mean color in each remaining box becomes one of the possible output colors. The second pass over the image maps each input pixel to the closest output color (optionally after applying a Floyd-Steinberg dithering correction). This mapping is logically trivial, but making it go fast enough requires considerable care. Heckbert-style quantizers vary a good deal in their policies for choosing the "largest" box and deciding where to cut it. The particular policies used here have proved out well in experimental comparisons, but better ones may yet be found. In earlier versions of the IJG code, this module quantized in YCbCr color space, processing the raw upsampled data without a color conversion step. This allowed the color conversion math to be done only once per colormap entry, not once per pixel. However, that optimization precluded other useful optimizations (such as merging color conversion with upsampling) and it also interfered with desired capabilities such as quantizing to an externally-supplied colormap. We have therefore abandoned that approach. The present code works in the post-conversion color space, typically RGB. To improve the visual quality of the results, we actually work in scaled RGB space, giving G distances more weight than R, and R in turn more than B. To do everything in integer math, we must use integer scale factors. The 2/3/1 scale factors used here correspond loosely to the relative weights of the colors in the NTSC grayscale equation. If you want to use this code to quantize a non-RGB color space, you'll probably need to change these scale factors. First we have the histogram data structure and routines for creating it. The number of bits of precision can be adjusted by changing these symbols. We recommend keeping 6 bits for G and 5 each for R and B. If you have plenty of memory and cycles, 6 bits all around gives marginally better results; if you are short of memory, 5 bits all around will save some space but degrade the results. To maintain a fully accurate histogram, we'd need to allocate a "long" (preferably unsigned long) for each cell. In practice this is overkill; we can get by with 16 bits per cell. Few of the cell counts will overflow, and clamping those that do overflow to the maximum value will give close- enough results. This reduces the recommended histogram size from 256Kb to 128Kb, which is a useful savings on PC-class machines. (In the second pass the histogram space is re-used for pixel mapping data; in that capacity, each cell must be able to store zero to the number of desired colors. 16 bits/cell is plenty for that too.) Since the JPEG code is intended to run in small memory model on 80x86 machines, we can't just allocate the histogram in one chunk. Instead of a true 3-D array, we use a row of pointers to 2-D arrays. Each pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that on 80x86 machines, the pointer row is in near memory but the actual arrays are in far memory (same arrangement as we use for image arrays). Declarations for Floyd-Steinberg dithering. Errors are accumulated into the array fserrors[], at a resolution of 1/16th of a pixel count. The error at a given pixel is propagated to its not-yet-processed neighbors using the standard F-S fractions, ... (here) 7/16 3/16 5/16 1/16 We work left-to-right on even rows, right-to-left on odd rows. We can get away with a single array (holding one row's worth of errors) by using it to store the current row's errors at pixel columns not yet processed, but the next row's errors at columns already processed. We need only a few extra variables to hold the errors immediately around the current column. (If we are lucky, those variables are in registers, but even if not, they're probably cheaper to access than array elements are.) The fserrors[] array has (#columns + 2) entries; the extra entry at each end saves us from special-casing the first and last pixels. Each entry is three values long, one value for each color component.
my_2pass_cquantizer.box
my_c_coef_controller
my_destination_mgr Expanded data destination object for output to Stream
my_merged_upsampler
my_source_mgr Expanded data source object for stdio input
my_trans_c_coef_controller This is a special implementation of the coefficient buffer controller. This is similar to jccoefct.c, but it handles only output from presupplied virtual arrays. Furthermore, we generate any dummy padding blocks on-the-fly rather than expecting them to be present in the arrays.
my_upsampler