private int m_next_row;        /* index of next row to fill/empty in strip */

        /// <summary>
        /// Initialize postprocessing controller.
        /// </summary>
        public jpeg_d_post_controller(jpeg_decompress_struct cinfo, bool need_full_buffer)
        {
            m_cinfo = cinfo;

            /* Create the quantization buffer, if needed */
            if (cinfo.m_quantize_colors)
            {
                /* The buffer strip height is max_v_samp_factor, which is typically
                * an efficient number of rows for upsampling to return.
                * (In the presence of output rescaling, we might want to be smarter?)
                */
                m_strip_height = cinfo.m_max_v_samp_factor;

                if (need_full_buffer)
                {
                    /* Two-pass color quantization: need full-image storage. */
                    /* We round up the number of rows to a multiple of the strip height. */
                    m_whole_image = jpeg_common_struct.CreateSamplesArray(
                        cinfo.m_output_width * cinfo.m_out_color_components,
                        JpegUtils.jround_up(cinfo.m_output_height, m_strip_height));
                    m_whole_image.ErrorProcessor = cinfo;
                }
                else
                {
                    /* One-pass color quantization: just make a strip buffer. */
                    m_buffer = jpeg_common_struct.AllocJpegSamples(
                        cinfo.m_output_width * cinfo.m_out_color_components, m_strip_height);
                }
            }
        }
예제 #2
0
        public jpeg_d_coef_controller(jpeg_decompress_struct cinfo, bool need_full_buffer)
        {
            m_cinfo = cinfo;

            /* Create the coefficient buffer. */
            if (need_full_buffer)
            {
                /* Allocate a full-image virtual array for each component, */
                /* padded to a multiple of samp_factor DCT blocks in each direction. */
                /* Note we ask for a pre-zeroed array. */
                for (int ci = 0; ci < cinfo.m_num_components; ci++)
                {
                    m_whole_image[ci] = jpeg_common_struct.CreateBlocksArray(
                        JpegUtils.jround_up(cinfo.Comp_info[ci].Width_in_blocks, cinfo.Comp_info[ci].H_samp_factor),
                        JpegUtils.jround_up(cinfo.Comp_info[ci].height_in_blocks, cinfo.Comp_info[ci].V_samp_factor));
                    m_whole_image[ci].ErrorProcessor = cinfo;
                }

                m_useDummyConsumeData = false;
                m_decompressor        = DecompressorType.Ordinary;
                m_coef_arrays         = m_whole_image; /* link to virtual arrays */
            }
            else
            {
                /* We only need a single-MCU buffer. */
                for (int i = 0; i < JpegConstants.D_MAX_BLOCKS_IN_MCU; i++)
                {
                    m_MCU_buffer[i] = new JBLOCK();
                }

                m_useDummyConsumeData = true;
                m_decompressor        = DecompressorType.OnePass;
                m_coef_arrays         = null; /* flag for no virtual arrays */
            }
        }
예제 #3
0
        // the algorithm flow is based on:
        // https://bitmiracle.github.io/libjpeg.net/help/articles/KB/decompression-details.html
        private DecompressionResult DecompressJpgToRaw(byte[] image)
        {
            var cinfo = new jpeg_decompress_struct(new jpeg_error_mgr());

            using (var memoryStream = new MemoryStream(image))
            {
                cinfo.jpeg_stdio_src(memoryStream);
                cinfo.jpeg_read_header(true);

                cinfo.Out_color_space = J_COLOR_SPACE.JCS_RGB;

                cinfo.jpeg_start_decompress();

                // there are 3 components: R, G, B
                var rowStride    = 3 * cinfo.Output_width;
                var result       = new byte[rowStride * cinfo.Output_height];
                var resultOffset = 0;

                var buffer = new byte[1][];
                buffer[0] = new byte[rowStride];

                while (cinfo.Output_scanline < cinfo.Output_height)
                {
                    var ct = cinfo.jpeg_read_scanlines(buffer, 1);
                    if (ct > 0)
                    {
                        Array.Copy(buffer[0], 0, result, resultOffset, buffer[0].Length);
                        resultOffset += buffer[0].Length;
                    }
                }

                cinfo.jpeg_finish_decompress();
                return(new DecompressionResult(result, cinfo.Output_width, cinfo.Output_height));
            }
        }
예제 #4
0
        private int m_rows_to_go;    /* counts rows remaining in image */

        public my_merged_upsampler(jpeg_decompress_struct cinfo)
        {
            m_cinfo             = cinfo;
            m_need_context_rows = false;

            m_out_row_width = cinfo.m_output_width * cinfo.m_out_color_components;

            if (cinfo.m_max_v_samp_factor == 2)
            {
                m_use_2v_upsample = true;
                /* Allocate a spare row buffer */
                m_spare_row = new byte[m_out_row_width];
            }
            else
            {
                m_use_2v_upsample = false;
            }

            if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_BG_YCC)
            {
                build_bg_ycc_rgb_table();
            }
            else
            {
                build_ycc_rgb_table();
            }
        }
예제 #5
0
        // Fill an input buffer from a stream.
        private static Int fill_input_buffer(ref jpeg_decompress_struct cinfo)
        {
            int         len;
            StreamState state = GetStreamState(ref cinfo);

            if (!(state.sawEOF))
            {
                len = state.stream.Read
                          (state.buffer, 0, state.buffer.Length);
                if (len > 0)
                {
                    Marshal.Copy(state.buffer, 0, state.buf, len);
                    cinfo.src->next_input_byte = state.buf;
                    cinfo.src->bytes_in_buffer = (size_t)len;
                    return((Int)1);
                }
                state.sawEOF = true;
            }

            // Insert an EOI marker to indicate end of stream to "libjpeg".
            Marshal.WriteByte(state.buf, 0, (byte)0xFF);
            Marshal.WriteByte(state.buf, 1, (byte)0xD9);
            cinfo.src->next_input_byte = state.buf;
            cinfo.src->bytes_in_buffer = (size_t)2;
            return((Int)1);
        }
        private int m_iMCU_row_ctr;    /* counts iMCU rows to detect image top/bot */

        public jpeg_d_main_controller(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Allocate the workspace.
             * ngroups is the number of row groups we need.
             */
            int ngroups = cinfo.m_min_DCT_scaled_size;

            if (cinfo.m_upsample.NeedContextRows())
            {
                if (cinfo.m_min_DCT_scaled_size < 2) /* unsupported, see comments above */
                {
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL);
                }

                alloc_funny_pointers(); /* Alloc space for xbuffer[] lists */
                ngroups = cinfo.m_min_DCT_scaled_size + 2;
            }

            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                /* height of a row group of component */
                int rgroup = (cinfo.Comp_info[ci].V_samp_factor * cinfo.Comp_info[ci].DCT_scaled_size) / cinfo.m_min_DCT_scaled_size;

                m_buffer[ci] = jpeg_common_struct.AllocJpegSamples(
                    cinfo.Comp_info[ci].Width_in_blocks * cinfo.Comp_info[ci].DCT_scaled_size,
                    rgroup * ngroups);
            }
        }
예제 #7
0
        private d_derived_tbl m_ac_derived_tbl; /* active table during an AC scan */

        public phuff_entropy_decoder(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Mark derived tables unallocated */
            for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
            {
                m_derived_tbls[i] = null;
            }

            /* Create progression status table */
            cinfo.m_coef_bits = new int[cinfo.m_num_components][];
            for (int i = 0; i < cinfo.m_num_components; i++)
            {
                cinfo.m_coef_bits[i] = new int[JpegConstants.DCTSIZE2];
            }

            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    cinfo.m_coef_bits[ci][i] = -1;
                }
            }
        }
        public jpeg_d_coef_controller(jpeg_decompress_struct cinfo, bool need_full_buffer)
        {
            m_cinfo = cinfo;

            /* Create the coefficient buffer. */
            if (need_full_buffer)
            {
                /* Allocate a full-image virtual array for each component, */
                /* padded to a multiple of samp_factor DCT blocks in each direction. */
                /* Note we ask for a pre-zeroed array. */
                for (int ci = 0; ci < cinfo.m_num_components; ci++)
                {
                    m_whole_image[ci] = jpeg_common_struct.CreateBlocksArray(
                        JpegUtils.jround_up(cinfo.Comp_info[ci].Width_in_blocks, cinfo.Comp_info[ci].H_samp_factor),
                        JpegUtils.jround_up(cinfo.Comp_info[ci].height_in_blocks, cinfo.Comp_info[ci].V_samp_factor));
                    m_whole_image[ci].ErrorProcessor = cinfo;
                }

                m_useDummyConsumeData = false;
                m_decompressor = DecompressorType.Ordinary;
                m_coef_arrays = m_whole_image; /* link to virtual arrays */
            }
            else
            {
                /* We only need a single-MCU buffer. */
                for (int i = 0; i < JpegConstants.D_MAX_BLOCKS_IN_MCU; i++)
                    m_MCU_buffer[i] = new JBLOCK();

                m_useDummyConsumeData = true;
                m_decompressor = DecompressorType.OnePass;
                m_coef_arrays = null; /* flag for no virtual arrays */
            }
        }
