public override bool encode_mcu(JBLOCK[][] MCU_data)
        {
            if (m_gather_statistics)
                return encode_mcu_gather(MCU_data);

            return encode_mcu_huff(MCU_data);
        }
Example #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 */
            }
        }
        public my_c_coef_controller(jpeg_compress_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. */
                for (int ci = 0; ci < cinfo.m_num_components; ci++)
                {
                    m_whole_image[ci] = jpeg_common_struct.CreateBlocksArray(
                        JpegUtils.jround_up(cinfo.Component_info[ci].Width_in_blocks, cinfo.Component_info[ci].H_samp_factor),
                        JpegUtils.jround_up(cinfo.Component_info[ci].height_in_blocks, cinfo.Component_info[ci].V_samp_factor));
                    m_whole_image[ci].ErrorProcessor = cinfo;
                }
            }
            else
            {
                /* We only need a single-MCU buffer. */
                JBLOCK[] buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU];
                for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
                    buffer[i] = new JBLOCK();

                for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
                {
                    m_MCU_buffer[i] = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU - i];
                    for (int j = i; j < JpegConstants.C_MAX_BLOCKS_IN_MCU; j++)
                        m_MCU_buffer[i][j - i] = buffer[j];
                }

                /* flag for no virtual arrays */
                m_whole_image[0] = null;
            }
        }
Example #4
0
        /// <summary>
        /// Process some data in subsequent passes of a multi-pass case.
        /// We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        /// per call, ie, v_samp_factor block rows for each component in the scan.
        /// The data is obtained from the virtual arrays and fed to the entropy coder.
        /// Returns true if the iMCU row is completed, false if suspended.
        /// </summary>
        private bool compressOutput()
        {
            /* Align the virtual buffers for the components used in this scan.
             */
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_iMCU_row_num * componentInfo.V_samp_factor, componentInfo.V_samp_factor);
            }

            /* Loop to process one whole iMCU row */
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_mcu_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            for (int xindex = 0; xindex < componentInfo.MCU_width; xindex++)
                            {
                                int bufLength = buffer[ci][yindex + yoffset].Length;
                                int start     = start_col + xindex;
                                m_MCU_buffer[blkn] = new JBLOCK[bufLength - start];
                                for (int j = start; j < bufLength; j++)
                                {
                                    m_MCU_buffer[blkn][j - start] = buffer[ci][yindex + yoffset][j];
                                }

                                blkn++;
                            }
                        }
                    }

                    /* Try to write the MCU. */
                    if (!m_cinfo.m_entropy.encode_mcu(m_MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_mcu_ctr         = MCU_col_num;
                        return(false);
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_mcu_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_iMCU_row_num++;
            start_iMCU_row();
            return(true);
        }
 private byte[] Hash(JBLOCK block, int[] group)
 {
     using (var ms = new MemoryStream())
         using (var sw = new BinaryWriter(ms))
         {
             group.Select(i => block[i]).ToList().ForEach(sw.Write);
             sw.Flush();
             ms.Seek(0, SeekOrigin.Begin);
             return(_md5.ComputeHash(ms).Take(BytesPerGroup).ToArray());
         }
 }
        private void EncodeGroup(JBLOCK block, int[] @group, byte[] data)
        {
            var deviation = 1;

            while (!Go(block, @group, data, 0, deviation))
            {
                deviation++;
                Console.Out.WriteLine("deviation = {0}", deviation);
            }

            Console.Out.WriteLine("block encrypted");
        }
        private byte[] DecodeBlock(JBLOCK block)
        {
            using (var ms = new MemoryStream())
            {
                foreach (var @group in Groups)
                {
                    var h = DecodeGroup(block, @group);
                    ms.Write(h, 0, h.Length);
                }

                return(ms.GetBuffer().Take(BytesPerBlock).ToArray());
            }
        }
        private void EncodeBlock(JBLOCK block, byte[] data)
        {
            for (var i = 0; i < Groups.Length; i++)
            {
                var currentGroupData = data.Skip(i * BytesPerGroup).Take(BytesPerGroup).ToArray();

                if (UseOldEncoder)
                {
                    EncodeGroupOld(block, Groups[i], currentGroupData);
                }
                else
                {
                    EncodeGroup(block, Groups[i], currentGroupData);
                }
            }
        }
        private void EncodeGroupOld(JBLOCK block, int[] @group, byte[] data)
        {
            var tries = 0;

            while (!Hash(block, group).SequenceEqual(data))
            {
                var index = @group[_random.Next(@group.Length)];
                block[index] += _random.Next(2) == 0 ? (short)1 : (short)-1;

                if (tries++ > 10000000)
                {
                    throw new Exception("Max tries reached");
                }
            }

            Console.Out.WriteLine("block encrypted");
        }
        /// <summary>
        /// Initialize coefficient buffer controller.
        /// 
        /// Each passed coefficient array must be the right size for that
        /// coefficient: width_in_blocks wide and height_in_blocks high,
        /// with unit height at least v_samp_factor.
        /// </summary>
        public my_trans_c_coef_controller(jpeg_compress_struct cinfo, jvirt_array<JBLOCK>[] coef_arrays)
        {
            m_cinfo = cinfo;

            /* Save pointer to virtual arrays */
            m_whole_image = coef_arrays;

            /* Allocate and pre-zero space for dummy DCT blocks. */
            JBLOCK[] buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU];
            for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
                buffer[i] = new JBLOCK();

            for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
            {
                m_dummy_buffer[i] = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU - i];
                for (int j = i; j < JpegConstants.C_MAX_BLOCKS_IN_MCU; j++)
                    m_dummy_buffer[i][j - i] = buffer[j];
            }
        }
        private bool Go(JBLOCK block, int[] @group, byte[] target, int pos, int deviation)
        {
            if (pos == @group.Length)
            {
                return(Hash(block, @group).SequenceEqual(target));
            }

            for (var i = -deviation; i <= deviation; i++)
            {
                block[@group[pos]] += (short)i;

                if (Go(block, @group, target, pos + 1, deviation - Math.Abs(i)))
                {
                    return(true);
                }

                block[@group[pos]] -= (short)i;
            }

            return(false);
        }
Example #12
0
        public my_c_coef_controller(jpeg_compress_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. */
                for (int ci = 0; ci < cinfo.m_num_components; ci++)
                {
                    m_whole_image[ci] = jpeg_common_struct.CreateBlocksArray(
                        JpegUtils.jround_up(cinfo.Component_info[ci].Width_in_blocks, cinfo.Component_info[ci].H_samp_factor),
                        JpegUtils.jround_up(cinfo.Component_info[ci].height_in_blocks, cinfo.Component_info[ci].V_samp_factor));
                    m_whole_image[ci].ErrorProcessor = cinfo;
                }
            }
            else
            {
                /* We only need a single-MCU buffer. */
                JBLOCK[] buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU];
                for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
                {
                    buffer[i] = new JBLOCK();
                }

                for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
                {
                    m_MCU_buffer[i] = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU - i];
                    for (int j = i; j < JpegConstants.C_MAX_BLOCKS_IN_MCU; j++)
                    {
                        m_MCU_buffer[i][j - i] = buffer[j];
                    }
                }

                /* flag for no virtual arrays */
                m_whole_image[0] = null;
            }
        }
