Exemplo n.º 1
0
        private int m_next_row;                           /* index of next row to fill/empty in strip */

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

            /* Create the quantization buffer, if needed */
            if (cinfo.quantizeColors)
            {
                /* 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_maxVSampleFactor;

                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 = JpegCommonStruct.CreateSamplesArray(
                        cinfo.outputWidth * cinfo.outColorComponents,
                        JpegUtils.jround_up(cinfo.outputHeight, m_strip_height));
                    m_whole_image.ErrorProcessor = cinfo;
                }
                else
                {
                    /* One-pass color quantization: just make a strip buffer. */
                    m_buffer = JpegCommonStruct.AllocJpegSamples(
                        cinfo.outputWidth * cinfo.outColorComponents, m_strip_height);
                }
            }
        }
Exemplo n.º 2
0
        private int m_iMCU_row_ctr;    /* counts iMCU rows to detect image top/bot */

        public JpegDMainController(JpegDecompressStruct cinfo)
        {
            m_cinfo = cinfo;

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

            if (cinfo.m_upsample.NeedContextRows())
            {
                if (cinfo.min_DCT_v_scaled_size < 2) /* unsupported, see comments above */
                {
                    cinfo.ErrExit(JMessageCode.JERR_NOTIMPL);
                }

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

            for (var ci = 0; ci < cinfo.numComponents; ci++)
            {
                /* height of a row group of component */
                var rgroup = (cinfo.CompInfo[ci].V_samp_factor * cinfo.CompInfo[ci].DCT_v_scaled_size) / cinfo.min_DCT_v_scaled_size;

                m_buffer[ci] = JpegCommonStruct.AllocJpegSamples(
                    cinfo.CompInfo[ci].Width_in_blocks * cinfo.CompInfo[ci].DCT_h_scaled_size,
                    rgroup * ngroups);
            }
        }
Exemplo n.º 3
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 My1PassCQuantizer(JpegDecompressStruct 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.outColorComponents > MAX_Q_COMPS)
            {
                cinfo.ErrExit(JMessageCode.JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
            }

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

            /* Create the colormap and color index table. */
            CreateColormap();
            CreateColorIndex();

            /* 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.ditherMode == JDitherMode.JDITHER_FS)
            {
                AllocFsWorkspace();
            }
        }
Exemplo n.º 4
0
        private int m_rows_to_go;             /* counts rows remaining in image */

        public MyMergedUpSampler(JpegDecompressStruct cinfo)
        {
            m_cinfo             = cinfo;
            m_need_context_rows = false;

            m_out_row_width = cinfo.outputWidth * cinfo.outColorComponents;

            if (cinfo.m_maxVSampleFactor == 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.jpegColorSpace == JColorSpace.JCS_BG_YCC)
            {
                BuildBgYccRgbTable();
            }
            else
            {
                BuildYccRgbTable();
            }
        }
Exemplo n.º 5
0
        public JpegDCoefController(JpegDecompressStruct 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 (var ci = 0; ci < cinfo.numComponents; ci++)
                {
                    m_whole_image[ci] = JpegCommonStruct.CreateBlocksArray(
                        JpegUtils.jround_up(cinfo.CompInfo[ci].Width_in_blocks, cinfo.CompInfo[ci].H_samp_factor),
                        JpegUtils.jround_up(cinfo.CompInfo[ci].height_in_blocks, cinfo.CompInfo[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 (var 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 */
            }
        }
Exemplo n.º 6
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 JpegInputController(JpegDecompressStruct 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 = 1;
        }
Exemplo n.º 7
0
 public ArithEntropyDecoder(JpegDecompressStruct cinfo)
 {
     cinfo.ErrExit(JMessageCode.JERR_NOTIMPL);
 }
Exemplo n.º 8
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="JpegDecompressStruct"/></param>
        /// <param name="desired">The desired</param>
        /// <returns><c>false</c> if suspension is required.</returns>
        /// <remarks><para>
        /// 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/>
        /// </para>
        /// <para>
        /// 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/>
        /// </para>
        /// <para>
        /// 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/>
        /// </para>
        /// <para>
        /// 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/>
        /// </para>
        /// <para>
        /// #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.
        /// </para></remarks>
        public virtual bool ReSyncToRestart(JpegDecompressStruct cinfo, int desired)
        {
            if (cinfo is null)
            {
                throw new System.ArgumentNullException(nameof(cinfo));
            }
            /* Always put up a warning. */
            cinfo.WarnMS(JMessageCode.JWRN_MUST_RESYNC, cinfo.m_unreadMarker, desired);

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

                cinfo.TraceMS(4, JMessageCode.JTRC_RECOVERY_ACTION, cinfo.m_unreadMarker, action);

                switch (action)
                {
                case 1:
                    /* Discard marker and let entropy decoder resume processing. */
                    cinfo.m_unreadMarker = 0;
                    return(true);

                case 2:
                    /* Scan to the next marker, and repeat the decision loop. */
                    if (!cinfo.m_marker.NextMarker())
                    {
                        return(false);
                    }

                    break;

                case 3:
                    /* Return without advancing past this marker. */
                    /* Entropy decoder will be forced to process an empty segment. */
                    return(true);
                }
            }
        }
Exemplo n.º 9
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 MySourceManager(JpegDecompressStruct cinfo)
        {
            m_cinfo  = cinfo;
            m_buffer = new byte[INPUT_BUF_SIZE];
        }
Exemplo n.º 10
0
 public JpegDecompMaster(JpegDecompressStruct cinfo)
 {
     m_cinfo = cinfo;
     MasterSelection();
 }
Exemplo n.º 11
0
        private int[] rgb_y_tab;        /* => table for RGB to Y conversion */

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

            /* Make sure num_components agrees with jpeg_color_space */
            switch (cinfo.jpegColorSpace)
            {
            case JColorSpace.JCS_GRAYSCALE:
                if (cinfo.numComponents != 1)
                {
                    cinfo.ErrExit(JMessageCode.JERR_BAD_J_COLORSPACE);
                }

                break;

            case JColorSpace.JCS_RGB:
            case JColorSpace.JCS_YCbCr:
            case JColorSpace.JCS_BG_RGB:
            case JColorSpace.JCS_BG_YCC:
                if (cinfo.numComponents != 3)
                {
                    cinfo.ErrExit(JMessageCode.JERR_BAD_J_COLORSPACE);
                }

                break;

            case JColorSpace.JCS_CMYK:
            case JColorSpace.JCS_YCCK:
                if (cinfo.numComponents != 4)
                {
                    cinfo.ErrExit(JMessageCode.JERR_BAD_J_COLORSPACE);
                }

                break;

            case JColorSpace.JCS_NCHANNEL:
                if (cinfo.numComponents < 1)
                {
                    cinfo.ErrExit(JMessageCode.JERR_BAD_J_COLORSPACE);
                }

                break;

            default:
                /* JCS_UNKNOWN can be anything */
                if (cinfo.numComponents < 1)
                {
                    cinfo.ErrExit(JMessageCode.JERR_BAD_J_COLORSPACE);
                }

                break;
            }

            /* Support color transform only for RGB colorspaces */
            if (cinfo.color_transform != JColorTransform.JCT_NONE &&
                cinfo.jpegColorSpace != JColorSpace.JCS_RGB &&
                cinfo.jpegColorSpace != JColorSpace.JCS_BG_RGB)
            {
                cinfo.ErrExit(JMessageCode.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.outColorSpace)
            {
            case JColorSpace.JCS_GRAYSCALE:
                cinfo.outColorComponents = 1;
                switch (cinfo.jpegColorSpace)
                {
                case JColorSpace.JCS_GRAYSCALE:
                case JColorSpace.JCS_YCbCr:
                case JColorSpace.JCS_BG_YCC:
                    m_converter = GrayscaleConvert;
                    /* For color->grayscale conversion, only the Y (0) component is needed */
                    for (var ci = 1; ci < cinfo.numComponents; ci++)
                    {
                        cinfo.CompInfo[ci].component_needed = false;
                    }

                    break;

                case JColorSpace.JCS_RGB:
                    switch (cinfo.color_transform)
                    {
                    case JColorTransform.JCT_NONE:
                        m_converter = RgbGrayConvert;
                        break;

                    case JColorTransform.JCT_SUBTRACT_GREEN:
                        m_converter = Rgb1GrayConvert;
                        break;

                    default:
                        cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                        break;
                    }

                    BuildRgbYTable();
                    break;

                default:
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                    break;
                }
                break;

            case JColorSpace.JCS_RGB:
                cinfo.outColorComponents = JpegConstants.RGB_PIXELSIZE;
                switch (cinfo.jpegColorSpace)
                {
                case JColorSpace.JCS_GRAYSCALE:
                    m_converter = GrayRgbConvert;
                    break;

                case JColorSpace.JCS_YCbCr:
                    m_converter = YccRgbConvert;
                    BuildYccRgbTable();
                    break;

                case JColorSpace.JCS_BG_YCC:
                    m_converter = YccRgbConvert;
                    BuildBgYccRgbTable();
                    break;

                case JColorSpace.JCS_RGB:
                    switch (cinfo.color_transform)
                    {
                    case JColorTransform.JCT_NONE:
                        m_converter = RgbConvert;
                        break;

                    case JColorTransform.JCT_SUBTRACT_GREEN:
                        m_converter = Rgb1RgbConvert;
                        break;

                    default:
                        cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                        break;
                    }
                    break;

                case JColorSpace.JCS_CMYK:
                    m_converter = CmykRgbConvert;
                    break;

                case JColorSpace.JCS_YCCK:
                    m_converter = YcckRgbConvert;
                    BuildYccRgbTable();
                    break;

                default:
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                    break;
                }
                break;

            case JColorSpace.JCS_BG_RGB:
                cinfo.outColorComponents = JpegConstants.RGB_PIXELSIZE;
                if (cinfo.jpegColorSpace == JColorSpace.JCS_BG_RGB)
                {
                    switch (cinfo.color_transform)
                    {
                    case JColorTransform.JCT_NONE:
                        m_converter = RgbConvert;
                        break;

                    case JColorTransform.JCT_SUBTRACT_GREEN:
                        m_converter = Rgb1RgbConvert;
                        break;

                    default:
                        cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                        break;
                    }
                }
                else
                {
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case JColorSpace.JCS_CMYK:
                cinfo.outColorComponents = 4;
                switch (cinfo.jpegColorSpace)
                {
                case JColorSpace.JCS_YCCK:
                    m_converter = YcckCmykConvert;
                    BuildYccRgbTable();
                    break;

                case JColorSpace.JCS_CMYK:
                    m_converter = NullConvert;
                    break;

                default:
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                    break;
                }
                break;

            case JColorSpace.JCS_NCHANNEL:
                if (cinfo.jpegColorSpace == JColorSpace.JCS_NCHANNEL)
                {
                    m_converter = NullConvert;
                }
                else
                {
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                }

                break;

            default:
                /* Permit null conversion to same output space */
                if (cinfo.outColorSpace == cinfo.jpegColorSpace)
                {
                    cinfo.outColorComponents = cinfo.numComponents;
                    m_converter = NullConvert;
                }
                else
                {
                    /* unsupported non-null conversion */
                    cinfo.ErrExit(JMessageCode.JERR_CONVERSION_NOTIMPL);
                }
                break;
            }

            if (cinfo.quantizeColors)
            {
                cinfo.outputComponents = 1; /* single colormapped output component */
            }
            else
            {
                cinfo.outputComponents = cinfo.outColorComponents;
            }
        }
Exemplo n.º 12
0
        public MyUpSampler(JpegDecompressStruct 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(JMessageCode.JERR_CCIR601_NOTIMPL);
            }

            /* Verify we can handle the sampling factors, select per-component methods,
             * and create storage as needed.
             */
            for (var ci = 0; ci < cinfo.numComponents; ci++)
            {
                var componentInfo = cinfo.CompInfo[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.
                 */
                var h_in_group  = (componentInfo.H_samp_factor * componentInfo.DCT_h_scaled_size) / cinfo.min_DCT_h_scaled_size;
                var v_in_group  = (componentInfo.V_samp_factor * componentInfo.DCT_v_scaled_size) / cinfo.min_DCT_v_scaled_size;
                var h_out_group = cinfo.m_max_h_samp_factor;
                var v_out_group = cinfo.m_maxVSampleFactor;

                /* save for use later */
                m_rowgroup_height[ci] = v_in_group;

                if (!componentInfo.component_needed)
                {
                    /* Don't bother to upsample an uninteresting component. */
                    m_upsampleMethods[ci] = ComponentUpsampler.noop_upsampler;
                    continue;           /* don't need to allocate buffer */
                }

                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;
                    continue;           /* don't need to allocate buffer */
                }

                if (h_in_group * 2 == h_out_group && v_in_group == v_out_group)
                {
                    /* Special case for 2h1v upsampling */
                    m_upsampleMethods[ci] = ComponentUpsampler.h2v1_upsampler;
                }
                else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group)
                {
                    /* Special case for 2h2v upsampling */
                    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(JMessageCode.JERR_FRACT_SAMPLE_NOTIMPL);
                }

                var cb = new ComponentBuffer();
                cb.SetBuffer(JpegCommonStruct.AllocJpegSamples(JpegUtils.jround_up(cinfo.outputWidth,
                                                                                   cinfo.m_max_h_samp_factor), cinfo.m_maxVSampleFactor), null, 0);

                m_color_buf[ci] = cb;
            }
        }