예제 #9
0
        private bool m_on_odd_row;                               /* flag to remember which row we are on */

        /// <summary>
        /// Module initialization routine for 1-pass color quantization.
        /// </summary>
        /// <param name="cinfo">The cinfo.</param>
        public my_1pass_cquantizer(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            m_fserrors[0] = null; /* Flag FS workspace not allocated */
            m_odither[0]  = null; /* Also flag odither arrays not allocated */

            /* Make sure my internal arrays won't overflow */
            if (cinfo.m_out_color_components > MAX_Q_COMPS)
            {
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
            }

            /* Make sure colormap indexes can be represented by JSAMPLEs */
            if (cinfo.m_desired_number_of_colors > (JpegConstants.MAXJSAMPLE + 1))
            {
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_MANY_COLORS, JpegConstants.MAXJSAMPLE + 1);
            }

            /* Create the colormap and color index table. */
            create_colormap();
            create_colorindex();

            /* Allocate Floyd-Steinberg workspace now if requested.
             * We do this now since it is FAR storage and may affect the memory
             * manager's space calculations.  If the user changes to FS dither
             * mode in a later pass, we will allocate the space then, and will
             * possibly overrun the max_memory_to_use setting.
             */
            if (cinfo.m_dither_mode == J_DITHER_MODE.JDITHER_FS)
            {
                alloc_fs_workspace();
            }
        }