Example #13
0
        /// <summary>
        /// Initialize coefficient buffer controller.
        ///
        /// Each passed coefficient array must be the right size for that
        /// coefficient: width_in_blocks wide and height_in_blocks high,
        /// with unit height at least v_samp_factor.
        /// </summary>
        public my_trans_c_coef_controller(jpeg_compress_struct cinfo, jvirt_array <JBLOCK>[] coef_arrays)
        {
            m_cinfo = cinfo;

            /* Save pointer to virtual arrays */
            m_whole_image = coef_arrays;

            /* Allocate and pre-zero space for dummy DCT blocks. */
            JBLOCK[] buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU];
            for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
            {
                buffer[i] = new JBLOCK();
            }

            for (int i = 0; i < JpegConstants.C_MAX_BLOCKS_IN_MCU; i++)
            {
                m_dummy_buffer[i] = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU - i];
                for (int j = i; j < JpegConstants.C_MAX_BLOCKS_IN_MCU; j++)
                {
                    m_dummy_buffer[i][j - i] = buffer[j];
                }
            }
        }
        /// <summary>
        /// Decode and return one MCU's worth of Huffman-compressed coefficients.
        /// The coefficients are reordered from zigzag order into natural array order,
        /// but are not dequantized.
        /// 
        /// The i'th block of the MCU is stored into the block pointed to by
        /// MCU_data[i].  WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
        /// (Wholesale zeroing is usually a little faster than retail...)
        /// 
        /// Returns false if data source requested suspension.  In that case no
        /// changes have been made to permanent state.  (Exception: some output
        /// coefficients may already have been assigned.  This is harmless for
        /// this module, since we'll just re-assign them on the next call.)
        /// </summary>
        public override bool decode_mcu(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */

                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_dc_cur_tbls[blkn], ref get_buffer, ref bits_left))
                        return false;

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                            return false;

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    if (m_dc_needed[blkn])
                    {
                        /* Convert DC difference to actual value, update last_dc_val */
                        int ci = m_cinfo.m_MCU_membership[blkn];
                        s += state.last_dc_val[ci];
                        state.last_dc_val[ci] = s;

                        /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
                        MCU_data[blkn][0] = (short) s;
                    }

                    if (m_ac_needed[blkn])
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* Since zeroes are skipped, output area must be cleared beforehand */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                                return false;

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                    return false;
                                r = GET_BITS(s, get_buffer, ref bits_left);
                                s = HUFF_EXTEND(r, s);

                                /* Output coefficient in natural (dezigzagged) order.
                                   * Note: the extra entries in jpeg_natural_order[] will save us
                                   * if k >= DCTSIZE2, which could happen if the data is corrupted.
                                   */
                                MCU_data[blkn][JpegUtils.jpeg_natural_order[k]] = (short) s;
                            }
                            else
                            {
                                if (r != 15)
                                    break;

                                k += 15;
                            }
                        }
                    }
                    else
                    {
                        /* Section F.2.2.2: decode the AC coefficients */
                        /* In this path we just discard the values */
                        for (int k = 1; k < JpegConstants.DCTSIZE2; k++)
                        {
                            if (!HUFF_DECODE(out s, ref br_state, m_ac_cur_tbls[blkn], ref get_buffer, ref bits_left))
                                return false;

                            int r = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                    return false;

                                DROP_BITS(s, ref bits_left);
                            }
                            else
                            {
                                if (r != 15)
                                    break;

                                k += 15;
                            }
                        }
                    }
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
        /// <summary>
        /// Trial-encode one MCU's worth of Huffman-compressed coefficients.
        /// No data is actually output, so no suspension return is possible.
        /// </summary>
        private bool encode_mcu_gather(JBLOCK[][] MCU_data)
        {
            /* Take care of restart intervals if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    /* Re-initialize DC predictions to 0 */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                        m_saved.last_dc_val[ci] = 0;

                    /* Update restart state */
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                }

                m_restarts_to_go--;
            }

            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                int ci = m_cinfo.m_MCU_membership[blkn];
                htest_one_block(MCU_data[blkn][0].data, m_saved.last_dc_val[ci],
                    m_dc_count_ptrs[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no],
                    m_ac_count_ptrs[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no]);
                m_saved.last_dc_val[ci] = MCU_data[blkn][0][0];
            }

            return true;
        }
 /// <summary>
 /// MCU decoding for AC successive approximation refinement scan.
 /// </summary>
 private static void undo_decode_mcu_AC_refine(JBLOCK[] block, int[] newnz_pos, int num_newnz)
 {
     /* Re-zero any output coefficients that we made newly nonzero */
     while (num_newnz > 0)
         block[0][newnz_pos[--num_newnz]] = 0;
 }
Example #17
0
        /// <summary>
        /// Variant of decompress_data for use when doing block smoothing.
        /// </summary>
        private ReadResult decompress_smooth_data(ComponentBuffer[] output_buf)
        {
            /* Force some input to be done if we are getting ahead of the input. */
            while (m_cinfo.m_input_scan_number <= m_cinfo.m_output_scan_number && !m_cinfo.m_inputctl.EOIReached())
            {
                if (m_cinfo.m_input_scan_number == m_cinfo.m_output_scan_number)
                {
                    /* If input is working on current scan, we ordinarily want it to
                     * have completed the current row.  But if input scan is DC,
                     * we want it to keep one row ahead so that next block row's DC
                     * values are up to date.
                     */
                    int delta = (m_cinfo.m_Ss == 0) ? 1 : 0;
                    if (m_cinfo.m_input_iMCU_row > m_cinfo.m_output_iMCU_row + delta)
                        break;
                }

                if (m_cinfo.m_inputctl.consume_input() == ReadResult.JPEG_SUSPENDED)
                    return ReadResult.JPEG_SUSPENDED;
            }

            int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;

            /* OK, output from the virtual arrays. */
            for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[ci];

                /* Don't bother to IDCT an uninteresting component. */
                if (!componentInfo.component_needed)
                    continue;

                int block_rows;
                int access_rows;
                bool last_row;
                /* Count non-dummy DCT block rows in this iMCU row. */
                if (m_cinfo.m_output_iMCU_row < last_iMCU_row)
                {
                    block_rows = componentInfo.V_samp_factor;
                    access_rows = block_rows * 2; /* this and next iMCU row */
                    last_row = false;
                }
                else
                {
                    /* NB: can't use last_row_height here; it is input-side-dependent! */
                    block_rows = componentInfo.height_in_blocks % componentInfo.V_samp_factor;
                    if (block_rows == 0)
                        block_rows = componentInfo.V_samp_factor;
                    access_rows = block_rows; /* this iMCU row only */
                    last_row = true;
                }

                /* Align the virtual buffer for this component. */
                JBLOCK[][] buffer = null;
                bool first_row;
                int bufferRowOffset = 0;
                if (m_cinfo.m_output_iMCU_row > 0)
                {
                    access_rows += componentInfo.V_samp_factor; /* prior iMCU row too */
                    buffer = m_whole_image[ci].Access((m_cinfo.m_output_iMCU_row - 1) * componentInfo.V_samp_factor, access_rows);
                    bufferRowOffset = componentInfo.V_samp_factor; /* point to current iMCU row */
                    first_row = false;
                }
                else
                {
                    buffer = m_whole_image[ci].Access(0, access_rows);
                    first_row = true;
                }

                /* Fetch component-dependent info */
                int coefBitsOffset = ci * SAVED_COEFS;
                int Q00 = componentInfo.quant_table.quantval[0];
                int Q01 = componentInfo.quant_table.quantval[Q01_POS];
                int Q10 = componentInfo.quant_table.quantval[Q10_POS];
                int Q20 = componentInfo.quant_table.quantval[Q20_POS];
                int Q11 = componentInfo.quant_table.quantval[Q11_POS];
                int Q02 = componentInfo.quant_table.quantval[Q02_POS];
                int outputIndex = ci;

                /* Loop over all DCT blocks to be processed. */
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    int bufferIndex = bufferRowOffset + block_row;

                    int prev_block_row = 0;
                    if (first_row && block_row == 0)
                        prev_block_row = bufferIndex;
                    else
                        prev_block_row = bufferIndex - 1;

                    int next_block_row = 0;
                    if (last_row && block_row == block_rows - 1)
                        next_block_row = bufferIndex;
                    else
                        next_block_row = bufferIndex + 1;

                    /* We fetch the surrounding DC values using a sliding-register approach.
                     * Initialize all nine here so as to do the right thing on narrow pics.
                     */
                    int DC1 = buffer[prev_block_row][0][0];
                    int DC2 = DC1;
                    int DC3 = DC1;

                    int DC4 = buffer[bufferIndex][0][0];
                    int DC5 = DC4;
                    int DC6 = DC4;

                    int DC7 = buffer[next_block_row][0][0];
                    int DC8 = DC7;
                    int DC9 = DC7;

                    int output_col = 0;
                    int last_block_column = componentInfo.Width_in_blocks - 1;
                    for (int block_num = 0; block_num <= last_block_column; block_num++)
                    {
                        /* Fetch current DCT block into workspace so we can modify it. */
                        JBLOCK workspace = new JBLOCK();
                        Buffer.BlockCopy(buffer[bufferIndex][0].data, 0, workspace.data, 0, workspace.data.Length * sizeof(short));

                        /* Update DC values */
                        if (block_num < last_block_column)
                        {
                            DC3 = buffer[prev_block_row][1][0];
                            DC6 = buffer[bufferIndex][1][0];
                            DC9 = buffer[next_block_row][1][0];
                        }

                        /* Compute coefficient estimates per K.8.
                         * An estimate is applied only if coefficient is still zero,
                         * and is not known to be fully accurate.
                         */
                        /* AC01 */
                        int Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 1];
                        if (Al != 0 && workspace[1] == 0)
                        {
                            int pred;
                            int num = 36 * Q00 * (DC4 - DC6);
                            if (num >= 0)
                            {
                                pred = ((Q01 << 7) + num) / (Q01 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                            }
                            else
                            {
                                pred = ((Q01 << 7) - num) / (Q01 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                                pred = -pred;
                            }
                            workspace[1] = (short) pred;
                        }

                        /* AC10 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 2];
                        if (Al != 0 && workspace[8] == 0)
                        {
                            int pred;
                            int num = 36 * Q00 * (DC2 - DC8);
                            if (num >= 0)
                            {
                                pred = ((Q10 << 7) + num) / (Q10 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                            }
                            else
                            {
                                pred = ((Q10 << 7) - num) / (Q10 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                                pred = -pred;
                            }
                            workspace[8] = (short) pred;
                        }

                        /* AC20 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 3];
                        if (Al != 0 && workspace[16] == 0)
                        {
                            int pred;
                            int num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
                            if (num >= 0)
                            {
                                pred = ((Q20 << 7) + num) / (Q20 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                            }
                            else
                            {
                                pred = ((Q20 << 7) - num) / (Q20 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                                pred = -pred;
                            }
                            workspace[16] = (short) pred;
                        }

                        /* AC11 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 4];
                        if (Al != 0 && workspace[9] == 0)
                        {
                            int pred;
                            int num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
                            if (num >= 0)
                            {
                                pred = ((Q11 << 7) + num) / (Q11 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                            }
                            else
                            {
                                pred = ((Q11 << 7) - num) / (Q11 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                                pred = -pred;
                            }
                            workspace[9] = (short) pred;
                        }

                        /* AC02 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 5];
                        if (Al != 0 && workspace[2] == 0)
                        {
                            int pred;
                            int num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
                            if (num >= 0)
                            {
                                pred = ((Q02 << 7) + num) / (Q02 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                            }
                            else
                            {
                                pred = ((Q02 << 7) - num) / (Q02 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                    pred = (1 << Al) - 1;
                                pred = -pred;
                            }
                            workspace[2] = (short) pred;
                        }

                        /* OK, do the IDCT */
                        m_cinfo.m_idct.inverse(componentInfo.Component_index, workspace.data, output_buf[outputIndex], 0, output_col);

                        /* Advance for next column */
                        DC1 = DC2;
                        DC2 = DC3;
                        DC4 = DC5;
                        DC5 = DC6;
                        DC7 = DC8;
                        DC8 = DC9;

                        bufferIndex++;
                        prev_block_row++;
                        next_block_row++;

                        output_col += componentInfo.DCT_scaled_size;
                    }

                    outputIndex += componentInfo.DCT_scaled_size;
                }
            }

            m_cinfo.m_output_iMCU_row++;
            if (m_cinfo.m_output_iMCU_row < m_cinfo.m_total_iMCU_rows)
                return ReadResult.JPEG_ROW_COMPLETED;

            return ReadResult.JPEG_SCAN_COMPLETED;
        }