예제 #10
0
        private void Enc(string inputPath, string outputPath, byte[] data)
        {
            var input = new jpeg_decompress_struct();

            using (var fileStream = new FileStream(inputPath, FileMode.Open))
            {
                input.jpeg_stdio_src(fileStream);
                input.jpeg_read_header(false);
                var coefficients = input.jpeg_read_coefficients();

                var channels = coefficients.Take(3).Select(JpegHelper.GetBuffer).ToArray();
                Encrypt(channels, data);

                var output = new jpeg_compress_struct();
                using (var outfile = new FileStream(outputPath, FileMode.Create))
                {
                    output.jpeg_stdio_dest(outfile);

                    input.jpeg_copy_critical_parameters(output);

                    output.jpeg_write_coefficients(coefficients);
                    output.jpeg_finish_compress();
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Get the Huffman tables using reflection for a specific component (AC, DC)
        /// </summary>
        /// <returns></returns>
        public static HuffmanTable[] GetHuffmanTables(string JpegFilePath)
        {
            FileStream             objFileStreamMegaMap = File.Create(JpegFilePath);
            jpeg_decompress_struct jpds = new jpeg_decompress_struct();
            jpeg_compress_struct   jpcs = new jpeg_compress_struct();

            jpcs.jpeg_stdio_dest(objFileStreamMegaMap);
            jpds.jpeg_copy_critical_parameters(jpcs);
            jpds.jpeg_finish_decompress();
            objFileStreamMegaMap.Close();

            // DC Huffman tables
            JHUFF_TBL[] jpeg_dc_huffman_tables = jpcs.Dc_huff_tbl_ptrs;
            var         comp = HuffmanTable.EnumComponent.DC;
            var         htdc = getHTables(jpeg_dc_huffman_tables, comp);

            // AC Huffman tables
            JHUFF_TBL[] jpeg_ac_huffman_tables = jpcs.Ac_huff_tbl_ptrs;
            comp = HuffmanTable.EnumComponent.AC;
            var htac = getHTables(jpeg_ac_huffman_tables, comp);

            HuffmanTable[] hts = new HuffmanTable[htdc.Length + htac.Length];
            Array.Copy(htdc, hts, htdc.Length);
            Array.Copy(htac, 0, hts, htdc.Length, htac.Length);

            return(hts);
        }
예제 #12
0
        /// <summary>
        /// The DCT coefficients are returned in a structure where the different components are separated in 2D arrays od shorts[][].
        /// The first dimension of the array contains the Blocks and the second dimension the 64 values for that block.
        /// </summary>
        /// <returns></returns>
        public static DCTCoefficients GetDctCoefficients(string JpegFilePath)
        {
            jpeg_decompress_struct jpds          = new jpeg_decompress_struct();
            FileStream             fileStreamImg = new FileStream(JpegFilePath, FileMode.Open, FileAccess.Read);

            jpds.jpeg_stdio_src(fileStreamImg);
            jpds.jpeg_read_header(true);
            // DCT coefficients
            var jBlock = jpds.jpeg_read_coefficients();
            // Initialize the list for all the dct
            var dctFull   = new List <short>();
            var dctFullDc = new List <short>();
            var dctFullAc = new List <short>();
            // Get coeffs and fill the list _dctFull
            List <short[]> dctCr = readDctCoeffs(EnumStegoChannel.Cr, jBlock, dctFull, dctFullDc, dctFullAc);
            List <short[]> dctCb = readDctCoeffs(EnumStegoChannel.Cb, jBlock, dctFull, dctFullDc, dctFullAc);
            List <short[]> dctY  = readDctCoeffs(EnumStegoChannel.Y, jBlock, dctFull, dctFullDc, dctFullAc);

            // Close decompress and filestream
            jpds.jpeg_finish_decompress();
            fileStreamImg.Close();
            // Return DCT coefficients
            DCTCoefficients dctCoeffs = new DCTCoefficients
            {
                DctY      = dctY.ToArray(),
                DctCb     = dctCb.ToArray(),
                DctCr     = dctCr.ToArray(),
                DctFull   = dctFull.ToArray(),
                DctFullDc = dctFullDc.ToArray(),
                DctFullAc = dctFullAc.ToArray()
            };

            return(dctCoeffs);
        }
        private int m_next_row;                   /* index of next row to fill/empty in strip */

        /// <summary>
        /// Initialize postprocessing controller.
        /// </summary>
        public jpeg_d_post_controller(jpeg_decompress_struct cinfo, bool need_full_buffer)
        {
            m_cinfo = cinfo;

            /* Create the quantization buffer, if needed */
            if (cinfo.m_quantize_colors)
            {
                /* The buffer strip height is max_v_samp_factor, which is typically
                 * an efficient number of rows for upsampling to return.
                 * (In the presence of output rescaling, we might want to be smarter?)
                 */
                m_strip_height = cinfo.m_max_v_samp_factor;

                if (need_full_buffer)
                {
                    /* Two-pass color quantization: need full-image storage. */
                    /* We round up the number of rows to a multiple of the strip height. */
                    m_whole_image = jpeg_common_struct.CreateSamplesArray(
                        cinfo.m_output_width * cinfo.m_out_color_components,
                        JpegUtils.jround_up(cinfo.m_output_height, m_strip_height));
                    m_whole_image.ErrorProcessor = cinfo;
                }
                else
                {
                    /* One-pass color quantization: just make a strip buffer. */
                    m_buffer = jpeg_common_struct.AllocJpegSamples(
                        cinfo.m_output_width * cinfo.m_out_color_components, m_strip_height);
                }
            }
        }
예제 #14
0
        /// <summary>
        /// Get the Quantization tables using reflection per component
        /// </summary>
        /// <returns></returns>
        public static short[][] GetQuantizationTables(string JpegFilePath)
        {
            FileStream             objFileStreamMegaMap = File.Create(JpegFilePath);
            jpeg_decompress_struct jpds = new jpeg_decompress_struct();
            jpeg_compress_struct   jpcs = new jpeg_compress_struct();

            jpcs.jpeg_stdio_dest(objFileStreamMegaMap);
            jpds.jpeg_copy_critical_parameters(jpcs);
            jpds.jpeg_finish_decompress();
            objFileStreamMegaMap.Close();
            JQUANT_TBL[] jpeg_quant_tables = jpcs.Quant_tbl_ptrs;
            int          qCount            = jpeg_quant_tables.Length;

            short[][]    qt        = new short[qCount][];
            BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
            int          idx       = 0;

            while (null != jpeg_quant_tables[idx])
            {
                Type      type     = jpeg_quant_tables[idx].GetType();
                object    instance = jpeg_quant_tables[idx];
                FieldInfo field    = type.GetField("quantval", bindFlags);
                qt[idx] = field.GetValue(instance) as short[];
                ++idx;
            }
            var qTables = qt.Where(tab => null != tab).ToArray();

            return(qTables);
        }
예제 #15
0
        /// <summary>
        /// This is the default resync_to_restart method for data source
        /// managers to use if they don't have any better approach.
        /// </summary>
        /// <param name="cinfo">An instance of <see cref="jpeg_decompress_struct"/></param>
        /// <param name="desired">The desired</param>
        /// <returns><c>false</c> if suspension is required.</returns>
        /// <remarks>That method assumes that no backtracking is possible.
        /// Some data source managers may be able to back up, or may have
        /// additional knowledge about the data which permits a more
        /// intelligent recovery strategy; such managers would
        /// presumably supply their own resync method.<br/><br/>
        /// read_restart_marker calls resync_to_restart if it finds a marker other than
        /// the restart marker it was expecting.  (This code is *not* used unless
        /// a nonzero restart interval has been declared.)  cinfo.unread_marker is
        /// the marker code actually found (might be anything, except 0 or FF).
        /// The desired restart marker number (0..7) is passed as a parameter.<br/><br/>
        /// This routine is supposed to apply whatever error recovery strategy seems
        /// appropriate in order to position the input stream to the next data segment.
        /// Note that cinfo.unread_marker is treated as a marker appearing before
        /// the current data-source input point; usually it should be reset to zero
        /// before returning.<br/><br/>
        /// This implementation is substantially constrained by wanting to treat the
        /// input as a data stream; this means we can't back up.  Therefore, we have
        /// only the following actions to work with:<br/>
        /// 1. Simply discard the marker and let the entropy decoder resume at next
        /// byte of file.<br/>
        /// 2. Read forward until we find another marker, discarding intervening
        /// data.  (In theory we could look ahead within the current bufferload,
        /// without having to discard data if we don't find the desired marker.
        /// This idea is not implemented here, in part because it makes behavior
        /// dependent on buffer size and chance buffer-boundary positions.)<br/>
        /// 3. Leave the marker unread (by failing to zero cinfo.unread_marker).
        /// This will cause the entropy decoder to process an empty data segment,
        /// inserting dummy zeroes, and then we will reprocess the marker.<br/>
        /// #2 is appropriate if we think the desired marker lies ahead, while #3 is
        /// appropriate if the found marker is a future restart marker (indicating
        /// that we have missed the desired restart marker, probably because it got
        /// corrupted).<br/>
        /// We apply #2 or #3 if the found marker is a restart marker no more than
        /// two counts behind or ahead of the expected one.  We also apply #2 if the
        /// found marker is not a legal JPEG marker code (it's certainly bogus data).
        /// If the found marker is a restart marker more than 2 counts away, we do #1
        /// (too much risk that the marker is erroneous; with luck we will be able to
        /// resync at some future point).<br/>
        /// For any valid non-restart JPEG marker, we apply #3.  This keeps us from
        /// overrunning the end of a scan.  An implementation limited to single-scan
        /// files might find it better to apply #2 for markers other than EOI, since
        /// any other marker would have to be bogus data in that case.</remarks>
        public override bool resync_to_restart(jpeg_decompress_struct cinfo, int desired)
        {
            Tiff tif = m_sp.GetTiff();

            Tiff.ErrorExt(tif, tif.m_clientdata, "LibJpeg", "Unexpected error");
            return(false);
        }
예제 #16
0
        public void TestMarkerList()
        {
            jpeg_decompress_struct cinfo = new jpeg_decompress_struct();

            using (FileStream input = new FileStream(Tester.MapOpenPath("PARROTS.JPG"), FileMode.Open))
            {
                /* Specify data source for decompression */
                cinfo.jpeg_stdio_src(input);

                const int markerDataLengthLimit = 1000;
                cinfo.jpeg_save_markers((int)JPEG_MARKER.COM, markerDataLengthLimit);
                cinfo.jpeg_save_markers((int)JPEG_MARKER.APP0, markerDataLengthLimit);

                /* Read file header, set default decompression parameters */
                cinfo.jpeg_read_header(true);

                Assert.AreEqual(cinfo.Marker_list.Count, 3);

                int[] expectedMarkerType           = { (int)JPEG_MARKER.APP0, (int)JPEG_MARKER.APP0, (int)JPEG_MARKER.COM };
                int[] expectedMarkerOriginalLength = { 14, 3072, 10 };
                for (int i = 0; i < cinfo.Marker_list.Count; ++i)
                {
                    jpeg_marker_struct marker = cinfo.Marker_list[i];
                    Assert.IsNotNull(marker);
                    Assert.AreEqual(marker.Marker, expectedMarkerType[i]);
                    Assert.AreEqual(marker.OriginalLength, expectedMarkerOriginalLength[i]);
                    Assert.LessOrEqual(marker.Data.Length, markerDataLengthLimit);
                }
            }
        }
        private savable_state m_saved = new savable_state(); /* Other state at start of MCU */

        #endregion Fields

        #region Constructors

        public huff_entropy_decoder(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Mark tables unallocated */
            for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
                m_dc_derived_tbls[i] = m_ac_derived_tbls[i] = null;
        }
예제 #18
0
        private bool m_eoi_reached;        /* True when EOI has been consumed */

        /// <summary>
        /// Initialize the input controller module.
        /// This is called only once, when the decompression object is created.
        /// </summary>
        public jpeg_input_controller(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Initialize state: can't use reset_input_controller since we don't
             * want to try to reset other modules yet.
             */
            m_inheaders = true;
        }
예제 #19
0
        private int cur_output_row;             /* next row# to write to virtual array */

        public bmp_dest_struct(jpeg_decompress_struct cinfo, bool is_os2)
        {
            this.cinfo  = cinfo;
            this.is_os2 = is_os2;

            if (cinfo.Out_color_space == J_COLOR_SPACE.JCS_GRAYSCALE)
            {
                m_putGrayRows = true;
            }
            else if (cinfo.Out_color_space == J_COLOR_SPACE.JCS_RGB)
            {
                if (cinfo.Quantize_colors)
                {
                    m_putGrayRows = true;
                }
                else
                {
                    m_putGrayRows = false;
                }
            }
            else
            {
                cinfo.ERREXIT((int)ADDON_MESSAGE_CODE.JERR_BMP_COLORSPACE);
            }

            /* Calculate output image dimensions so we can allocate space */
            cinfo.jpeg_calc_output_dimensions();

            /* Determine width of rows in the BMP file (padded to 4-byte boundary). */
            row_width  = cinfo.Output_width * cinfo.Output_components;
            data_width = row_width;
            while ((row_width & 3) != 0)
            {
                row_width++;
            }

            pad_bytes = row_width - data_width;

            /* Allocate space for inversion array, prepare for write pass */
            whole_image = jpeg_common_struct.CreateSamplesArray(row_width, cinfo.Output_height);
            whole_image.ErrorProcessor = cinfo;

            cur_output_row = 0;
            if (cinfo.Progress != null)
            {
                cdjpeg_progress_mgr progress = cinfo.Progress as cdjpeg_progress_mgr;
                if (progress != null)
                {
                    /* count file input as separate pass */
                    progress.total_extra_passes++;
                }
            }

            /* Create decompressor output buffer. */
            buffer        = jpeg_common_struct.AllocJpegSamples(row_width, 1);
            buffer_height = 1;
        }
예제 #20
0
        private bool m_eoi_reached;       /* True when EOI has been consumed */

        /// <summary>
        /// Initialize the input controller module.
        /// This is called only once, when the decompression object is created.
        /// </summary>
        public jpeg_input_controller(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Initialize state: can't use reset_input_controller since we don't
            * want to try to reset other modules yet.
            */
            m_inheaders = true;
        }
예제 #21
0
        private bool m_start_of_file;     /* have we gotten any data yet? */

        public VirtualStreamSourceManager(jpeg_decompress_struct cinfo, Stream src)
        {
            m_cinfo  = cinfo;
            m_buffer = new byte[InputBufferSize];

            m_infile = src;
            m_infile.Seek(0, SeekOrigin.Begin);
            initInternalBuffer(null, 0);
        }
예제 #22
0
        public huff_entropy_decoder(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Mark tables unallocated */
            for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
            {
                m_dc_derived_tbls[i] = m_ac_derived_tbls[i] = null;
            }
        }
예제 #23
0
        // Free a source manager.
        public static void FreeSourceManager(ref jpeg_decompress_struct cinfo)
        {
            GCHandle    handle = (GCHandle)(cinfo.client_data);
            StreamState state  = (StreamState)(handle.Target);

            Marshal.FreeHGlobal(state.buf);
            handle.Free();
            Marshal.FreeHGlobal((IntPtr)(cinfo.src));
            cinfo.client_data = IntPtr.Zero;
            cinfo.src         = null;
        }
예제 #24
0
        /// <summary>
        /// Read next byte
        /// </summary>
        static int jpeg_getc(jpeg_decompress_struct decompressor)
        {
            int v;

            if (!decompressor.Src.GetByte(out v))
            {
                decompressor.ERREXIT(J_MESSAGE_CODE.JERR_CANT_SUSPEND);
            }

            return(v);
        }
예제 #25
0
        private byte[] Dec(string inputPath, int len)
        {
            var input = new jpeg_decompress_struct();

            input.jpeg_stdio_src(new FileStream(inputPath, FileMode.Open));
            input.jpeg_read_header(false);
            var coefficients = input.jpeg_read_coefficients();

            var channels = coefficients.Take(3).Select(JpegHelper.GetBuffer).ToArray();

            return(Decrypt(channels, len));
        }
예제 #26
0
        static void applyOptions(jpeg_decompress_struct decompressor, DecompressOptions options)
        {
            Debug.Assert(decompressor != null);
            Debug.Assert(options != null);

            if (options.QuantizeColors)
            {
                decompressor.Quantize_colors          = true;
                decompressor.Desired_number_of_colors = options.DesiredNumberOfColors;
            }

            decompressor.Dct_method  = options.DCTMethod;
            decompressor.Dither_mode = options.DitherMode;

            if (options.Debug)
            {
                decompressor.Err.Trace_level = 1;
            }

            if (options.Fast)
            {
                /* Select recommended processing options for quick-and-dirty output. */
                decompressor.Two_pass_quantize = false;
                decompressor.Dither_mode       = J_DITHER_MODE.JDITHER_ORDERED;
                if (!decompressor.Quantize_colors) /* don't override an earlier -colors */
                {
                    decompressor.Desired_number_of_colors = 216;
                }
                decompressor.Dct_method          = JpegConstants.JDCT_FASTEST;
                decompressor.Do_fancy_upsampling = false;
            }

            if (options.Grayscale)
            {
                decompressor.Out_color_space = J_COLOR_SPACE.JCS_GRAYSCALE;
            }

            if (options.NoSmooth)
            {
                decompressor.Do_fancy_upsampling = false;
            }

            if (options.OnePass)
            {
                decompressor.Two_pass_quantize = false;
            }

            if (options.Scaled)
            {
                decompressor.Scale_num   = options.ScaleNumerator;
                decompressor.Scale_denom = options.ScaleDenominator;
            }
        }
예제 #27
0
        // Convert a stream into a source manager.
        public static void StreamToSourceManager
            (ref jpeg_decompress_struct cinfo, Stream stream,
            byte[] prime, int primeLen)
        {
            // Allocate a state structure and store it in "cinfo".
            IntPtr      buf   = Marshal.AllocHGlobal(4096);
            StreamState state = new StreamState();

            state.buf         = buf;
            state.buffer      = new byte [4096];
            state.stream      = stream;
            cinfo.client_data = (IntPtr)(GCHandle.Alloc(state));

            // We prime the input buffer with the JPEG magic number
            // if some higher-level process has already read it.
            int len;

            if (prime != null)
            {
                len = primeLen;
                Marshal.Copy(prime, 0, buf, len);
            }
            else
            {
                len = 0;
            }

            // Create the managed version of "jpeg_source_mgr".
            jpeg_source_mgr mgr = new jpeg_source_mgr();

            mgr.next_input_byte   = buf;
            mgr.bytes_in_buffer   = (size_t)len;
            mgr.init_source       = new init_source_type(init_source);
            mgr.fill_input_buffer =
                new fill_input_buffer_type(fill_input_buffer);
            mgr.skip_input_data =
                new skip_input_data_type(skip_input_data);
            mgr.resync_to_restart =
                new resync_to_restart_type(jpeg_resync_to_restart);
            mgr.term_source =
                new term_source_type(term_source);

            // Convert it into the unmanaged version and store it.
#if __CSCC__
            IntPtr umgr = Marshal.AllocHGlobal(sizeof(jpeg_source_mgr));
            Marshal.StructureToPtr(mgr, umgr, false);
            cinfo.src = (jpeg_source_mgr *)umgr;
#endif
        }
        public byte[] DecodeJpeg(string inputPath, int len)
        {
            var input = new jpeg_decompress_struct();

            using (var fs = new FileStream(inputPath, FileMode.Open))
            {
                input.jpeg_stdio_src(fs);
                input.jpeg_read_header(false);
                var coefficients = input.jpeg_read_coefficients();

                var channels = coefficients.Take(3).Select(JpegHelper.GetBuffer).ToArray();
                input.jpeg_finish_decompress();
                return(DecodeBlocks(channels, len));
            }
        }
예제 #29
0
        public static void ApplyQuantizationTable(string JpegFilePath, EnumStegoChannel Component = EnumStegoChannel.Y, int ScaleFactor = 50, int[] QuantizationTable = null)
        {
            var        jpds          = new jpeg_decompress_struct();
            FileStream fileStreamImg = new FileStream(JpegFilePath, FileMode.Open, FileAccess.Read);

            jpds.jpeg_stdio_src(fileStreamImg);
            jpds.jpeg_read_header(true);
            // DCT coefficients
            var jBlock = jpds.jpeg_read_coefficients();

            jpds.jpeg_finish_decompress();
            fileStreamImg.Close();

            if (null == QuantizationTable)
            {
                switch (Component)
                {
                case EnumStegoChannel.Y:
                    QuantizationTable = _qLuminance;
                    break;

                case EnumStegoChannel.Cb:
                case EnumStegoChannel.Cr:
                    QuantizationTable = _qChromiance;
                    break;
                }
            }

            // Get fle info
            FileInfo fInfo            = new FileInfo(JpegFilePath);
            string   dir              = fInfo.DirectoryName;
            string   fNane            = fInfo.Name;
            string   stegFName        = $"steg_{DateTime.Now.ToString("yyyyMMddHHmm")}_{fNane}";
            string   stegJpegFilePath = Path.Combine(dir, stegFName);
            // Compress process
            FileStream           fileStream = File.Create(stegJpegFilePath);
            jpeg_compress_struct jpcs       = new jpeg_compress_struct();

            jpcs.jpeg_stdio_dest(fileStream);
            jpds.jpeg_copy_critical_parameters(jpcs);
            jpcs.jpeg_write_coefficients(jBlock);
            jpcs.jpeg_finish_compress();
            fileStream.Close();
            jpds.jpeg_abort_decompress();
        }
예제 #30
0
        // Generic versions of jpeg_abort and jpeg_destroy that work on either
        // flavor of JPEG object.  These may be more convenient in some places.

        /// <summary>
        /// Abort processing of a JPEG compression or decompression operation,
        /// but don't destroy the object itself.
        /// 
        /// Closing a data source or destination, if necessary, is the 
        /// application's responsibility.
        /// </summary>
        public void jpeg_abort()
        {
            /* Reset overall state for possible reuse of object */
            if (IsDecompressor)
            {
                m_global_state = JpegState.DSTATE_START;

                /* Try to keep application from accessing now-deleted marker list.
                 * A bit kludgy to do it here, but this is the most central place.
                 */
                jpeg_decompress_struct s = this as jpeg_decompress_struct;
                if (s != null)
                    s.m_marker_list = null;
            }
            else
            {
                m_global_state = JpegState.CSTATE_START;
            }
        }
        private savable_state m_saved = new savable_state(); /* Other state at start of MCU */

        #endregion Fields

        #region Constructors

        public phuff_entropy_decoder(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Mark derived tables unallocated */
            for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
                m_derived_tbls[i] = null;

            /* Create progression status table */
            cinfo.m_coef_bits = new int[cinfo.m_num_components][];
            for (int i = 0; i < cinfo.m_num_components; i++)
                cinfo.m_coef_bits[i] = new int[JpegConstants.DCTSIZE2];

            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                    cinfo.m_coef_bits[ci][i] = -1;
            }
        }
예제 #32
0
        // Skip data in an input stream.
        private static void skip_input_data
            (ref jpeg_decompress_struct cinfo, Long num_bytes)
        {
#if __CSCC__
            jpeg_source_mgr *src = cinfo.src;
            int num = (int)num_bytes;
            if (num > 0)
            {
                while (num > (int)(src->bytes_in_buffer))
                {
                    num -= (int)(src->bytes_in_buffer);
                    fill_input_buffer(ref cinfo);
                }
                src->next_input_byte =
                    new IntPtr((src->next_input_byte.ToInt64()) + num);
                src->bytes_in_buffer =
                    (size_t)(((int)(src->bytes_in_buffer)) - num);
            }
#endif
        }
        private int m_rows_to_go;  /* counts rows remaining in image */

        public my_merged_upsampler(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;
            m_need_context_rows = false;

            m_out_row_width = cinfo.m_output_width * cinfo.m_out_color_components;

            if (cinfo.m_max_v_samp_factor == 2)
            {
                m_use_2v_upsample = true;
                /* Allocate a spare row buffer */
                m_spare_row = new byte[m_out_row_width];
            }
            else
            {
                m_use_2v_upsample = false;
            }

            build_ycc_rgb_table();
        }
예제 #34
0
        /// <summary>
        /// Skip over an unknown or uninteresting variable-length marker
        /// </summary>
        private static bool skip_variable(jpeg_decompress_struct cinfo)
        {
            int length;

            if (!cinfo.m_src.GetTwoBytes(out length))
            {
                return(false);
            }

            length -= 2;

            cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_MISC_MARKER, cinfo.m_unread_marker, length);

            if (length > 0)
            {
                cinfo.m_src.skip_input_data(length);
            }

            return(true);
        }
        private int m_bytes_read;        /* data bytes read so far in marker */
        /* Note: cur_marker is not linked into marker_list until it's all read. */

        /// <summary>
        /// Initialize the marker reader module.
        /// This is called only once, when the decompression object is created.
        /// </summary>
        public jpeg_marker_reader(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Initialize COM/APPn processing.
            * By default, we examine and then discard APP0 and APP14,
            * but simply discard COM and all other APPn.
            */
            m_process_COM = skip_variable;

            for (int i = 0; i < 16; i++)
            {
                m_process_APPn[i] = skip_variable;
                m_length_limit_APPn[i] = 0;
            }

            m_process_APPn[0] = get_interesting_appn;
            m_process_APPn[14] = get_interesting_appn;

            /* Reset marker processing state */
            reset_marker_reader();
        }
예제 #36
0
        private int m_bytes_read;                /* data bytes read so far in marker */
        /* Note: cur_marker is not linked into marker_list until it's all read. */

        /// <summary>
        /// Initialize the marker reader module.
        /// This is called only once, when the decompression object is created.
        /// </summary>
        public jpeg_marker_reader(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Initialize COM/APPn processing.
             * By default, we examine and then discard APP0 and APP14,
             * but simply discard COM and all other APPn.
             */
            m_process_COM = skip_variable;

            for (int i = 0; i < 16; i++)
            {
                m_process_APPn[i]      = skip_variable;
                m_length_limit_APPn[i] = 0;
            }

            m_process_APPn[0]  = get_interesting_appn;
            m_process_APPn[14] = get_interesting_appn;

            /* Reset marker processing state */
            reset_marker_reader();
        }
예제 #37
0
 /// <summary>
 /// Examine first few bytes from an APP14.
 /// Take appropriate action if it is an Adobe marker.
 /// datalen is # of bytes at data[], remaining is length of rest of marker data.
 /// </summary>
 private static void examine_app14(jpeg_decompress_struct cinfo, byte[] data, int datalen, int remaining)
 {
     if (datalen >= APP14_DATA_LEN &&
         data[0] == 0x41 &&
         data[1] == 0x64 &&
         data[2] == 0x6F &&
         data[3] == 0x62 &&
         data[4] == 0x65)
     {
         /* Found Adobe APP14 marker */
         int version   = (data[5] << 8) + data[6];
         int flags0    = (data[7] << 8) + data[8];
         int flags1    = (data[9] << 8) + data[10];
         int transform = data[11];
         cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_ADOBE, version, flags0, flags1, transform);
         cinfo.m_saw_Adobe_marker = true;
         cinfo.m_Adobe_transform  = (byte)transform;
     }
     else
     {
         /* Start of APP14 does not match "Adobe", or too short */
         cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_APP14, datalen + remaining);
     }
 }
        /// <summary>
        /// Save an APPn or COM marker into the marker list
        /// </summary>
        private static bool save_marker(jpeg_decompress_struct cinfo)
        {
            jpeg_marker_struct cur_marker = cinfo.m_marker.m_cur_marker;
    
            byte[] data = null;
            int length = 0;
            int bytes_read;
            int data_length;
            int dataOffset = 0;

            if (cur_marker == null)
            {
                /* begin reading a marker */
                if (!cinfo.m_src.GetTwoBytes(out length))
                    return false;

                length -= 2;
                if (length >= 0)
                {
                    /* watch out for bogus length word */
                    /* figure out how much we want to save */
                    int limit;
                    if (cinfo.m_unread_marker == (int)JPEG_MARKER.COM)
                        limit = cinfo.m_marker.m_length_limit_COM;
                    else
                        limit = cinfo.m_marker.m_length_limit_APPn[cinfo.m_unread_marker - (int)JPEG_MARKER.APP0];

                    if (length < limit)
                        limit = length;
                    
                    /* allocate and initialize the marker item */
                    cur_marker = new jpeg_marker_struct((byte)cinfo.m_unread_marker, length, limit);
                    
                    /* data area is just beyond the jpeg_marker_struct */
                    data = cur_marker.Data;
                    cinfo.m_marker.m_cur_marker = cur_marker;
                    cinfo.m_marker.m_bytes_read = 0;
                    bytes_read = 0;
                    data_length = limit;
                }
                else
                {
                    /* deal with bogus length word */
                    bytes_read = data_length = 0;
                    data = null;
                }
            }
            else
            {
                /* resume reading a marker */
                bytes_read = cinfo.m_marker.m_bytes_read;
                data_length = cur_marker.Data.Length;
                data = cur_marker.Data;
                dataOffset = bytes_read;
            }

            byte[] tempData = null;
            if (data_length != 0)
                tempData = new byte[data.Length];

            while (bytes_read < data_length)
            {
                /* move the restart point to here */
                cinfo.m_marker.m_bytes_read = bytes_read;

                /* If there's not at least one byte in buffer, suspend */
                if (!cinfo.m_src.MakeByteAvailable())
                    return false;

                /* Copy bytes with reasonable rapidity */
                int read = cinfo.m_src.GetBytes(tempData, data_length - bytes_read);
                Buffer.BlockCopy(tempData, 0, data, dataOffset, data_length - bytes_read);
                bytes_read += read;
            }

            /* Done reading what we want to read */
            if (cur_marker != null)
            {
                /* will be null if bogus length word */
                /* Add new marker to end of list */
                cinfo.m_marker_list.Add(cur_marker);

                /* Reset pointer & calc remaining data length */
                data = cur_marker.Data;
                dataOffset = 0;
                length = cur_marker.OriginalLength - data_length;
            }

            /* Reset to initial state for next marker */
            cinfo.m_marker.m_cur_marker = null;

            JPEG_MARKER currentMarker = (JPEG_MARKER)cinfo.m_unread_marker;
            if (data_length != 0 && (currentMarker == JPEG_MARKER.APP0 || currentMarker == JPEG_MARKER.APP14))
            {
                tempData = new byte[data.Length];
                Buffer.BlockCopy(data, dataOffset, tempData, 0, data.Length - dataOffset);
            }

            /* Process the marker if interesting; else just make a generic trace msg */
            switch ((JPEG_MARKER)cinfo.m_unread_marker)
            {
                case JPEG_MARKER.APP0:
                    examine_app0(cinfo, tempData, data_length, length);
                    break;
                case JPEG_MARKER.APP14:
                    examine_app14(cinfo, tempData, data_length, length);
                    break;
                default:
                    cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_MISC_MARKER, cinfo.m_unread_marker, data_length + length);
                    break;
            }

            /* skip any remaining data -- could be lots */
            if (length > 0)
                cinfo.m_src.skip_input_data(length);

            return true;
        }
        private bool m_on_odd_row;		/* flag to remember which row we are on */

        /// <summary>
        /// Module initialization routine for 1-pass color quantization.
        /// </summary>
        /// <param name="cinfo">The cinfo.</param>
        public my_1pass_cquantizer(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            m_fserrors[0] = null; /* Flag FS workspace not allocated */
            m_odither[0] = null;    /* Also flag odither arrays not allocated */

            /* Make sure my internal arrays won't overflow */
            if (cinfo.m_out_color_components > MAX_Q_COMPS)
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_COMPONENTS, MAX_Q_COMPS);

            /* Make sure colormap indexes can be represented by JSAMPLEs */
            if (cinfo.m_desired_number_of_colors > (JpegConstants.MAXJSAMPLE + 1))
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_MANY_COLORS, JpegConstants.MAXJSAMPLE + 1);

            /* Create the colormap and color index table. */
            create_colormap();
            create_colorindex();

            /* Allocate Floyd-Steinberg workspace now if requested.
            * We do this now since it is FAR storage and may affect the memory
            * manager's space calculations.  If the user changes to FS dither
            * mode in a later pass, we will allocate the space then, and will
            * possibly overrun the max_memory_to_use setting.
            */
            if (cinfo.m_dither_mode == J_DITHER_MODE.JDITHER_FS)
                alloc_fs_workspace();
        }