Example #18
0
        // This version is used for integer DCT implementations.
        private void forwardDCTImpl(int quant_tbl_no, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            int[] workspace = new int [JpegConstants.DCTSIZE2];    /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += JpegConstants.DCTSIZE)
            {
                /* Load data into workspace, applying unsigned->signed conversion */
                int workspaceIndex = 0;
                for (int elemr = 0; elemr < JpegConstants.DCTSIZE; elemr++)
                {
                    for (int column = 0; column < JpegConstants.DCTSIZE; column++)
                    {
                        workspace[workspaceIndex] = (int)sample_data[start_row + elemr][start_col + column] - JpegConstants.CENTERJSAMPLE;
                        workspaceIndex++;
                    }
                }

                /* Perform the DCT */
                if (m_useSlowMethod)
                    jpeg_fdct_islow(workspace);
                else
                    jpeg_fdct_ifast(workspace);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    int qval = m_divisors[quant_tbl_no][i];
                    int temp = workspace[i];

                    if (temp < 0)
                    {
                        temp = -temp;
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;

                        temp = -temp;
                    }
                    else
                    {
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;
                    }

                    coef_blocks[bi][i] = (short) temp;
                }
            }
        }
Example #19
0
 /// <summary>
 /// Perform forward DCT on one or more blocks of a component.
 /// 
 /// The input samples are taken from the sample_data[] array starting at
 /// position start_row/start_col, and moving to the right for any additional
 /// blocks. The quantized coefficients are returned in coef_blocks[].
 /// </summary>
 public virtual void forward_DCT(int quant_tbl_no, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
 {
     if (m_useFloatMethod)
         forwardDCTFloatImpl(quant_tbl_no, sample_data, coef_blocks, start_row, start_col, num_blocks);
     else
         forwardDCTImpl(quant_tbl_no, sample_data, coef_blocks, start_row, start_col, num_blocks);
 }
        /// <summary>
        /// MCU decoding for DC successive approximation refinement scan.
        /// Note: we assume such scans can be multi-component, although the spec
        /// is not very clear on the point.
        /// </summary>
        private bool decode_mcu_DC_refine(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* Not worth the cycles to check insufficient_data here,
             * since we will not change the data anyway if we read zeroes.
             */

            /* Load up working state */
            int get_buffer;
            int bits_left;
            bitread_working_state br_state = new bitread_working_state();
            BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);

            /* Outer loop handles each block in the MCU */

            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                /* Encoded data is simply the next bit of the two's-complement DC value */
                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                    return false;

                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                {
                    /* 1 in the bit position being coded */
                    MCU_data[blkn][0] = (short)((ushort)MCU_data[blkn][0] | (ushort)(1 << m_cinfo.m_Al));
                }

                /* Note: since we use |=, repeating the assignment later is safe */
            }

            /* Completed MCU, so update state */
            BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
Example #21
0
        /// <summary>
        /// MCU encoding for AC successive approximation refinement scan.
        /// </summary>
        private bool encode_mcu_AC_refine(JBLOCK[][] MCU_data)
        {
            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                    emit_restart(m_next_restart_num);
            }

            /* Encode the MCU data block */

            /* It is convenient to make a pre-pass to determine the transformed
             * coefficients' absolute values and the EOB position.
             */
            int EOB = 0;
            int[] absvalues = new int[JpegConstants.DCTSIZE2];
            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = MCU_data[0][0][JpegUtils.jpeg_natural_order[k]];

                /* We must apply the point transform by Al.  For AC coefficients this
                 * is an integer division with rounding towards 0.  To do this portably
                 * in C, we shift after obtaining the absolute value.
                 */
                if (temp < 0)
                    temp = -temp;       /* temp is abs value of input */

                temp >>= m_cinfo.m_Al;        /* apply the point transform */
                absvalues[k] = temp;    /* save abs value for main pass */

                if (temp == 1)
                {
                    /* EOB = index of last newly-nonzero coef */
                    EOB = k;
                }
            }

            /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */

            int r = 0;          /* r = run length of zeros */
            int BR = 0;         /* BR = count of buffered bits added now */
            int bitBufferOffset = m_BE; /* Append bits to buffer */

            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = absvalues[k];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* Emit any required ZRLs, but not if they can be folded into EOB */
                while (r > 15 && k <= EOB)
                {
                    /* emit any pending EOBRUN and the BE correction bits */
                    emit_eobrun();

                    /* Emit ZRL */
                    emit_symbol(m_ac_tbl_no, 0xF0);
                    r -= 16;

                    /* Emit buffered correction bits that must be associated with ZRL */
                    emit_buffered_bits(bitBufferOffset, BR);
                    bitBufferOffset = 0;/* BE bits are gone now */
                    BR = 0;
                }

                /* If the coef was previously nonzero, it only needs a correction bit.
                 * NOTE: a straight translation of the spec's figure G.7 would suggest
                 * that we also need to test r > 15.  But if r > 15, we can only get here
                 * if k > EOB, which implies that this coefficient is not 1.
                 */
                if (temp > 1)
                {
                    /* The correction bit is the next bit of the absolute value. */
                    m_bit_buffer[bitBufferOffset + BR] = (char) (temp & 1);
                    BR++;
                    continue;
                }

                /* Emit any pending EOBRUN and the BE correction bits */
                emit_eobrun();

                /* Count/emit Huffman symbol for run length / number of bits */
                emit_symbol(m_ac_tbl_no, (r << 4) + 1);

                /* Emit output bit for newly-nonzero coef */
                temp = (MCU_data[0][0][JpegUtils.jpeg_natural_order[k]] < 0) ? 0 : 1;
                emit_bits(temp, 1);

                /* Emit buffered correction bits that must be associated with this code */
                emit_buffered_bits(bitBufferOffset, BR);
                bitBufferOffset = 0;/* BE bits are gone now */
                BR = 0;
                r = 0;          /* reset zero run length */
            }

            if (r > 0 || BR > 0)
            {
                /* If there are trailing zeroes, */
                m_EOBRUN++;      /* count an EOB */
                m_BE += BR;      /* concat my correction bits to older ones */

                /* We force out the EOB if we risk either:
                 * 1. overflow of the EOB counter;
                 * 2. overflow of the correction bit buffer during the next MCU.
                 */
                if (m_EOBRUN == 0x7FFF || m_BE > (MAX_CORR_BITS - JpegConstants.DCTSIZE2 + 1))
                    emit_eobrun();
            }

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }
                m_restarts_to_go--;
            }

            return true;
        }
Example #22
0
        public override bool encode_mcu(JBLOCK[][] MCU_data)
        {
            switch (m_MCUEncoder)
            {
                case MCUEncoder.mcu_DC_first_encoder:
                    return encode_mcu_DC_first(MCU_data);
                case MCUEncoder.mcu_AC_first_encoder:
                    return encode_mcu_AC_first(MCU_data);
                case MCUEncoder.mcu_DC_refine_encoder:
                    return encode_mcu_DC_refine(MCU_data);
                case MCUEncoder.mcu_AC_refine_encoder:
                    return encode_mcu_AC_refine(MCU_data);
            }

            m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOTIMPL);
            return false;
        }
Example #23
0
        // This version is used for floating-point DCT implementations.
        private void forwardDCTFloatImpl(jpeg_component_info compptr, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            float_DCT_method_ptr do_dct = do_float_dct[compptr.Component_index];
            float[] divisors = m_dctTables[compptr.Component_index].float_array;
            float[] workspace = new float[JpegConstants.DCTSIZE2]; /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += compptr.DCT_h_scaled_size)
            {
                /* Perform the DCT */
                do_dct(workspace, sample_data, start_row, start_col);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    /* Apply the quantization and scaling factor */
                    float temp = workspace[i] * divisors[i];

                    /* Round to nearest integer.
                     * Since C does not specify the direction of rounding for negative
                     * quotients, we have to force the dividend positive for portability.
                     * The maximum coefficient size is +-16K (for 12-bit data), so this
                     * code should work for either 16-bit or 32-bit ints.
                     */
                    coef_blocks[bi][i] = (short)((int)(temp + (float)16384.5) - 16384);
                }
            }
        }