예제 #40
0
 private bool m_start_of_file; /* have we gotten any data yet? */
 
 /// <summary>
 /// Initialize source - called by jpeg_read_header
 /// before any data is actually read.
 /// </summary>
 public my_source_mgr(jpeg_decompress_struct cinfo)
 {
     m_cinfo = cinfo;
     m_buffer = new byte[INPUT_BUF_SIZE];
 }
 /// <summary>
 /// Install a special processing method for COM or APPn markers.
 /// </summary>
 public void jpeg_set_marker_processor(int marker_code, jpeg_decompress_struct.jpeg_marker_parser_method routine)
 {
     if (marker_code == (int)JPEG_MARKER.COM)
         m_process_COM = routine;
     else if (marker_code >= (int)JPEG_MARKER.APP0 && marker_code <= (int)JPEG_MARKER.APP15)
         m_process_APPn[marker_code - (int)JPEG_MARKER.APP0] = routine;
     else
         m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_UNKNOWN_MARKER, marker_code);
 }
        private int m_whichFunny; /* indicates which funny indices set is now in use */

        #endregion Fields

        #region Constructors

        public jpeg_d_main_controller(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Allocate the workspace.
            * ngroups is the number of row groups we need.
            */
            int ngroups = cinfo.m_min_DCT_scaled_size;
            if (cinfo.m_upsample.NeedContextRows())
            {
                if (cinfo.m_min_DCT_scaled_size < 2) /* unsupported, see comments above */
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL);

                alloc_funny_pointers(); /* Alloc space for xbuffer[] lists */
                ngroups = cinfo.m_min_DCT_scaled_size + 2;
            }

            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                /* height of a row group of component */
                int rgroup = (cinfo.Comp_info[ci].V_samp_factor * cinfo.Comp_info[ci].DCT_scaled_size) / cinfo.m_min_DCT_scaled_size;

                m_buffer[ci] = jpeg_common_struct.AllocJpegSamples(
                    cinfo.Comp_info[ci].Width_in_blocks * cinfo.Comp_info[ci].DCT_scaled_size,
                    rgroup * ngroups);
            }
        }