Example #24
0
        // This version is used for integer DCT implementations.
        private void forwardDCTImpl(jpeg_component_info compptr, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            forward_DCT_method_ptr do_dct = this.do_dct[compptr.Component_index];
            int[] divisors = m_dctTables[compptr.Component_index].int_array;
            int[] workspace = new int[JpegConstants.DCTSIZE2];    /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += compptr.DCT_h_scaled_size)
            {
                /* Perform the DCT */
                do_dct(workspace, sample_data, start_row, start_col);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    int qval = divisors[i];
                    int temp = workspace[i];

                    if (temp < 0)
                    {
                        temp = -temp;
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;

                        temp = -temp;
                    }
                    else
                    {
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;
                    }

                    coef_blocks[bi][i] = (short)temp;
                }
            }
        }
        /// <summary>
        /// Process some data.
        /// We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        /// per call, ie, v_samp_factor block rows for each component in the scan.
        /// The data is obtained from the virtual arrays and fed to the entropy coder.
        /// Returns true if the iMCU row is completed, false if suspended.
        /// 
        /// NB: input_buf is ignored; it is likely to be a null pointer.
        /// </summary>
        public virtual bool compress_data(byte[][][] input_buf)
        {
            /* Align the virtual buffers for the components used in this scan. */
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_iMCU_row_num * componentInfo.V_samp_factor, componentInfo.V_samp_factor);
            }

            /* Loop to process one whole iMCU row */
            int last_MCU_col = m_cinfo.m_MCUs_per_row - 1;
            int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;
            JBLOCK[][] MCU_buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU][];
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_mcu_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        int blockcnt = (MCU_col_num < last_MCU_col) ? componentInfo.MCU_width : componentInfo.last_col_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            int xindex = 0;
                            if (m_iMCU_row_num < last_iMCU_row || yindex + yoffset < componentInfo.last_row_height)
                            {
                                /* Fill in pointers to real blocks in this row */
                                for (xindex = 0; xindex < blockcnt; xindex++)
                                {
                                    int bufLength = buffer[ci][yindex + yoffset].Length;
                                    int start = start_col + xindex;
                                    MCU_buffer[blkn] = new JBLOCK[bufLength - start];
                                    for (int j = start; j < bufLength; j++)
                                        MCU_buffer[blkn][j - start] = buffer[ci][yindex + yoffset][j];

                                    blkn++;
                                }
                            }
                            else
                            {
                                /* At bottom of image, need a whole row of dummy blocks */
                                xindex = 0;
                            }

                            /* Fill in any dummy blocks needed in this row.
                            * Dummy blocks are filled in the same way as in jccoefct.c:
                            * all zeroes in the AC entries, DC entries equal to previous
                            * block's DC value.  The init routine has already zeroed the
                            * AC entries, so we need only set the DC entries correctly.
                            */
                            for (; xindex < componentInfo.MCU_width; xindex++)
                            {
                                MCU_buffer[blkn] = m_dummy_buffer[blkn];
                                MCU_buffer[blkn][0][0] = MCU_buffer[blkn - 1][0][0];
                                blkn++;
                            }
                        }
                    }
                
                    /* Try to write the MCU. */
                    if (!m_cinfo.m_entropy.encode_mcu(MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_mcu_ctr = MCU_col_num;
                        return false;
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_mcu_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_iMCU_row_num++;
            start_iMCU_row();
            return true;
        }
        // There is always only one block per MCU
        private bool decode_mcu_AC_refine(JBLOCK[] MCU_data)
        {
            int p1 = 1 << m_cinfo.m_Al;    /* 1 in the bit position being coded */
            int m1 = -1 << m_cinfo.m_Al; /* -1 in the bit position being coded */

            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, don't modify the MCU.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* If we are forced to suspend, we must undo the assignments to any newly
                 * nonzero coefficients in the block, because otherwise we'd get confused
                 * next time about which coefficients were already nonzero.
                 * But we need not undo addition of bits to already-nonzero coefficients;
                 * instead, we can test the current bit to see if we already did it.
                 */
                int num_newnz = 0;
                int[] newnz_pos = new int[JpegConstants.DCTSIZE2];

                /* initialize coefficient loop counter to start of band */
                int k = m_cinfo.m_Ss;

                if (EOBRUN == 0)
                {
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, ref get_buffer, ref bits_left))
                        {
                            undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                            return false;
                        }

                        int r = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            if (s != 1)
                            {
                                /* size of new coef should always be 1 */
                                m_cinfo.WARNMS(J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                            }

                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return false;
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                /* newly nonzero coef is positive */
                                s = p1;
                            }
                            else
                            {
                                /* newly nonzero coef is negative */
                                s = m1;
                            }
                        }
                        else
                        {
                            if (r != 15)
                            {
                                EOBRUN = 1 << r;    /* EOBr, run length is 2^r + appended bits */
                                if (r != 0)
                                {
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                    {
                                        undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                        return false;
                                    }

                                    r = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }
                                break;      /* rest of block is handled by EOB logic */
                            }
                            /* note s = 0 for processing ZRL */
                        }
                        /* Advance over already-nonzero coefs and r still-zero coefs,
                         * appending correction bits to the nonzeroes.  A correction bit is 1
                         * if the absolute value of the coefficient must be increased.
                         */
                        do
                        {
                            int blockIndex = JpegUtils.jpeg_natural_order[k];
                            short thiscoef = MCU_data[0][blockIndex];
                            if (thiscoef != 0)
                            {
                                if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                                {
                                    undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                    return false;
                                }

                                if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                                {
                                    if ((thiscoef & p1) == 0)
                                    {
                                        /* do nothing if already set it */
                                        if (thiscoef >= 0)
                                            MCU_data[0][blockIndex] += (short)p1;
                                        else
                                            MCU_data[0][blockIndex] += (short)m1;
                                    }
                                }
                            }
                            else
                            {
                                if (--r < 0)
                                    break;      /* reached target zero coefficient */
                            }

                            k++;
                        }
                        while (k <= m_cinfo.m_Se);

                        if (s != 0)
                        {
                            int pos = JpegUtils.jpeg_natural_order[k];

                            /* Output newly nonzero coefficient */
                            MCU_data[0][pos] = (short)s;

                            /* Remember its position in case we have to suspend */
                            newnz_pos[num_newnz++] = pos;
                        }
                    }
                }

                if (EOBRUN > 0)
                {
                    /* Scan any remaining coefficient positions after the end-of-band
                     * (the last newly nonzero coefficient, if any).  Append a correction
                     * bit to each already-nonzero coefficient.  A correction bit is 1
                     * if the absolute value of the coefficient must be increased.
                     */
                    for (; k <= m_cinfo.m_Se; k++)
                    {
                        int blockIndex = JpegUtils.jpeg_natural_order[k];
                        short thiscoef = MCU_data[0][blockIndex];
                        if (thiscoef != 0)
                        {
                            if (!CHECK_BIT_BUFFER(ref br_state, 1, ref get_buffer, ref bits_left))
                            {
                                //undo_decode_mcu_AC_refine(MCU_data[0], newnz_pos, num_newnz);
                                undo_decode_mcu_AC_refine(MCU_data, newnz_pos, num_newnz);
                                return false;
                            }

                            if (GET_BITS(1, get_buffer, ref bits_left) != 0)
                            {
                                if ((thiscoef & p1) == 0)
                                {
                                    /* do nothing if already changed it */
                                    if (thiscoef >= 0)
                                        MCU_data[0][blockIndex] += (short)p1;
                                    else
                                        MCU_data[0][blockIndex] += (short)m1;
                                }
                            }
                        }
                    }

                    /* Count one block completed in EOB run */
                    EOBRUN--;
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
        /// <summary>
        /// MCU decoding for AC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_AC_first(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state.
                 * We can avoid loading/saving bitread state if in an EOB run.
                 */
                int EOBRUN = m_saved.EOBRUN; /* only part of saved state we need */

                /* There is always only one block per MCU */

                if (EOBRUN > 0)
                {
                    /* if it's a band of zeroes... */
                    /* ...process it now (we do nothing) */
                    EOBRUN--;
                }
                else
                {
                    int get_buffer;
                    int bits_left;
                    bitread_working_state br_state = new bitread_working_state();
                    BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);

                    for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
                    {
                        int s;
                        if (!HUFF_DECODE(out s, ref br_state, m_ac_derived_tbl, ref get_buffer, ref bits_left))
                            return false;

                        int r = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            k += r;

                            if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                                return false;

                            r = GET_BITS(s, get_buffer, ref bits_left);
                            s = HUFF_EXTEND(r, s);

                            /* Scale and output coefficient in natural (dezigzagged) order */
                            MCU_data[0][JpegUtils.jpeg_natural_order[k]] = (short)(s << m_cinfo.m_Al);
                        }
                        else
                        {
                            if (r == 15)
                            {
                                /* ZRL */
                                k += 15;        /* skip 15 zeroes in band */
                            }
                            else
                            {
                                /* EOBr, run length is 2^r + appended bits */
                                EOBRUN = 1 << r;
                                if (r != 0)
                                {
                                    /* EOBr, r > 0 */
                                    if (!CHECK_BIT_BUFFER(ref br_state, r, ref get_buffer, ref bits_left))
                                        return false;

                                    r = GET_BITS(r, get_buffer, ref bits_left);
                                    EOBRUN += r;
                                }

                                EOBRUN--;       /* this band is processed at this moment */
                                break;      /* force end-of-band */
                            }
                        }
                    }

                    BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                }

                /* Completed MCU, so update state */
                m_saved.EOBRUN = EOBRUN; /* only part of saved state we need */
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
Example #28
0
        /// <summary>
        /// MCU encoding for DC successive approximation refinement scan.
        /// Note: we assume such scans can be multi-component, although the spec
        /// is not very clear on the point.
        /// </summary>
        private bool encode_mcu_DC_refine(JBLOCK[][] MCU_data)
        {
            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                    emit_restart(m_next_restart_num);
            }

            /* Encode the MCU data blocks */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                /* We simply emit the Al'th bit of the DC coefficient value. */
                int temp = MCU_data[blkn][0][0];
                emit_bits(temp >> m_cinfo.m_Al, 1);
            }

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }
                m_restarts_to_go--;
            }

            return true;
        }
        /*
         * Huffman MCU decoding.
         * Each of these routines decodes and returns one MCU's worth of
         * Huffman-compressed coefficients.
         * The coefficients are reordered from zigzag order into natural array order,
         * but are not dequantized.
         *
         * The i'th block of the MCU is stored into the block pointed to by
         * MCU_data[i].  WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
         *
         * We return false if data source requested suspension.  In that case no
         * changes have been made to permanent state.  (Exception: some output
         * coefficients may already have been assigned.  This is harmless for
         * spectral selection, since we'll just re-assign them on the next call.
         * Successive approximation AC refinement has to be more careful, however.)
         */
        /// <summary>
        /// MCU decoding for DC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool decode_mcu_DC_first(JBLOCK[] MCU_data)
        {
            /* Process restart marker if needed; may have to suspend */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!process_restart())
                        return false;
                }
            }

            /* If we've run out of data, just leave the MCU set to zeroes.
             * This way, we return uniform gray for the remainder of the segment.
             */
            if (!m_insufficient_data)
            {
                /* Load up working state */
                int get_buffer;
                int bits_left;
                bitread_working_state br_state = new bitread_working_state();
                BITREAD_LOAD_STATE(m_bitstate, out get_buffer, out bits_left, ref br_state);
                savable_state state = new savable_state();
                state.Assign(m_saved);

                /* Outer loop handles each block in the MCU */
                for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
                {
                    int ci = m_cinfo.m_MCU_membership[blkn];

                    /* Decode a single block's worth of coefficients */

                    /* Section F.2.2.1: decode the DC coefficient difference */
                    int s;
                    if (!HUFF_DECODE(out s, ref br_state, m_derived_tbls[m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no], ref get_buffer, ref bits_left))
                        return false;

                    if (s != 0)
                    {
                        if (!CHECK_BIT_BUFFER(ref br_state, s, ref get_buffer, ref bits_left))
                            return false;

                        int r = GET_BITS(s, get_buffer, ref bits_left);
                        s = HUFF_EXTEND(r, s);
                    }

                    /* Convert DC difference to actual value, update last_dc_val */
                    s += state.last_dc_val[ci];
                    state.last_dc_val[ci] = s;

                    /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
                    MCU_data[blkn][0] = (short)(s << m_cinfo.m_Al);
                }

                /* Completed MCU, so update state */
                BITREAD_SAVE_STATE(ref m_bitstate, get_buffer, bits_left);
                m_saved.Assign(state);
            }

            /* Account for restart interval (no-op if not using restarts) */
            m_restarts_to_go--;

            return true;
        }