예제 #43
0
	// Skip data in an input stream.
	private static void skip_input_data
				(ref jpeg_decompress_struct cinfo, Long num_bytes)
			{
#if __CSCC__
				jpeg_source_mgr *src = cinfo.src;
				int num = (int)num_bytes;
				if(num > 0)
				{
					while(num > (int)(src->bytes_in_buffer))
					{
						num -= (int)(src->bytes_in_buffer);
						fill_input_buffer(ref cinfo);
					}
					src->next_input_byte =
						new IntPtr((src->next_input_byte.ToInt64()) + num);
					src->bytes_in_buffer =
						(size_t)(((int)(src->bytes_in_buffer)) - num);
				}
#endif
			}
예제 #44
0
        /// <summary>
        /// This is the default resync_to_restart method for data source 
        /// managers to use if they don't have any better approach.
        /// </summary>
        /// <param name="cinfo">An instance of <see cref="jpeg_decompress_struct"/></param>
        /// <param name="desired">The desired</param>
        /// <returns><c>false</c> if suspension is required.</returns>
        /// <remarks>That method assumes that no backtracking is possible. 
        /// Some data source managers may be able to back up, or may have 
        /// additional knowledge about the data which permits a more 
        /// intelligent recovery strategy; such managers would
        /// presumably supply their own resync method.<br/><br/>
        /// 
        /// read_restart_marker calls resync_to_restart if it finds a marker other than
        /// the restart marker it was expecting.  (This code is *not* used unless
        /// a nonzero restart interval has been declared.)  cinfo.unread_marker is
        /// the marker code actually found (might be anything, except 0 or FF).
        /// The desired restart marker number (0..7) is passed as a parameter.<br/><br/>
        /// 
        /// This routine is supposed to apply whatever error recovery strategy seems
        /// appropriate in order to position the input stream to the next data segment.
        /// Note that cinfo.unread_marker is treated as a marker appearing before
        /// the current data-source input point; usually it should be reset to zero
        /// before returning.<br/><br/>
        /// 
        /// This implementation is substantially constrained by wanting to treat the
        /// input as a data stream; this means we can't back up.  Therefore, we have
        /// only the following actions to work with:<br/>
        /// 1. Simply discard the marker and let the entropy decoder resume at next
        /// byte of file.<br/>
        /// 2. Read forward until we find another marker, discarding intervening
        /// data.  (In theory we could look ahead within the current bufferload,
        /// without having to discard data if we don't find the desired marker.
        /// This idea is not implemented here, in part because it makes behavior
        /// dependent on buffer size and chance buffer-boundary positions.)<br/>
        /// 3. Leave the marker unread (by failing to zero cinfo.unread_marker).
        /// This will cause the entropy decoder to process an empty data segment,
        /// inserting dummy zeroes, and then we will reprocess the marker.<br/>
        /// 
        /// #2 is appropriate if we think the desired marker lies ahead, while #3 is
        /// appropriate if the found marker is a future restart marker (indicating
        /// that we have missed the desired restart marker, probably because it got
        /// corrupted).<br/>
        /// We apply #2 or #3 if the found marker is a restart marker no more than
        /// two counts behind or ahead of the expected one.  We also apply #2 if the
        /// found marker is not a legal JPEG marker code (it's certainly bogus data).
        /// If the found marker is a restart marker more than 2 counts away, we do #1
        /// (too much risk that the marker is erroneous; with luck we will be able to
        /// resync at some future point).<br/>
        /// For any valid non-restart JPEG marker, we apply #3.  This keeps us from
        /// overrunning the end of a scan.  An implementation limited to single-scan
        /// files might find it better to apply #2 for markers other than EOI, since
        /// any other marker would have to be bogus data in that case.</remarks>
        public virtual bool resync_to_restart(jpeg_decompress_struct cinfo, int desired)
        {
            /* Always put up a warning. */
            cinfo.WARNMS(J_MESSAGE_CODE.JWRN_MUST_RESYNC, cinfo.m_unread_marker, desired);

            /* Outer loop handles repeated decision after scanning forward. */
            int action = 1;
            for ( ; ; )
            {
                if (cinfo.m_unread_marker < (int)JPEG_MARKER.SOF0)
                {
                    /* invalid marker */
                    action = 2;
                }
                else if (cinfo.m_unread_marker < (int)JPEG_MARKER.RST0 ||
                    cinfo.m_unread_marker > (int)JPEG_MARKER.RST7)
                {
                    /* valid non-restart marker */
                    action = 3;
                }
                else
                {
                    if (cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired + 1) & 7))
                        || cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired + 2) & 7)))
                    {
                        /* one of the next two expected restarts */
                        action = 3;
                    }
                    else if (cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired - 1) & 7)) ||
                        cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired - 2) & 7)))
                    {
                        /* a prior restart, so advance */
                        action = 2;
                    }
                    else
                    {
                        /* desired restart or too far away */
                        action = 1;
                    }
                }

                cinfo.TRACEMS(4, J_MESSAGE_CODE.JTRC_RECOVERY_ACTION, cinfo.m_unread_marker, action);

                switch (action)
                {
                    case 1:
                        /* Discard marker and let entropy decoder resume processing. */
                        cinfo.m_unread_marker = 0;
                        return true;
                    case 2:
                        /* Scan to the next marker, and repeat the decision loop. */
                        if (!cinfo.m_marker.next_marker())
                            return false;
                        break;
                    case 3:
                        /* Return without advancing past this marker. */
                        /* Entropy decoder will be forced to process an empty segment. */
                        return true;
                }
            }
        }
예제 #45
0
 public jpeg_decomp_master(jpeg_decompress_struct cinfo)
 {
     m_cinfo = cinfo;
     master_selection();
 }
        private int[] rgb_y_tab;        /* => table for RGB to Y conversion */

        /// <summary>
        /// Module initialization routine for output colorspace conversion.
        /// </summary>
        public jpeg_color_deconverter(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Make sure num_components agrees with jpeg_color_space */
            switch (cinfo.m_jpeg_color_space)
            {
                case J_COLOR_SPACE.JCS_GRAYSCALE:
                    if (cinfo.m_num_components != 1)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                case J_COLOR_SPACE.JCS_RGB:
                case J_COLOR_SPACE.JCS_YCbCr:
                case J_COLOR_SPACE.JCS_BG_RGB:
                case J_COLOR_SPACE.JCS_BG_YCC:
                    if (cinfo.m_num_components != 3)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                case J_COLOR_SPACE.JCS_CMYK:
                case J_COLOR_SPACE.JCS_YCCK:
                    if (cinfo.m_num_components != 4)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                case J_COLOR_SPACE.JCS_NCHANNEL:
                    if (cinfo.m_num_components < 1)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                default:
                    /* JCS_UNKNOWN can be anything */
                    if (cinfo.m_num_components < 1)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;
            }

            /* Support color transform only for RGB colorspaces */
            if (cinfo.color_transform != J_COLOR_TRANSFORM.JCT_NONE &&
                cinfo.m_jpeg_color_space != J_COLOR_SPACE.JCS_RGB &&
                cinfo.m_jpeg_color_space != J_COLOR_SPACE.JCS_BG_RGB)
            {
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
            }

            /* Set out_color_components and conversion method based on requested space.
            * Also clear the component_needed flags for any unused components,
            * so that earlier pipeline stages can avoid useless computation.
            */

            switch (cinfo.m_out_color_space)
            {
                case J_COLOR_SPACE.JCS_GRAYSCALE:
                    cinfo.m_out_color_components = 1;
                    switch (cinfo.m_jpeg_color_space)
                    {
                        case J_COLOR_SPACE.JCS_GRAYSCALE:
                        case J_COLOR_SPACE.JCS_YCbCr:
                        case J_COLOR_SPACE.JCS_BG_YCC:
                            m_converter = grayscale_convert;
                            /* For color->grayscale conversion, only the Y (0) component is needed */
                            for (int ci = 1; ci < cinfo.m_num_components; ci++)
                                cinfo.Comp_info[ci].component_needed = false;
                            break;

                        case J_COLOR_SPACE.JCS_RGB:
                            switch (cinfo.color_transform)
                            {
                                case J_COLOR_TRANSFORM.JCT_NONE:
                                    m_converter = rgb_gray_convert;
                                    break;

                                case J_COLOR_TRANSFORM.JCT_SUBTRACT_GREEN:
                                    m_converter = rgb1_gray_convert;
                                    break;

                                default:
                                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                                    break;
                            }

                            build_rgb_y_table();
                            break;

                        default:
                            cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                            break;
                    }
                    break;

                case J_COLOR_SPACE.JCS_RGB:
                    cinfo.m_out_color_components = JpegConstants.RGB_PIXELSIZE;
                    switch (cinfo.m_jpeg_color_space)
                    {
                        case J_COLOR_SPACE.JCS_GRAYSCALE:
                            m_converter = gray_rgb_convert;
                            break;

                        case J_COLOR_SPACE.JCS_YCbCr:
                            m_converter = ycc_rgb_convert;
                            build_ycc_rgb_table();
                            break;

                        case J_COLOR_SPACE.JCS_BG_YCC:
                            m_converter = ycc_rgb_convert;
                            build_bg_ycc_rgb_table();
                            break;

                        case J_COLOR_SPACE.JCS_RGB:
                            switch (cinfo.color_transform)
                            {
                                case J_COLOR_TRANSFORM.JCT_NONE:
                                    m_converter = rgb_convert;
                                    break;

                                case J_COLOR_TRANSFORM.JCT_SUBTRACT_GREEN:
                                    m_converter = rgb1_rgb_convert;
                                    break;

                                default:
                                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                                    break;
                            }
                            break;

                        case J_COLOR_SPACE.JCS_CMYK:
                            m_converter = cmyk_rgb_convert;
                            break;

                        case J_COLOR_SPACE.JCS_YCCK:
                            m_converter = ycck_rgb_convert;
                            build_ycc_rgb_table();
                            break;

                        default:
                            cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                            break;
                    }
                    break;

                case J_COLOR_SPACE.JCS_BG_RGB:
                    cinfo.m_out_color_components = JpegConstants.RGB_PIXELSIZE;
                    if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_BG_RGB)
                    {
                        switch (cinfo.color_transform)
                        {
                            case J_COLOR_TRANSFORM.JCT_NONE:
                                m_converter = rgb_convert;
                                break;

                            case J_COLOR_TRANSFORM.JCT_SUBTRACT_GREEN:
                                m_converter = rgb1_rgb_convert;
                                break;

                            default:
                                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                                break;
                        }
                    }
                    else
                    {
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    }
                    break;

                case J_COLOR_SPACE.JCS_CMYK:
                    cinfo.m_out_color_components = 4;
                    switch (cinfo.m_jpeg_color_space)
                    {
                        case J_COLOR_SPACE.JCS_YCCK:
                            m_converter = ycck_cmyk_convert;
                            build_ycc_rgb_table();
                            break;

                        case J_COLOR_SPACE.JCS_CMYK:
                            m_converter = null_convert;
                            break;

                        default:
                            cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                            break;
                    }
                    break;

                case J_COLOR_SPACE.JCS_NCHANNEL:
                    if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_NCHANNEL)
                        m_converter = null_convert;
                    else
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    break;

                default:
                    /* Permit null conversion to same output space */
                    if (cinfo.m_out_color_space == cinfo.m_jpeg_color_space)
                    {
                        cinfo.m_out_color_components = cinfo.m_num_components;
                        m_converter = null_convert;
                    }
                    else
                    {
                        /* unsupported non-null conversion */
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    }
                    break;
            }

            if (cinfo.m_quantize_colors)
                cinfo.m_output_components = 1; /* single colormapped output component */
            else
                cinfo.m_output_components = cinfo.m_out_color_components;
        }
        /*
         * Routines for processing APPn and COM markers.
         * These are either saved in memory or discarded, per application request.
         * APP0 and APP14 are specially checked to see if they are
         * JFIF and Adobe markers, respectively.
         */

        /// <summary>
        /// Examine first few bytes from an APP0.
        /// Take appropriate action if it is a JFIF marker.
        /// datalen is # of bytes at data[], remaining is length of rest of marker data.
        /// </summary>
        private static void examine_app0(jpeg_decompress_struct cinfo, byte[] data, int datalen, int remaining)
        {
            int totallen = datalen + remaining;

            if (datalen >= APP0_DATA_LEN &&
                data[0] == 0x4A &&
                data[1] == 0x46 &&
                data[2] == 0x49 &&
                data[3] == 0x46 &&
                data[4] == 0)
            {
                /* Found JFIF APP0 marker: save info */
                cinfo.m_saw_JFIF_marker = true;
                cinfo.m_JFIF_major_version = data[5];
                cinfo.m_JFIF_minor_version = data[6];
                cinfo.m_density_unit = (DensityUnit)data[7];
                cinfo.m_X_density = (short)((data[8] << 8) + data[9]);
                cinfo.m_Y_density = (short)((data[10] << 8) + data[11]);

                /* Check version.
                 * Major version must be 1, anything else signals an incompatible change.
                 * (We used to treat this as an error, but now it's a nonfatal warning,
                 * because some bozo at Hijaak couldn't read the spec.)
                 * Minor version should be 0..2, but process anyway if newer.
                 */
                if (cinfo.m_JFIF_major_version != 1)
                    cinfo.WARNMS(J_MESSAGE_CODE.JWRN_JFIF_MAJOR, cinfo.m_JFIF_major_version, cinfo.m_JFIF_minor_version);

                /* Generate trace messages */
                cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_JFIF, cinfo.m_JFIF_major_version, cinfo.m_JFIF_minor_version, cinfo.m_X_density,
                                cinfo.m_Y_density, cinfo.m_density_unit);

                /* Validate thumbnail dimensions and issue appropriate messages */
                if ((data[12] | data[13]) != 0)
                    cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_JFIF_THUMBNAIL, data[12], data[13]);

                totallen -= APP0_DATA_LEN;
                if (totallen != ((int)data[12] * (int)data[13] * 3))
                    cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_JFIF_BADTHUMBNAILSIZE, totallen);
            }
            else if (datalen >= 6 && data[0] == 0x4A && data[1] == 0x46 && data[2] == 0x58 && data[3] == 0x58 && data[4] == 0)
            {
                /* Found JFIF "JFXX" extension APP0 marker */
                /* The library doesn't actually do anything with these,
                 * but we try to produce a helpful trace message.
                 */
                switch (data[5])
                {
                    case 0x10:
                        cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_THUMB_JPEG, totallen);
                        break;
                    case 0x11:
                        cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_THUMB_PALETTE, totallen);
                        break;
                    case 0x13:
                        cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_THUMB_RGB, totallen);
                        break;
                    default:
                        cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_JFIF_EXTENSION, data[5], totallen);
                        break;
                }
            }
            else
            {
                /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
                cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_APP0, totallen);
            }
        }