Example #30
0
        /// <summary>
        /// MCU encoding for AC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool encode_mcu_AC_first(JBLOCK[][] MCU_data)
        {
            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                    emit_restart(m_next_restart_num);
            }

            /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
            /* r = run length of zeros */
            int r = 0;
            for (int k = m_cinfo.m_Ss; k <= m_cinfo.m_Se; k++)
            {
                int temp = MCU_data[0][0][JpegUtils.jpeg_natural_order[k]];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* We must apply the point transform by Al.  For AC coefficients this
                 * is an integer division with rounding towards 0.  To do this portably
                 * in C, we shift after obtaining the absolute value; so the code is
                 * interwoven with finding the abs value (temp) and output bits (temp2).
                 */
                int temp2;
                if (temp < 0)
                {
                    temp = -temp;       /* temp is abs value of input */
                    temp >>= m_cinfo.m_Al;        /* apply the point transform */
                    /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
                    temp2 = ~temp;
                }
                else
                {
                    temp >>= m_cinfo.m_Al;        /* apply the point transform */
                    temp2 = temp;
                }

                /* Watch out for case that nonzero coef is zero after point transform */
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                /* Emit any pending EOBRUN */
                if (m_EOBRUN > 0)
                    emit_eobrun();

                /* if run length > 15, must emit special run-length-16 codes (0xF0) */
                while (r > 15)
                {
                    emit_symbol(m_ac_tbl_no, 0xF0);
                    r -= 16;
                }

                /* Find the number of bits needed for the magnitude of the coefficient */
                int nbits = 1;          /* there must be at least one 1 bit */
                while ((temp >>= 1) != 0)
                    nbits++;

                /* Check for out-of-range coefficient values */
                if (nbits > MAX_HUFFMAN_COEF_BITS)
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);

                /* Count/emit Huffman symbol for run length / number of bits */
                emit_symbol(m_ac_tbl_no, (r << 4) + nbits);

                /* Emit that number of bits of the value, if positive, */
                /* or the complement of its magnitude, if negative. */
                emit_bits(temp2, nbits);

                r = 0;          /* reset zero run length */
            }

            if (r > 0)
            {
                /* If there are trailing zeroes, */
                m_EOBRUN++;      /* count an EOB */
                if (m_EOBRUN == 0x7FFF)
                    emit_eobrun();   /* force it out to avoid overflow */
            }

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }
                m_restarts_to_go--;
            }

            return true;
        }
        /// <summary>
        /// Process some data in subsequent passes of a multi-pass case.
        /// We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        /// per call, ie, v_samp_factor block rows for each component in the scan.
        /// The data is obtained from the virtual arrays and fed to the entropy coder.
        /// Returns true if the iMCU row is completed, false if suspended.
        /// </summary>
        private bool compressOutput()
        {
            /* Align the virtual buffers for the components used in this scan.
             */
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_iMCU_row_num * componentInfo.V_samp_factor, componentInfo.V_samp_factor);
            }

            /* Loop to process one whole iMCU row */
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_mcu_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            for (int xindex = 0; xindex < componentInfo.MCU_width; xindex++)
                            {
                                int bufLength = buffer[ci][yindex + yoffset].Length;
                                int start = start_col + xindex;
                                m_MCU_buffer[blkn] = new JBLOCK[bufLength - start];
                                for (int j = start; j < bufLength; j++)
                                    m_MCU_buffer[blkn][j - start] = buffer[ci][yindex + yoffset][j];

                                blkn++;
                            }
                        }
                    }

                    /* Try to write the MCU. */
                    if (!m_cinfo.m_entropy.encode_mcu(m_MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_mcu_ctr = MCU_col_num;
                        return false;
                    }
                }
            
                /* Completed an MCU row, but perhaps not an iMCU row */
                m_mcu_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_iMCU_row_num++;
            start_iMCU_row();
            return true;
        }