예제 #48
0
	// Convert a stream into a source manager.
	public static void StreamToSourceManager
				(ref jpeg_decompress_struct cinfo, Stream stream,
				 byte[] prime, int primeLen)
			{
				// Allocate a state structure and store it in "cinfo".
				IntPtr buf = Marshal.AllocHGlobal(4096);
				StreamState state = new StreamState();
				state.buf = buf;
				state.buffer = new byte [4096];
				state.stream = stream;
				cinfo.client_data = (IntPtr)(GCHandle.Alloc(state));

				// We prime the input buffer with the JPEG magic number
				// if some higher-level process has already read it.
				int len;
				if(prime != null)
				{
					len = primeLen;
					Marshal.Copy(prime, 0, buf, len);
				}
				else
				{
					len = 0;
				}

				// Create the managed version of "jpeg_source_mgr".
				jpeg_source_mgr mgr = new jpeg_source_mgr();
				mgr.next_input_byte = buf;
				mgr.bytes_in_buffer = (size_t)len;
				mgr.init_source = new init_source_type(init_source);
				mgr.fill_input_buffer =
					new fill_input_buffer_type(fill_input_buffer);
				mgr.skip_input_data =
					new skip_input_data_type(skip_input_data);
				mgr.resync_to_restart =
					new resync_to_restart_type(jpeg_resync_to_restart);
				mgr.term_source =
					new term_source_type(term_source);

				// Convert it into the unmanaged version and store it.
#if __CSCC__
				IntPtr umgr = Marshal.AllocHGlobal(sizeof(jpeg_source_mgr));
				Marshal.StructureToPtr(mgr, umgr, false);
				cinfo.src = (jpeg_source_mgr *)umgr;
#endif
			}
예제 #49
0
	// Free a source manager.
	public static void FreeSourceManager(ref jpeg_decompress_struct cinfo)
			{
				GCHandle handle = (GCHandle)(cinfo.client_data);
				StreamState state = (StreamState)(handle.Target);
				Marshal.FreeHGlobal(state.buf);
				handle.Free();
				Marshal.FreeHGlobal((IntPtr)(cinfo.src));
				cinfo.client_data = IntPtr.Zero;
				cinfo.src = null;
			}
예제 #50
0
        public huff_entropy_decoder(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            finish_pass = finish_pass_huff;

            if (m_cinfo.m_progressive_mode)
            {
                /* Create progression status table */
                cinfo.m_coef_bits = new int[cinfo.m_num_components][];
                for (int i = 0; i < cinfo.m_num_components; i++)
                    cinfo.m_coef_bits[i] = new int[JpegConstants.DCTSIZE2];

                for (int ci = 0; ci < cinfo.m_num_components; ci++)
                {
                    for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                        cinfo.m_coef_bits[ci][i] = -1;
                }

                /* Mark derived tables unallocated */
                for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
                {
                    derived_tbls[i] = null;
                }
            }
            else
            {
                /* Mark tables unallocated */
                for (int i = 0; i < JpegConstants.NUM_HUFF_TBLS; i++)
                {
                    m_dc_derived_tbls[i] = null;
                    m_ac_derived_tbls[i] = null;
                }
            }
        }
        /// <summary>
        /// Skip over an unknown or uninteresting variable-length marker
        /// </summary>
        private static bool skip_variable(jpeg_decompress_struct cinfo)
        {
            int length;
            if (!cinfo.m_src.GetTwoBytes(out length))
                return false;

            length -= 2;

            cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_MISC_MARKER, cinfo.m_unread_marker, length);

            if (length > 0)
                cinfo.m_src.skip_input_data(length);

            return true;
        }