Example #32
0
        /// <summary>
        /// MCU encoding for DC initial scan (either spectral selection,
        /// or first pass of successive approximation).
        /// </summary>
        private bool encode_mcu_DC_first(JBLOCK[][] MCU_data)
        {
            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                    emit_restart(m_next_restart_num);
            }

            /* Encode the MCU data blocks */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                /* Compute the DC value after the required point transform by Al.
                 * This is simply an arithmetic right shift.
                 */
                int temp2 = IRIGHT_SHIFT(MCU_data[blkn][0][0], m_cinfo.m_Al);

                /* DC differences are figured on the point-transformed values. */
                int ci = m_cinfo.m_MCU_membership[blkn];
                int temp = temp2 - m_last_dc_val[ci];
                m_last_dc_val[ci] = temp2;

                /* Encode the DC coefficient difference per section G.1.2.1 */
                temp2 = temp;
                if (temp < 0)
                {
                    /* temp is abs value of input */
                    temp = -temp;

                    /* For a negative input, want temp2 = bitwise complement of abs(input) */
                    /* This code assumes we are on a two's complement machine */
                    temp2--;
                }

                /* Find the number of bits needed for the magnitude of the coefficient */
                int nbits = 0;
                while (temp != 0)
                {
                    nbits++;
                    temp >>= 1;
                }

                /* Check for out-of-range coefficient values.
                 * Since we're encoding a difference, the range limit is twice as much.
                 */
                if (nbits > MAX_HUFFMAN_COEF_BITS + 1)
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_DCT_COEF);

                /* Count/emit the Huffman-coded symbol for the number of bits */
                emit_symbol(m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no, nbits);

                /* Emit that number of bits of the value, if positive, */
                /* or the complement of its magnitude, if negative. */
                if (nbits != 0)
                {
                    /* emit_bits rejects calls with size 0 */
                    emit_bits(temp2, nbits);
                }
            }

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }

                m_restarts_to_go--;
            }

            return true;
        }
 private byte[] DecodeGroup(JBLOCK block, int[] @group)
 {
     return(Hash(block, @group));
 }
 public abstract bool decode_mcu(JBLOCK[] MCU_data);
        /// <summary>
        /// Consume input data and store it in the full-image coefficient buffer.
        /// We read as much as one fully interleaved MCU row ("iMCU" row) per call,
        /// ie, v_samp_factor block rows for each component in the scan.
        /// </summary>
        public ReadResult consume_data()
        {
            if (m_useDummyConsumeData)
            {
                return(ReadResult.JPEG_SUSPENDED);  /* Always indicate nothing was done */
            }
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];

            /* Align the virtual buffers for the components used in this scan. */
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];

                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_cinfo.m_input_iMCU_row * componentInfo.V_samp_factor, componentInfo.V_samp_factor);

                /* Note: entropy decoder expects buffer to be zeroed,
                 * but this is handled automatically by the memory manager
                 * because we requested a pre-zeroed array.
                 */
            }

            /* Loop to process one whole iMCU row */
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_MCU_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            for (int xindex = 0; xindex < componentInfo.MCU_width; xindex++)
                            {
                                m_MCU_buffer[blkn] = buffer[ci][yindex + yoffset][start_col + xindex];
                                blkn++;
                            }
                        }
                    }

                    /* Try to fetch the MCU. */
                    if (!m_cinfo.m_entropy.decode_mcu(m_MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_MCU_ctr         = MCU_col_num;
                        return(ReadResult.JPEG_SUSPENDED);
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_MCU_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_cinfo.m_input_iMCU_row++;
            if (m_cinfo.m_input_iMCU_row < m_cinfo.m_total_iMCU_rows)
            {
                start_iMCU_row();
                return(ReadResult.JPEG_ROW_COMPLETED);
            }

            /* Completed the scan */
            m_cinfo.m_inputctl.finish_input_pass();
            return(ReadResult.JPEG_SCAN_COMPLETED);
        }
Example #36
0
        // This version is used for floating-point DCT implementations.
        private void forwardDCTFloatImpl(int quant_tbl_no, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            float[] workspace = new float [JpegConstants.DCTSIZE2]; /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += JpegConstants.DCTSIZE)
            {
                /* Load data into workspace, applying unsigned->signed conversion */
                int workspaceIndex = 0;
                for (int elemr = 0; elemr < JpegConstants.DCTSIZE; elemr++)
                {
                    for (int column = 0; column < JpegConstants.DCTSIZE; column++)
                    {
                        workspace[workspaceIndex] = (float)((int)sample_data[start_row + elemr][start_col + column] - JpegConstants.CENTERJSAMPLE);
                        workspaceIndex++;
                    }
                }

                /* Perform the DCT */
                jpeg_fdct_float(workspace);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    /* Apply the quantization and scaling factor */
                    float temp = workspace[i] * m_float_divisors[quant_tbl_no][i];

                    /* Round to nearest integer.
                     * Since C does not specify the direction of rounding for negative
                     * quotients, we have to force the dividend positive for portability.
                     * The maximum coefficient size is +-16K (for 12-bit data), so this
                     * code should work for either 16-bit or 32-bit ints.
                     */
                    coef_blocks[bi][i] = (short)((int)(temp + (float)16384.5) - 16384);
                }
            }
        }
        /// <summary>
        /// Variant of decompress_data for use when doing block smoothing.
        /// </summary>
        private ReadResult decompress_smooth_data(ComponentBuffer[] output_buf)
        {
            /* Force some input to be done if we are getting ahead of the input. */
            while (m_cinfo.m_input_scan_number <= m_cinfo.m_output_scan_number && !m_cinfo.m_inputctl.EOIReached())
            {
                if (m_cinfo.m_input_scan_number == m_cinfo.m_output_scan_number)
                {
                    /* If input is working on current scan, we ordinarily want it to
                     * have completed the current row.  But if input scan is DC,
                     * we want it to keep one row ahead so that next block row's DC
                     * values are up to date.
                     */
                    int delta = (m_cinfo.m_Ss == 0) ? 1 : 0;
                    if (m_cinfo.m_input_iMCU_row > m_cinfo.m_output_iMCU_row + delta)
                    {
                        break;
                    }
                }

                if (m_cinfo.m_inputctl.consume_input() == ReadResult.JPEG_SUSPENDED)
                {
                    return(ReadResult.JPEG_SUSPENDED);
                }
            }

            int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;

            /* OK, output from the virtual arrays. */
            for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[ci];

                /* Don't bother to IDCT an uninteresting component. */
                if (!componentInfo.component_needed)
                {
                    continue;
                }

                int  block_rows;
                int  access_rows;
                bool last_row;
                /* Count non-dummy DCT block rows in this iMCU row. */
                if (m_cinfo.m_output_iMCU_row < last_iMCU_row)
                {
                    block_rows  = componentInfo.V_samp_factor;
                    access_rows = block_rows * 2; /* this and next iMCU row */
                    last_row    = false;
                }
                else
                {
                    /* NB: can't use last_row_height here; it is input-side-dependent! */
                    block_rows = componentInfo.height_in_blocks % componentInfo.V_samp_factor;
                    if (block_rows == 0)
                    {
                        block_rows = componentInfo.V_samp_factor;
                    }
                    access_rows = block_rows; /* this iMCU row only */
                    last_row    = true;
                }

                /* Align the virtual buffer for this component. */
                JBLOCK[][] buffer = null;
                bool       first_row;
                int        bufferRowOffset = 0;
                if (m_cinfo.m_output_iMCU_row > 0)
                {
                    access_rows    += componentInfo.V_samp_factor; /* prior iMCU row too */
                    buffer          = m_whole_image[ci].Access((m_cinfo.m_output_iMCU_row - 1) * componentInfo.V_samp_factor, access_rows);
                    bufferRowOffset = componentInfo.V_samp_factor; /* point to current iMCU row */
                    first_row       = false;
                }
                else
                {
                    buffer    = m_whole_image[ci].Access(0, access_rows);
                    first_row = true;
                }

                /* Fetch component-dependent info */
                int coefBitsOffset = ci * SAVED_COEFS;
                int Q00            = componentInfo.quant_table.quantval[0];
                int Q01            = componentInfo.quant_table.quantval[Q01_POS];
                int Q10            = componentInfo.quant_table.quantval[Q10_POS];
                int Q20            = componentInfo.quant_table.quantval[Q20_POS];
                int Q11            = componentInfo.quant_table.quantval[Q11_POS];
                int Q02            = componentInfo.quant_table.quantval[Q02_POS];
                int outputIndex    = ci;

                /* Loop over all DCT blocks to be processed. */
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    int bufferIndex = bufferRowOffset + block_row;

                    int prev_block_row = 0;
                    if (first_row && block_row == 0)
                    {
                        prev_block_row = bufferIndex;
                    }
                    else
                    {
                        prev_block_row = bufferIndex - 1;
                    }

                    int next_block_row = 0;
                    if (last_row && block_row == block_rows - 1)
                    {
                        next_block_row = bufferIndex;
                    }
                    else
                    {
                        next_block_row = bufferIndex + 1;
                    }

                    /* We fetch the surrounding DC values using a sliding-register approach.
                     * Initialize all nine here so as to do the right thing on narrow pics.
                     */
                    int DC1 = buffer[prev_block_row][0][0];
                    int DC2 = DC1;
                    int DC3 = DC1;

                    int DC4 = buffer[bufferIndex][0][0];
                    int DC5 = DC4;
                    int DC6 = DC4;

                    int DC7 = buffer[next_block_row][0][0];
                    int DC8 = DC7;
                    int DC9 = DC7;

                    int output_col        = 0;
                    int last_block_column = componentInfo.Width_in_blocks - 1;
                    for (int block_num = 0; block_num <= last_block_column; block_num++)
                    {
                        /* Fetch current DCT block into workspace so we can modify it. */
                        JBLOCK workspace = new JBLOCK();
                        Buffer.BlockCopy(buffer[bufferIndex][0].data, 0, workspace.data, 0, workspace.data.Length * sizeof(short));

                        /* Update DC values */
                        if (block_num < last_block_column)
                        {
                            DC3 = buffer[prev_block_row][1][0];
                            DC6 = buffer[bufferIndex][1][0];
                            DC9 = buffer[next_block_row][1][0];
                        }

                        /* Compute coefficient estimates per K.8.
                         * An estimate is applied only if coefficient is still zero,
                         * and is not known to be fully accurate.
                         */
                        /* AC01 */
                        int Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 1];
                        if (Al != 0 && workspace[1] == 0)
                        {
                            int pred;
                            int num = 36 * Q00 * (DC4 - DC6);
                            if (num >= 0)
                            {
                                pred = ((Q01 << 7) + num) / (Q01 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = ((Q01 << 7) - num) / (Q01 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[1] = (short)pred;
                        }

                        /* AC10 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 2];
                        if (Al != 0 && workspace[8] == 0)
                        {
                            int pred;
                            int num = 36 * Q00 * (DC2 - DC8);
                            if (num >= 0)
                            {
                                pred = ((Q10 << 7) + num) / (Q10 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = ((Q10 << 7) - num) / (Q10 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[8] = (short)pred;
                        }

                        /* AC20 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 3];
                        if (Al != 0 && workspace[16] == 0)
                        {
                            int pred;
                            int num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
                            if (num >= 0)
                            {
                                pred = ((Q20 << 7) + num) / (Q20 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = ((Q20 << 7) - num) / (Q20 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[16] = (short)pred;
                        }

                        /* AC11 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 4];
                        if (Al != 0 && workspace[9] == 0)
                        {
                            int pred;
                            int num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
                            if (num >= 0)
                            {
                                pred = ((Q11 << 7) + num) / (Q11 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = ((Q11 << 7) - num) / (Q11 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[9] = (short)pred;
                        }

                        /* AC02 */
                        Al = m_coef_bits_latch[m_coef_bits_savedOffset + coefBitsOffset + 5];
                        if (Al != 0 && workspace[2] == 0)
                        {
                            int pred;
                            int num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
                            if (num >= 0)
                            {
                                pred = ((Q02 << 7) + num) / (Q02 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = ((Q02 << 7) - num) / (Q02 << 8);
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[2] = (short)pred;
                        }

                        /* OK, do the IDCT */
                        m_cinfo.m_idct.inverse(componentInfo.Component_index, workspace.data, output_buf[outputIndex], 0, output_col);

                        /* Advance for next column */
                        DC1 = DC2;
                        DC2 = DC3;
                        DC4 = DC5;
                        DC5 = DC6;
                        DC7 = DC8;
                        DC8 = DC9;

                        bufferIndex++;
                        prev_block_row++;
                        next_block_row++;

                        output_col += componentInfo.DCT_scaled_size;
                    }

                    outputIndex += componentInfo.DCT_scaled_size;
                }
            }

            m_cinfo.m_output_iMCU_row++;
            if (m_cinfo.m_output_iMCU_row < m_cinfo.m_total_iMCU_rows)
            {
                return(ReadResult.JPEG_ROW_COMPLETED);
            }

            return(ReadResult.JPEG_SCAN_COMPLETED);
        }
Example #38
0
        /// <summary>
        /// Consume input data and store it in the full-image coefficient buffer.
        /// We read as much as one fully interleaved MCU row ("iMCU" row) per call,
        /// ie, v_samp_factor block rows for each component in the scan.
        /// </summary>
        public ReadResult consume_data()
        {
            if (m_useDummyConsumeData)
                return ReadResult.JPEG_SUSPENDED;  /* Always indicate nothing was done */

            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];

            /* Align the virtual buffers for the components used in this scan. */
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];

                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_cinfo.m_input_iMCU_row * componentInfo.V_samp_factor, componentInfo.V_samp_factor);

                /* Note: entropy decoder expects buffer to be zeroed,
                 * but this is handled automatically by the memory manager
                 * because we requested a pre-zeroed array.
                 */
            }

            /* Loop to process one whole iMCU row */
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_MCU_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            for (int xindex = 0; xindex < componentInfo.MCU_width; xindex++)
                            {
                                m_MCU_buffer[blkn] = buffer[ci][yindex + yoffset][start_col + xindex];
                                blkn++;
                            }
                        }
                    }

                    /* Try to fetch the MCU. */
                    if (!m_cinfo.m_entropy.decode_mcu(m_MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_MCU_ctr = MCU_col_num;
                        return ReadResult.JPEG_SUSPENDED;
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_MCU_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_cinfo.m_input_iMCU_row++;
            if (m_cinfo.m_input_iMCU_row < m_cinfo.m_total_iMCU_rows)
            {
                start_iMCU_row();
                return ReadResult.JPEG_ROW_COMPLETED;
            }

            /* Completed the scan */
            m_cinfo.m_inputctl.finish_input_pass();
            return ReadResult.JPEG_SCAN_COMPLETED;
        }
        /// <summary>
        /// Encode and output one MCU's worth of Huffman-compressed coefficients.
        /// </summary>
        private bool encode_mcu_huff(JBLOCK[][] MCU_data)
        {
            /* Load up working state */
            savable_state state;
            state = m_saved;

            /* Emit restart marker if needed */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    if (!emit_restart(state, m_next_restart_num))
                        return false;
                }
            }

            /* Encode the MCU data blocks */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                int ci = m_cinfo.m_MCU_membership[blkn];
                if (!encode_one_block(state, MCU_data[blkn][0].data, state.last_dc_val[ci],
                    m_dc_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Dc_tbl_no],
                    m_ac_derived_tbls[m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]].Ac_tbl_no]))
                {
                    return false;
                }

                /* Update last_dc_val */
                state.last_dc_val[ci] = MCU_data[blkn][0][0];
            }

            /* Completed MCU, so update state */
            m_saved = state;

            /* Update restart-interval state too */
            if (m_cinfo.m_restart_interval != 0)
            {
                if (m_restarts_to_go == 0)
                {
                    m_restarts_to_go = m_cinfo.m_restart_interval;
                    m_next_restart_num++;
                    m_next_restart_num &= 7;
                }

                m_restarts_to_go--;
            }

            return true;
        }