예제 #52
0
        public my_upsampler(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;
            m_need_context_rows = false; /* until we find out differently */

            if (cinfo.m_CCIR601_sampling)    /* this isn't supported */
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CCIR601_NOTIMPL);

            /* jpeg_d_main_controller doesn't support context rows when min_DCT_scaled_size = 1,
            * so don't ask for it.
            */
            bool do_fancy = cinfo.m_do_fancy_upsampling && cinfo.m_min_DCT_scaled_size > 1;

            /* Verify we can handle the sampling factors, select per-component methods,
            * and create storage as needed.
            */
            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                jpeg_component_info componentInfo = cinfo.Comp_info[ci];

                /* Compute size of an "input group" after IDCT scaling.  This many samples
                * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
                */
                int h_in_group = (componentInfo.H_samp_factor * componentInfo.DCT_scaled_size) / cinfo.m_min_DCT_scaled_size;
                int v_in_group = (componentInfo.V_samp_factor * componentInfo.DCT_scaled_size) / cinfo.m_min_DCT_scaled_size;
                int h_out_group = cinfo.m_max_h_samp_factor;
                int v_out_group = cinfo.m_max_v_samp_factor;

                /* save for use later */
                m_rowgroup_height[ci] = v_in_group;
                bool need_buffer = true;
                if (!componentInfo.component_needed)
                {
                    /* Don't bother to upsample an uninteresting component. */
                    m_upsampleMethods[ci] = ComponentUpsampler.noop_upsampler;
                    need_buffer = false;
                }
                else if (h_in_group == h_out_group && v_in_group == v_out_group)
                {
                    /* Fullsize components can be processed without any work. */
                    m_upsampleMethods[ci] = ComponentUpsampler.fullsize_upsampler;
                    need_buffer = false;
                }
                else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group)
                {
                    /* Special cases for 2h1v upsampling */
                    if (do_fancy && componentInfo.downsampled_width > 2)
                        m_upsampleMethods[ci] = ComponentUpsampler.h2v1_fancy_upsampler;
                    else
                        m_upsampleMethods[ci] = ComponentUpsampler.h2v1_upsampler;
                }
                else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group)
                {
                    /* Special cases for 2h2v upsampling */
                    if (do_fancy && componentInfo.downsampled_width > 2)
                    {
                        m_upsampleMethods[ci] = ComponentUpsampler.h2v2_fancy_upsampler;
                        m_need_context_rows = true;
                    }
                    else
                    {
                        m_upsampleMethods[ci] = ComponentUpsampler.h2v2_upsampler;
                    }
                }
                else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0)
                {
                    /* Generic integral-factors upsampling method */
                    m_upsampleMethods[ci] = ComponentUpsampler.int_upsampler;
                    m_h_expand[ci] = (byte) (h_out_group / h_in_group);
                    m_v_expand[ci] = (byte) (v_out_group / v_in_group);
                }
                else
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_FRACT_SAMPLE_NOTIMPL);

                if (need_buffer)
                {
                    ComponentBuffer cb = new ComponentBuffer();
                    cb.SetBuffer(jpeg_common_struct.AllocJpegSamples(JpegUtils.jround_up(cinfo.m_output_width, 
                        cinfo.m_max_h_samp_factor), cinfo.m_max_v_samp_factor), null, 0);

                    m_color_buf[ci] = cb;
                }
            }
        }
        /// <summary>
        /// Process an APP0 or APP14 marker without saving it
        /// </summary>
        private static bool get_interesting_appn(jpeg_decompress_struct cinfo)
        {
            int length;
            if (!cinfo.m_src.GetTwoBytes(out length))
                return false;

            length -= 2;

            /* get the interesting part of the marker data */
            int numtoread = 0;
            if (length >= APPN_DATA_LEN)
                numtoread = APPN_DATA_LEN;
            else if (length > 0)
                numtoread = length;

            byte[] b = new byte[APPN_DATA_LEN];
            for (int i = 0; i < numtoread; i++)
            {
                int temp = 0;
                if (!cinfo.m_src.GetByte(out temp))
                    return false;

                b[i] = (byte) temp;
            }

            length -= numtoread;

            /* process it */
            switch ((JPEG_MARKER)cinfo.m_unread_marker)
            {
                case JPEG_MARKER.APP0:
                    examine_app0(cinfo, b, numtoread, length);
                    break;
                case JPEG_MARKER.APP14:
                    examine_app14(cinfo, b, numtoread, length);
                    break;
                default:
                    /* can't get here unless jpeg_save_markers chooses wrong processor */
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_UNKNOWN_MARKER, cinfo.m_unread_marker);
                    break;
            }

            /* skip any remaining data -- could be lots */
            if (length > 0)
                cinfo.m_src.skip_input_data(length);

            return true;
        }
        private int[] m_Cb_g_tab;        /* => table for Cb to G conversion */

        /// <summary>
        /// Module initialization routine for output colorspace conversion.
        /// </summary>
        public jpeg_color_deconverter(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Make sure num_components agrees with jpeg_color_space */
            switch (cinfo.m_jpeg_color_space)
            {
                case J_COLOR_SPACE.JCS_GRAYSCALE:
                    if (cinfo.m_num_components != 1)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                case J_COLOR_SPACE.JCS_RGB:
                case J_COLOR_SPACE.JCS_YCbCr:
                    if (cinfo.m_num_components != 3)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                case J_COLOR_SPACE.JCS_CMYK:
                case J_COLOR_SPACE.JCS_YCCK:
                    if (cinfo.m_num_components != 4)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;

                default:
                    /* JCS_UNKNOWN can be anything */
                    if (cinfo.m_num_components < 1)
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                    break;
            }

            /* Set out_color_components and conversion method based on requested space.
            * Also clear the component_needed flags for any unused components,
            * so that earlier pipeline stages can avoid useless computation.
            */

            switch (cinfo.m_out_color_space)
            {
                case J_COLOR_SPACE.JCS_GRAYSCALE:
                    cinfo.m_out_color_components = 1;
                    if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_GRAYSCALE || cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_YCbCr)
                    {
                        m_converter = ColorConverter.grayscale_converter;
                        /* For color->grayscale conversion, only the Y (0) component is needed */
                        for (int ci = 1; ci < cinfo.m_num_components; ci++)
                            cinfo.Comp_info[ci].component_needed = false;
                    }
                    else
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    break;

                case J_COLOR_SPACE.JCS_RGB:
                    cinfo.m_out_color_components = JpegConstants.RGB_PIXELSIZE;
                    if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_YCbCr)
                    {
                        m_converter = ColorConverter.ycc_rgb_converter;
                        build_ycc_rgb_table();
                    }
                    else if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_GRAYSCALE)
                        m_converter = ColorConverter.gray_rgb_converter;
                    else if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_RGB)
                        m_converter = ColorConverter.null_converter;
                    else
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    break;

                case J_COLOR_SPACE.JCS_CMYK:
                    cinfo.m_out_color_components = 4;
                    if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_YCCK)
                    {
                        m_converter = ColorConverter.ycck_cmyk_converter;
                        build_ycc_rgb_table();
                    }
                    else if (cinfo.m_jpeg_color_space == J_COLOR_SPACE.JCS_CMYK)
                        m_converter = ColorConverter.null_converter;
                    else
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    break;

                default:
                    /* Permit null conversion to same output space */
                    if (cinfo.m_out_color_space == cinfo.m_jpeg_color_space)
                    {
                        cinfo.m_out_color_components = cinfo.m_num_components;
                        m_converter = ColorConverter.null_converter;
                    }
                    else
                    {
                        /* unsupported non-null conversion */
                        cinfo.ERREXIT(J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                    }
                    break;
            }

            if (cinfo.m_quantize_colors)
                cinfo.m_output_components = 1; /* single colormapped output component */
            else
                cinfo.m_output_components = cinfo.m_out_color_components;
        }
 /// <summary>
 /// Examine first few bytes from an APP14.
 /// Take appropriate action if it is an Adobe marker.
 /// datalen is # of bytes at data[], remaining is length of rest of marker data.
 /// </summary>
 private static void examine_app14(jpeg_decompress_struct cinfo, byte[] data, int datalen, int remaining)
 {
     if (datalen >= APP14_DATA_LEN &&
         data[0] == 0x41 &&
         data[1] == 0x64 &&
         data[2] == 0x6F &&
         data[3] == 0x62 &&
         data[4] == 0x65)
     {
         /* Found Adobe APP14 marker */
         int version = (data[5] << 8) + data[6];
         int flags0 = (data[7] << 8) + data[8];
         int flags1 = (data[9] << 8) + data[10];
         int transform = data[11];
         cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_ADOBE, version, flags0, flags1, transform);
         cinfo.m_saw_Adobe_marker = true;
         cinfo.m_Adobe_transform = (byte) transform;
     }
     else
     {
         /* Start of APP14 does not match "Adobe", or too short */
         cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_APP14, datalen + remaining);
     }
 }
예제 #56
0
	// Terminate an input source.
	private static void term_source(ref jpeg_decompress_struct cinfo)
			{
				// Nothing to do here.
			}
예제 #57
0
	// Fill an input buffer from a stream.
	private static Int fill_input_buffer(ref jpeg_decompress_struct cinfo)
			{
				int len;
				StreamState state = GetStreamState(ref cinfo);
				if(!(state.sawEOF))
				{
					len = state.stream.Read
						(state.buffer, 0, state.buffer.Length);
					if(len > 0)
					{
						Marshal.Copy(state.buffer, 0, state.buf, len);
						cinfo.src->next_input_byte = state.buf;
						cinfo.src->bytes_in_buffer = (size_t)len;
						return (Int)1;
					}
					state.sawEOF = true;
				}

				// Insert an EOI marker to indicate end of stream to "libjpeg".
				Marshal.WriteByte(state.buf, 0, (byte)0xFF);
				Marshal.WriteByte(state.buf, 1, (byte)0xD9);
				cinfo.src->next_input_byte = state.buf;
				cinfo.src->bytes_in_buffer = (size_t)2;
				return (Int)1;
			}
예제 #58
0
        private int[] m_error_limiter;     /* table for clamping the applied error */

        /// <summary>
        /// Module initialization routine for 2-pass color quantization.
        /// </summary>
        public my_2pass_cquantizer(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Make sure jdmaster didn't give me a case I can't handle */
            if (cinfo.m_out_color_components != 3)
                cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL);

            /* Allocate the histogram/inverse colormap storage */
            m_histogram = new ushort[HIST_C0_ELEMS][];
            for (int i = 0; i < HIST_C0_ELEMS; i++)
                m_histogram[i] = new ushort[HIST_C1_ELEMS * HIST_C2_ELEMS];

            m_needs_zeroed = true; /* histogram is garbage now */

            /* Allocate storage for the completed colormap, if required.
            * We do this now since it is FAR storage and may affect
            * the memory manager's space calculations.
            */
            if (cinfo.m_enable_2pass_quant)
            {
                /* Make sure color count is acceptable */
                int desired_local = cinfo.m_desired_number_of_colors;

                /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
                if (desired_local < 8)
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_FEW_COLORS, 8);

                /* Make sure colormap indexes can be represented by JSAMPLEs */
                if (desired_local > MAXNUMCOLORS)
                    cinfo.ERREXIT(J_MESSAGE_CODE.JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);

                m_sv_colormap = jpeg_common_struct.AllocJpegSamples(desired_local, 3);
                m_desired = desired_local;
            }

            /* Only F-S dithering or no dithering is supported. */
            /* If user asks for ordered dither, give him F-S. */
            if (cinfo.m_dither_mode != J_DITHER_MODE.JDITHER_NONE)
                cinfo.m_dither_mode = J_DITHER_MODE.JDITHER_FS;

            /* Allocate Floyd-Steinberg workspace if necessary.
            * This isn't really needed until pass 2, but again it is FAR storage.
            * Although we will cope with a later change in dither_mode,
            * we do not promise to honor max_memory_to_use if dither_mode changes.
            */
            if (cinfo.m_dither_mode == J_DITHER_MODE.JDITHER_FS)
            {
                m_fserrors = new short[(cinfo.m_output_width + 2) * 3];

                /* Might as well create the error-limiting table too. */
                init_error_limit();
            }
        }
예제 #59
0
 public arith_entropy_decoder(jpeg_decompress_struct cinfo)
 {
     cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL);
 }
예제 #60
0
        public jpeg_inverse_dct(jpeg_decompress_struct cinfo)
        {
            m_cinfo = cinfo;

            m_dctTables = new multiplier_table[cinfo.m_num_components];
            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                /* Allocate and pre-zero a multiplier table for each component */
                m_dctTables[ci] = new multiplier_table();

                /* Mark multiplier table not yet set up for any method */
                m_cur_method[ci] = -1;
            }
        }