Example #40
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. */
                JBLOCK[] buffer = new JBLOCK[JpegConstants.D_MAX_BLOCKS_IN_MCU];
                for (int i = 0; i < JpegConstants.D_MAX_BLOCKS_IN_MCU; i++)
                {
                    buffer[i] = new JBLOCK();
                    for (int ii = 0; ii < buffer[i].data.Length; ii++)
                        buffer[i].data[ii] = -12851;

                    m_MCU_buffer[i] = buffer[i];
                }

                m_useDummyConsumeData = true;
                m_decompressor = DecompressorType.OnePass;
                m_coef_arrays = null; /* flag for no virtual arrays */
            }
        }
Example #41
0
        /// <summary>
        /// Process some data.
        /// We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        /// per call, ie, v_samp_factor block rows for each component in the scan.
        /// The data is obtained from the virtual arrays and fed to the entropy coder.
        /// Returns true if the iMCU row is completed, false if suspended.
        ///
        /// NB: input_buf is ignored; it is likely to be a null pointer.
        /// </summary>
        public virtual bool compress_data(byte[][][] input_buf)
        {
            /* Align the virtual buffers for the components used in this scan. */
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_iMCU_row_num * componentInfo.V_samp_factor, componentInfo.V_samp_factor);
            }

            /* Loop to process one whole iMCU row */
            int last_MCU_col  = m_cinfo.m_MCUs_per_row - 1;
            int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;

            JBLOCK[][] MCU_buffer = new JBLOCK[JpegConstants.C_MAX_BLOCKS_IN_MCU][];
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_mcu_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        int blockcnt  = (MCU_col_num < last_MCU_col) ? componentInfo.MCU_width : componentInfo.last_col_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            int xindex = 0;
                            if (m_iMCU_row_num < last_iMCU_row || yindex + yoffset < componentInfo.last_row_height)
                            {
                                /* Fill in pointers to real blocks in this row */
                                for (xindex = 0; xindex < blockcnt; xindex++)
                                {
                                    int bufLength = buffer[ci][yindex + yoffset].Length;
                                    int start     = start_col + xindex;
                                    MCU_buffer[blkn] = new JBLOCK[bufLength - start];
                                    for (int j = start; j < bufLength; j++)
                                    {
                                        MCU_buffer[blkn][j - start] = buffer[ci][yindex + yoffset][j];
                                    }

                                    blkn++;
                                }
                            }
                            else
                            {
                                /* At bottom of image, need a whole row of dummy blocks */
                                xindex = 0;
                            }

                            /* Fill in any dummy blocks needed in this row.
                             * Dummy blocks are filled in the same way as in jccoefct.c:
                             * all zeroes in the AC entries, DC entries equal to previous
                             * block's DC value.  The init routine has already zeroed the
                             * AC entries, so we need only set the DC entries correctly.
                             */
                            for (; xindex < componentInfo.MCU_width; xindex++)
                            {
                                MCU_buffer[blkn]       = m_dummy_buffer[blkn];
                                MCU_buffer[blkn][0][0] = MCU_buffer[blkn - 1][0][0];
                                blkn++;
                            }
                        }
                    }

                    /* Try to write the MCU. */
                    if (!m_cinfo.m_entropy.encode_mcu(MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_mcu_ctr         = MCU_col_num;
                        return(false);
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_mcu_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_iMCU_row_num++;
            start_iMCU_row();
            return(true);
        }