Пример #1
0
        // Out-of-line code for Huffman code decoding.
        static int jpeg_huff_decode(ref bitread_working_state state, ulong get_buffer, int bits_left, d_derived_tbl htbl, int min_bits)
        {
            int l = min_bits;

            // HUFF_DECODE has determined that the code is at least min_bits
            // bits long, so fetch that many bits in one swoop.

            //was CHECK_BIT_BUFFER(*state, l, return -1);
            if (bits_left < l)
            {
                if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, l))
                {
                    return(-1);
                }
                get_buffer = state.get_buffer;
                bits_left  = state.bits_left;
            }

            //was code = GET_BITS(l);
            int code = ((int)(get_buffer >> (bits_left -= l))) & ((1 << l) - 1);

            // Collect the rest of the Huffman code one bit at a time.
            // This is per Figure F.16 in the JPEG spec.
            while (code > htbl.maxcode[l])
            {
                code <<= 1;
                //was CHECK_BIT_BUFFER(*state, 1, return -1);
                if (bits_left < 1)
                {
                    if (!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 1))
                    {
                        return(-1);
                    }
                    get_buffer = state.get_buffer;
                    bits_left  = state.bits_left;
                }
                //was code |= GET_BITS(1);
                code |= ((int)(get_buffer >> (bits_left -= 1))) & 1;
                l++;
            }

            // Unload the local registers
            state.get_buffer = get_buffer;
            state.bits_left  = bits_left;

            // With garbage input we may reach the sentinel value l = 17.

            if (l > 16)
            {
                WARNMS(state.cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
                return(0);                                      // fake a zero as the safest result
            }

            return(htbl.pub.huffval[(int)(code + htbl.valoffset[l])]);
        }
Пример #2
0
		// 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.)
		static bool decode_mcu(jpeg_decompress cinfo, short[][] MCU_data)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			shuff_entropy_decoder entropy=(shuff_entropy_decoder)lossyd.entropy_private;

			// Process restart marker if needed; may have to suspend
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
					if(!process_restart_dshuff(cinfo)) 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(!entropy.insufficient_data)
			{
				bitread_working_state br_state=new bitread_working_state();

				savable_state_sq state;
				state.last_dc_val=new int[MAX_COMPS_IN_SCAN];

				// Load up working state
				//was BITREAD_STATE_VARS;
				//was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
				br_state.cinfo=cinfo;
				br_state.input_bytes=cinfo.src.input_bytes;
				br_state.next_input_byte=cinfo.src.next_input_byte;
				br_state.bytes_in_buffer=cinfo.src.bytes_in_buffer;
				ulong get_buffer=entropy.bitstate.get_buffer;
				int bits_left=entropy.bitstate.bits_left;

				//was state=entropy.saved;
				entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

				// Outer loop handles each block in the MCU
				for(int blkn=0; blkn<cinfo.blocks_in_MCU; blkn++)
				{
					short[] block=MCU_data[blkn];
					d_derived_tbl dctbl=entropy.dc_cur_tbls[blkn];
					d_derived_tbl actbl=entropy.ac_cur_tbls[blkn];
					int s=0, k, r;

					// Decode a single block's worth of coefficients

					// Section F.2.2.1: decode the DC coefficient difference
					//was HUFF_DECODE(s, br_state, dctbl, return false, label1);
					{
						int nb, look;
						bool label=false;
						if(bits_left<HUFF_LOOKAHEAD)
						{
							if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) return false;
							get_buffer=br_state.get_buffer;
							bits_left=br_state.bits_left;
							if(bits_left<HUFF_LOOKAHEAD)
							{
								nb=1;
								label=true;
								if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb))<0) return false;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
							}
						}

						if(!label)
						{
							//was look=PEEK_BITS(HUFF_LOOKAHEAD);
							look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
							if((nb=dctbl.look_nbits[look])!=0)
							{
								//was DROP_BITS(nb);
								bits_left-=nb;
								s=dctbl.look_sym[look];
							}
							else
							{
								nb=HUFF_LOOKAHEAD+1;
								if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb))<0) return false;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
							}
						}
					}

					if(s!=0)
					{
						//was CHECK_BIT_BUFFER(br_state, s, return false);
						if(bits_left<s)
						{
							if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) return false;
							get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
						}
						//was r = GET_BITS(s);
						r=((int)(get_buffer>>(bits_left-=s)))&((1<<s)-1);
						//was s=HUFF_EXTEND(r, s);
						s=(r<(1<<(s-1))?r+(((-1)<<s)+1):r);
					}

					if(entropy.dc_needed[blkn])
					{
						// Convert DC difference to actual value, update last_dc_val
						int ci=cinfo.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)
						block[0]=(short)s;
					}

					if(entropy.ac_needed[blkn])
					{
						// Section F.2.2.2: decode the AC coefficients
						// Since zeroes are skipped, output area must be cleared beforehand
						for(k=1; k<DCTSIZE2; k++)
						{
							//was HUFF_DECODE(s, br_state, actbl, return false, label2);
							{
								int nb, look;
								bool label=false;
								if(bits_left<HUFF_LOOKAHEAD)
								{
									if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) return false;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
									if(bits_left<HUFF_LOOKAHEAD)
									{
										nb=1;
										label=true;
										if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb))<0) return false;
										get_buffer=br_state.get_buffer;
										bits_left=br_state.bits_left;
									}
								}

								if(!label)
								{
									//was look=PEEK_BITS(HUFF_LOOKAHEAD);
									look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
									if((nb=actbl.look_nbits[look])!=0)
									{
										//was DROP_BITS(nb);
										bits_left-=nb;
										s=actbl.look_sym[look];
									}
									else
									{
										nb=HUFF_LOOKAHEAD+1;
										if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb))<0) return false;
										get_buffer=br_state.get_buffer;
										bits_left=br_state.bits_left;
									}
								}
							}

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

							if(s!=0)
							{
								k+=r;
								//was CHECK_BIT_BUFFER(br_state, s, return false);
								if(bits_left<s)
								{
									if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) return false;
									get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
								}
								//was r = GET_BITS(s);
								r=((int)(get_buffer>>(bits_left-=s)))&((1<<s)-1);
								//was s=HUFF_EXTEND(r, s);
								s=(r<(1<<(s-1))?r+(((-1)<<s)+1):r);


								// 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.
								block[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(k=1; k<DCTSIZE2; k++)
						{
							//was HUFF_DECODE(s, br_state, actbl, return false, label3);
							{
								int nb, look;
								bool label=false;
								if(bits_left<HUFF_LOOKAHEAD)
								{
									if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) return false;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
									if(bits_left<HUFF_LOOKAHEAD)
									{
										nb=1;
										label=true;
										if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb))<0) return false;
										get_buffer=br_state.get_buffer;
										bits_left=br_state.bits_left;

									}
								}

								if(!label)
								{
									//was look=PEEK_BITS(HUFF_LOOKAHEAD);
									look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
									if((nb=actbl.look_nbits[look])!=0)
									{
										//was DROP_BITS(nb);
										bits_left-=nb;
										s=actbl.look_sym[look];
									}
									else
									{
										nb=HUFF_LOOKAHEAD+1;
										if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb))<0) return false;
										get_buffer=br_state.get_buffer;
										bits_left=br_state.bits_left;
									}
								}
							}

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

							if(s!=0)
							{
								k+=r;
								//was CHECK_BIT_BUFFER(br_state, s, return false);
								if(bits_left<s)
								{
									if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) return false;
									get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
								}
								//was DROP_BITS(s);
								bits_left-=s;
							}
							else
							{
								if(r!=15) break;
								k+=15;
							}
						}
					}
				}

				// Completed MCU, so update state
				//was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
				cinfo.src.input_bytes=br_state.input_bytes;
				cinfo.src.next_input_byte=br_state.next_input_byte;
				cinfo.src.bytes_in_buffer=br_state.bytes_in_buffer;
				entropy.bitstate.get_buffer=get_buffer;
				entropy.bitstate.bits_left=bits_left;

				//was entropy.saved=state;
				state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
			}

			// Account for restart interval (no-op if not using restarts)
			entropy.restarts_to_go--;

			return true;
		}
Пример #3
0
		// Out-of-line code for Huffman code decoding.
		static int jpeg_huff_decode(ref bitread_working_state state, ulong get_buffer, int bits_left, d_derived_tbl htbl, int min_bits)
		{
			int l=min_bits;

			// HUFF_DECODE has determined that the code is at least min_bits
			// bits long, so fetch that many bits in one swoop.

			//was CHECK_BIT_BUFFER(*state, l, return -1);
			if(bits_left<l)
			{
				if(!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, l)) return -1;
				get_buffer=state.get_buffer;
				bits_left=state.bits_left;
			}

			//was code = GET_BITS(l);
			int code=((int)(get_buffer>>(bits_left-=l)))&((1<<l)-1);

			// Collect the rest of the Huffman code one bit at a time.
			// This is per Figure F.16 in the JPEG spec.
			while(code>htbl.maxcode[l])
			{
				code<<=1;
				//was CHECK_BIT_BUFFER(*state, 1, return -1);
				if(bits_left<1)
				{
					if(!jpeg_fill_bit_buffer(ref state, get_buffer, bits_left, 1)) return -1;
					get_buffer=state.get_buffer;
					bits_left=state.bits_left;
				}
				//was code |= GET_BITS(1);
				code|=((int)(get_buffer>>(bits_left-=1)))&1;
				l++;
			}

			// Unload the local registers
			state.get_buffer=get_buffer;
			state.bits_left=bits_left;

			// With garbage input we may reach the sentinel value l = 17.

			if(l>16)
			{
				WARNMS(state.cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);
				return 0;			// fake a zero as the safest result
			}

			return htbl.pub.huffval[(int)(code+htbl.valoffset[l])];
		}
Пример #4
0
		// Macros to declare and load/save bitread local variables.
		//#define BITREAD_STATE_VARS \
		//	ulong get_buffer; \
		//	int bits_left; \
		//	bitread_working_state br_state

		//#define BITREAD_LOAD_STATE(cinfop, permstate) \
		//	br_state.cinfo=cinfop; \
		//	br_state.next_input_byte=cinfop.src.next_input_byte; \
		//	br_state.bytes_in_buffer=cinfop.src.bytes_in_buffer; \
		//	get_buffer=permstate.get_buffer; \
		//	bits_left=permstate.bits_left;

		//#define BITREAD_SAVE_STATE(cinfop, permstate) \
		//	cinfop.src.next_input_byte=br_state.next_input_byte; \
		//	cinfop.src.bytes_in_buffer=br_state.bytes_in_buffer; \
		//	permstate.get_buffer=get_buffer; \
		//	permstate.bits_left=bits_left

		// These macros provide the in-line portion of bit fetching.
		// Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
		// before using GET_BITS, PEEK_BITS, or DROP_BITS.
		// The variables get_buffer and bits_left are assumed to be locals,
		// but the state struct might not be (jpeg_huff_decode needs this).
		//	CHECK_BIT_BUFFER(state,n,action);
		//		Ensure there are N bits in get_buffer; if suspend, take action.
		//		val = GET_BITS(n);
		//		Fetch next N bits.
		//		val = PEEK_BITS(n);
		//		Fetch next N bits without removing them from the buffer.
		//	DROP_BITS(n);
		//		Discard next N bits.
		// The value N should be a simple variable, not an expression, because it
		// is evaluated multiple times.

		//#define CHECK_BIT_BUFFER(state, nbits, action) \
		//	{ if(bits_left<(nbits)) { \
		//		if(!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) { action; } \
		//		get_buffer=(state).get_buffer; bits_left=(state).bits_left; } }

		//#define GET_BITS(nbits) (((int)(get_buffer>>(bits_left-=(nbits))))&((1<<(nbits))-1))

		//#define PEEK_BITS(nbits) (((int)(get_buffer>>(bits_left-(nbits))))&((1<<(nbits))-1))

		//#define DROP_BITS(nbits) (bits_left-=(nbits))

		// Load up the bit buffer to a depth of at least nbits
		// Out-of-line code for bit fetching.
		// Note: current values of get_buffer and bits_left are passed as parameters,
		// but are returned in the corresponding fields of the state struct.

		// On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
		// of get_buffer to be used. (On machines with wider words, an even larger
		// buffer could be used.) However, on some machines 32-bit shifts are
		// quite slow and take time proportional to the number of places shifted.
		// (This is true with most PC compilers, for instance.) In this case it may
		// be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
		// average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
		static bool jpeg_fill_bit_buffer(ref bitread_working_state state, ulong get_buffer, int bits_left, int nbits)
		{
			int MIN_GET_BITS=57;
			// Copy heavily used state fields into locals (hopefully registers)
			byte[] input_bytes=state.input_bytes;
			int next_input_byte=state.next_input_byte;
			uint bytes_in_buffer=state.bytes_in_buffer;
			jpeg_decompress cinfo=state.cinfo;

			// Attempt to load at least MIN_GET_BITS bits into get_buffer.
			// (It is assumed that no request will be for more than that many bits.)
			// We fail to do so only if we hit a marker or are forced to suspend.
			if(cinfo.unread_marker==0)
			{	// cannot advance past a marker
				while(bits_left<MIN_GET_BITS)
				{
					// Attempt to read a byte
					if(bytes_in_buffer==0)
					{
						if(!cinfo.src.fill_input_buffer(cinfo)) return false;
						input_bytes=cinfo.src.input_bytes;
						next_input_byte=cinfo.src.next_input_byte;
						bytes_in_buffer=cinfo.src.bytes_in_buffer;
					}
					bytes_in_buffer--;
					int c=input_bytes[next_input_byte++];

					// If it's 0xFF, check and discard stuffed zero byte
					if(c==0xFF)
					{
						// Loop here to discard any padding FF's on terminating marker,
						// so that we can save a valid unread_marker value. NOTE: we will
						// accept multiple FF's followed by a 0 as meaning a single FF data
						// byte. This data pattern is not valid according to the standard.
						do
						{
							if(bytes_in_buffer==0)
							{
								if(!cinfo.src.fill_input_buffer(cinfo)) return false;
								input_bytes=cinfo.src.input_bytes;
								next_input_byte=cinfo.src.next_input_byte;
								bytes_in_buffer=cinfo.src.bytes_in_buffer;
							}
							bytes_in_buffer--;
							c=input_bytes[next_input_byte++];
						} while(c==0xFF);

						if(c==0)
						{
							// Found FF/00, which represents an FF data byte
							c=0xFF;
						}
						else
						{
							// Oops, it's actually a marker indicating end of compressed data.
							// Save the marker code for later use.
							// Fine point: it might appear that we should save the marker into
							// bitread working state, not straight into permanent state. But
							// once we have hit a marker, we cannot need to suspend within the
							// current MCU, because we will read no more bytes from the data
							// source. So it is OK to update permanent state right away.
							cinfo.unread_marker=c;
							// See if we need to insert some fake zero bits.
							break;
						}
					}

					// OK, load c into get_buffer
					get_buffer*=256;
					get_buffer|=(uint)c;
					bits_left+=8;
				} // end while
			}

			if(cinfo.unread_marker!=0)
			{
				// We get here if we've read the marker that terminates the compressed
				// data segment. There should be enough bits in the buffer register
				// to satisfy the request; if so, no problem.
				if(nbits>bits_left)
				{
					// Uh-oh. Report corrupted data to user and stuff zeroes into
					// the data stream, so that we can produce some kind of image.
					// We use a nonvolatile flag to ensure that only one warning message
					// appears per data segment.
					jpeg_entropy_decoder huffd;
#if D_LOSSLESS_SUPPORTED
					if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)
						huffd=(jpeg_entropy_decoder)((jpeg_lossless_d_codec)cinfo.coef).entropy_private;
					else 
#endif
						huffd=(jpeg_entropy_decoder)((jpeg_lossy_d_codec)cinfo.coef).entropy_private;
					if(!huffd.insufficient_data)
					{
						WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HIT_MARKER);
						huffd.insufficient_data=true;
					}
					// Fill the buffer with zero bits
					get_buffer<<=MIN_GET_BITS-bits_left;
					bits_left=MIN_GET_BITS;
				}
			}

			// Unload the local registers
			state.input_bytes=input_bytes;
			state.next_input_byte=next_input_byte;
			state.bytes_in_buffer=bytes_in_buffer;
			state.get_buffer=get_buffer;
			state.bits_left=bits_left;

			return true;
		}
Пример #5
0
		// MCU decoding for AC successive approximation refinement scan.
		static bool decode_mcu_AC_refine(jpeg_decompress cinfo, short[][] MCU_data)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private;
			int Se=cinfo.Se;
			short p1=(short)(1<<cinfo.Al);		// 1 in the bit position being coded
			short m1=(short)((-1)<<cinfo.Al);	// -1 in the bit position being coded
			short[] block=null;

			// 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[DCTSIZE2];

			// Process restart marker if needed; may have to suspend
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
					if(!process_restart_dphuff(cinfo)) return false;
			}

			// If we've run out of data, don't modify the MCU.
			if(!entropy.insufficient_data)
			{
				// Load up working state
				//was BITREAD_STATE_VARS;
				bitread_working_state br_state=new bitread_working_state();

				//was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
				br_state.cinfo=cinfo;
				br_state.input_bytes=cinfo.src.input_bytes;
				br_state.next_input_byte=cinfo.src.next_input_byte;
				br_state.bytes_in_buffer=cinfo.src.bytes_in_buffer;
				ulong get_buffer=entropy.bitstate.get_buffer;
				int bits_left=entropy.bitstate.bits_left;
				uint EOBRUN=entropy.saved.EOBRUN; // only part of saved state we need

				// There is always only one block per MCU
				block=MCU_data[0];
				d_derived_tbl tbl=entropy.ac_derived_tbl;

				// initialize coefficient loop counter to start of band
				int k=cinfo.Ss;

				if(EOBRUN==0)
				{
					for(; k<=Se; k++)
					{
						int s=0, r;

						//was HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
						{
							int nb, look;
							bool label=false;
							if(bits_left<HUFF_LOOKAHEAD)
							{
								if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) goto undoit;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
								if(bits_left<HUFF_LOOKAHEAD)
								{
									nb=1;
									label=true;
									if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) goto undoit;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
								}
							}

							if(!label)
							{
								//was look=PEEK_BITS(HUFF_LOOKAHEAD);
								look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
								if((nb=tbl.look_nbits[look])!=0)
								{
									//was DROP_BITS(nb);
									bits_left-=nb;
									s=tbl.look_sym[look];
								}
								else
								{
									nb=HUFF_LOOKAHEAD+1;
									if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) goto undoit;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
								}
							}
						}

						r=s>>4;
						s&=15;
						if(s!=0)
						{
							if(s!=1) WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE); // size of new coef should always be 1
							//was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
							if(bits_left<1)
							{
								if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit;
								get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
							}
							//was if (GET_BITS(1))
							if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) s=p1; // newly nonzero coef is positive
							else s=m1; // newly nonzero coef is negative
						}
						else
						{
							if(r!=15)
							{
								EOBRUN=(uint)(1<<r); // EOBr, run length is 2^r + appended bits
								if(r!=0)
								{
									//was CHECK_BIT_BUFFER(br_state, r, goto undoit);
									if(bits_left<r)
									{
										if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) goto undoit;
										get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
									}
									//was r = GET_BITS(r);
									r=((int)(get_buffer>>(bits_left-=r)))&((1<<r)-1);
									EOBRUN+=(uint)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 thiscoef=jpeg_natural_order[k];
							if(block[thiscoef]!=0)
							{
								//was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
								if(bits_left<1)
								{
									if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit;
									get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
								}
								//was if (GET_BITS(1))
								if((((int)(get_buffer>>(bits_left-=1)))&1)!=0)
								{
									if((block[thiscoef]&p1)==0)
									{ // do nothing if already set it
										if(block[thiscoef]>=0) block[thiscoef]+=p1;
										else block[thiscoef]+=m1;
									}
								}
							}
							else
							{
								if(--r<0) break; // reached target zero coefficient
							}
							k++;
						} while(k<=Se);

						if(s!=0)
						{
							int pos=jpeg_natural_order[k];
							// Output newly nonzero coefficient
							block[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<=Se; k++)
					{
						int thiscoef=jpeg_natural_order[k];
						if(block[thiscoef]!=0)
						{
							//was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
							if(bits_left<1)
							{
								if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) goto undoit;
								get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
							}
							//was if (GET_BITS(1))
							if((((int)(get_buffer>>(bits_left-=1)))&1)!=0)
							{
								if((block[thiscoef]&p1)==0)
								{ // do nothing if already changed it
									if(block[thiscoef]>=0) block[thiscoef]+=p1;
									else block[thiscoef]+=m1;
								}
							}
						}
					}
					// Count one block completed in EOB run
					EOBRUN--;
				}

				// Completed MCU, so update state
				//was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
				cinfo.src.input_bytes=br_state.input_bytes;
				cinfo.src.next_input_byte=br_state.next_input_byte;
				cinfo.src.bytes_in_buffer=br_state.bytes_in_buffer;
				entropy.bitstate.get_buffer=get_buffer;
				entropy.bitstate.bits_left=bits_left;
				entropy.saved.EOBRUN=EOBRUN; // only part of saved state we need
			}

			// Account for restart interval (no-op if not using restarts)
			entropy.restarts_to_go--;

			return true;

undoit:
			// Re-zero any output coefficients that we made newly nonzero
			while(num_newnz>0) block[newnz_pos[--num_newnz]]=0;

			return false;
		}
Пример #6
0
		// 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.
		static bool decode_mcu_DC_refine(jpeg_decompress cinfo, short[][] MCU_data)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private;
			short p1=(short)(1<<cinfo.Al);	// 1 in the bit position being coded

			// Process restart marker if needed; may have to suspend
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
					if(!process_restart_dphuff(cinfo)) 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
			//was BITREAD_STATE_VARS;
			bitread_working_state br_state=new bitread_working_state();

			//was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
			br_state.cinfo=cinfo;
			br_state.input_bytes=cinfo.src.input_bytes;
			br_state.next_input_byte=cinfo.src.next_input_byte;
			br_state.bytes_in_buffer=cinfo.src.bytes_in_buffer;
			ulong get_buffer=entropy.bitstate.get_buffer;
			int bits_left=entropy.bitstate.bits_left;

			// Outer loop handles each block in the MCU
			for(int blkn=0; blkn<cinfo.blocks_in_MCU; blkn++)
			{
				short[] block=MCU_data[blkn];

				// Encoded data is simply the next bit of the two's-complement DC value
				//was CHECK_BIT_BUFFER(br_state, 1, return false);
				if(bits_left<1)
				{
					if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1)) return false;
					get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
				}

				//was if(GET_BITS(1))
				if((((int)(get_buffer>>(bits_left-=1)))&1)!=0) block[0]|=p1;
				// Note: since we use |=, repeating the assignment later is safe
			}

			// Completed MCU, so update state
			//was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
			cinfo.src.input_bytes=br_state.input_bytes;
			cinfo.src.next_input_byte=br_state.next_input_byte;
			cinfo.src.bytes_in_buffer=br_state.bytes_in_buffer;
			entropy.bitstate.get_buffer=get_buffer;
			entropy.bitstate.bits_left=bits_left;

			// Account for restart interval (no-op if not using restarts)
			entropy.restarts_to_go--;

			return true;
		}
Пример #7
0
		// MCU decoding for AC initial scan (either spectral selection,
		// or first pass of successive approximation).
		static bool decode_mcu_AC_first(jpeg_decompress cinfo, short[][] MCU_data)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private;
			int Se=cinfo.Se;
			int Al=cinfo.Al;

			// Process restart marker if needed; may have to suspend
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
					if(!process_restart_dphuff(cinfo)) 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(!entropy.insufficient_data)
			{
				// Load up working state.
				// We can avoid loading/saving bitread state if in an EOB run.
				uint EOBRUN=entropy.saved.EOBRUN; // only part of saved state we need

				// There is always only one block per MCU
				if(EOBRUN>0) EOBRUN--; // if it's a band of zeroes... ...process it now (we do nothing)
				else
				{
					//was BITREAD_STATE_VARS;
					bitread_working_state br_state=new bitread_working_state();

					//was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
					br_state.cinfo=cinfo;
					br_state.input_bytes=cinfo.src.input_bytes;
					br_state.next_input_byte=cinfo.src.next_input_byte;
					br_state.bytes_in_buffer=cinfo.src.bytes_in_buffer;
					ulong get_buffer=entropy.bitstate.get_buffer;
					int bits_left=entropy.bitstate.bits_left;
					short[] block=MCU_data[0];
					d_derived_tbl tbl=entropy.ac_derived_tbl;

					for(int k=cinfo.Ss; k<=Se; k++)
					{
						int s=0, r;

						//was HUFF_DECODE(s, br_state, tbl, return false, label2);
						{
							int nb, look;
							bool label=false;
							if(bits_left<HUFF_LOOKAHEAD)
							{
								if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) return false;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
								if(bits_left<HUFF_LOOKAHEAD)
								{
									nb=1;
									label=true;
									if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) return false;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
								}
							}

							if(!label)
							{
								//was look=PEEK_BITS(HUFF_LOOKAHEAD);
								look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
								if((nb=tbl.look_nbits[look])!=0)
								{
									//was DROP_BITS(nb);
									bits_left-=nb;
									s=tbl.look_sym[look];
								}
								else
								{
									nb=HUFF_LOOKAHEAD+1;
									if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) return false;
									get_buffer=br_state.get_buffer;
									bits_left=br_state.bits_left;
								}
							}
						}

						r=s>>4;
						s&=15;
						if(s!=0)
						{
							k+=r;
							//was CHECK_BIT_BUFFER(br_state, s, return false);
							if(bits_left<s)
							{
								if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) return false;
								get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
							}
							//was r = GET_BITS(s);
							r=((int)(get_buffer>>(bits_left-=s)))&((1<<s)-1);
							//was s=HUFF_EXTEND(r, s);
							s=(r<(1<<(s-1))?r+(((-1)<<s)+1):r);

							// Scale and output coefficient in natural (dezigzagged) order
							block[jpeg_natural_order[k]]=(short)(s<<Al);
						}
						else
						{
							if(r==15)
							{ // ZRL
								k+=15; // skip 15 zeroes in band
							}
							else
							{ // EOBr, run length is 2^r + appended bits
								EOBRUN=(uint)(1<<r);
								if(r!=0)
								{ // EOBr, r > 0
									//was CHECK_BIT_BUFFER(br_state, r, return false);
									if(bits_left<r)
									{
										if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r)) return false;
										get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
									}
									//was r = GET_BITS(r);
									r=((int)(get_buffer>>(bits_left-=r)))&((1<<r)-1);
									EOBRUN+=(uint)r;
								}
								EOBRUN--;	// this band is processed at this moment
								break;		// force end-of-band
							}
						}
					}

					//was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
					cinfo.src.input_bytes=br_state.input_bytes;
					cinfo.src.next_input_byte=br_state.next_input_byte;
					cinfo.src.bytes_in_buffer=br_state.bytes_in_buffer;
					entropy.bitstate.get_buffer=get_buffer;
					entropy.bitstate.bits_left=bits_left;
				}

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

			// Account for restart interval (no-op if not using restarts)
			entropy.restarts_to_go--;

			return true;
		}
Пример #8
0
		// 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.)
		
		// MCU decoding for DC initial scan (either spectral selection,
		// or first pass of successive approximation).
		static bool decode_mcu_DC_first(jpeg_decompress cinfo, short[][] MCU_data)
		{
			jpeg_lossy_d_codec lossyd=(jpeg_lossy_d_codec)cinfo.coef;
			phuff_entropy_decoder entropy=(phuff_entropy_decoder)lossyd.entropy_private;
			int Al=cinfo.Al;

			// Process restart marker if needed; may have to suspend
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
					if(!process_restart_dphuff(cinfo)) 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(!entropy.insufficient_data)
			{
				// Load up working state
				//was BITREAD_STATE_VARS;
				bitread_working_state br_state=new bitread_working_state();

				savable_state state;
				state.last_dc_val=new int[MAX_COMPS_IN_SCAN];

				//was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
				br_state.cinfo=cinfo;
				br_state.input_bytes=cinfo.src.input_bytes;
				br_state.next_input_byte=cinfo.src.next_input_byte;
				br_state.bytes_in_buffer=cinfo.src.bytes_in_buffer;
				ulong get_buffer=entropy.bitstate.get_buffer;
				int bits_left=entropy.bitstate.bits_left;

				//was state=entropy.saved;
				state.EOBRUN=entropy.saved.EOBRUN;
				entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

				// Outer loop handles each block in the MCU
				for(int blkn=0; blkn<cinfo.blocks_in_MCU; blkn++)
				{
					short[] block=MCU_data[blkn];
					int ci=cinfo.MCU_membership[blkn];
					jpeg_component_info compptr=cinfo.cur_comp_info[ci];
					d_derived_tbl tbl=entropy.derived_tbls[compptr.dc_tbl_no];

					int s=0;

					// Decode a single block's worth of coefficients

					// Section F.2.2.1: decode the DC coefficient difference
					//was HUFF_DECODE(s, br_state, tbl, return false, label1);
					{
						int nb, look;
						bool label=false;
						if(bits_left<HUFF_LOOKAHEAD)
						{
							if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0)) return false;
							get_buffer=br_state.get_buffer;
							bits_left=br_state.bits_left;
							if(bits_left<HUFF_LOOKAHEAD)
							{
								nb=1;
								label=true;
								if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) return false;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
							}
						}

						if(!label)
						{
							//was look=PEEK_BITS(HUFF_LOOKAHEAD);
							look=((int)(get_buffer>>(bits_left-HUFF_LOOKAHEAD)))&((1<<HUFF_LOOKAHEAD)-1);
							if((nb=tbl.look_nbits[look])!=0)
							{
								//was DROP_BITS(nb);
								bits_left-=nb;
								s=tbl.look_sym[look];
							}
							else
							{
								nb=HUFF_LOOKAHEAD+1;
								if((s=jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb))<0) return false;
								get_buffer=br_state.get_buffer;
								bits_left=br_state.bits_left;
							}
						}
					}

					if(s!=0)
					{
						//was CHECK_BIT_BUFFER(br_state, s, return false);
						if(bits_left<s)
						{
							if(!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s)) return false;
							get_buffer=br_state.get_buffer; bits_left=br_state.bits_left;
						}
						//was r = GET_BITS(s);
						int r=((int)(get_buffer>>(bits_left-=s)))&((1<<s)-1);
						//was s=HUFF_EXTEND(r, s);
						s=(r<(1<<(s-1))?r+(((-1)<<s)+1):r);
					}

					// 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)
					block[0]=(short)(s<<Al);
				}

				// Completed MCU, so update state
				//was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
				cinfo.src.input_bytes=br_state.input_bytes;
				cinfo.src.next_input_byte=br_state.next_input_byte;
				cinfo.src.bytes_in_buffer=br_state.bytes_in_buffer;
				entropy.bitstate.get_buffer=get_buffer;
				entropy.bitstate.bits_left=bits_left;

				//was entropy.saved=state;
				entropy.saved.EOBRUN=state.EOBRUN;
				state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
			}

			// Account for restart interval (no-op if not using restarts)
			entropy.restarts_to_go--;

			return true;
		}
Пример #9
0
        // Decode and return nMCU's worth of Huffman-compressed differences.
        // Each MCU is also disassembled and placed accordingly in diff_buf.
        //
        // MCU_col_num specifies the column of the first MCU being requested within
        // the MCU-row. This tells us where to position the output row pointers in
        // diff_buf.
        //
        // Returns the number of MCUs decoded. This may be less than nMCU if data
        // source requested suspension. In that case no changes have been made to
        // permanent state. (Exception: some output differences may already have
        // been assigned. This is harmless for this module, since we'll just
        // re-assign them on the next call.)
        static uint decode_mcus_dlhuff(jpeg_decompress cinfo, int[][][] diff_buf, uint MCU_row_num, uint MCU_col_num, uint nMCU)
        {
            jpeg_lossless_d_codec losslsd = (jpeg_lossless_d_codec)cinfo.coef;
            lhuff_entropy_decoder entropy = (lhuff_entropy_decoder)losslsd.entropy_private;

            // Set output pointer locations based on MCU_col_num
            for (int ptrn = 0; ptrn < entropy.num_output_ptrs; ptrn++)
            {
                int ci        = entropy.output_ptr_info[ptrn].ci;
                int yoffset   = entropy.output_ptr_info[ptrn].yoffset;
                int MCU_width = entropy.output_ptr_info[ptrn].MCU_width;
                entropy.output_ptr[ptrn]     = diff_buf[ci][MCU_row_num + yoffset];
                entropy.output_ptr_ind[ptrn] = (int)(MCU_col_num * MCU_width);
            }

            // If we've run out of data, zero out the buffers and return.
            // By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
            //
            // NB: We should find a way to do this without interacting with the
            // undifferencer module directly.
            if (entropy.insufficient_data)
            {
                for (int ptrn = 0; ptrn < entropy.num_output_ptrs; ptrn++)
                {
                    for (int i = 0; i < nMCU * entropy.output_ptr_info[ptrn].MCU_width; i++)
                    {
                        entropy.output_ptr[ptrn][entropy.output_ptr_ind[ptrn] + i] = 0;
                    }
                }

                losslsd.predict_process_restart(cinfo);
            }

            else
            {
                // Load up working state

                //was BITREAD_STATE_VARS;
                bitread_working_state br_state = new bitread_working_state();

                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;

                // Outer loop handles the number of MCU requested
                for (uint mcu_num = 0; mcu_num < nMCU; mcu_num++)
                {
                    // Inner loop handles the samples in the MCU
                    for (int sampn = 0; sampn < cinfo.blocks_in_MCU; sampn++)
                    {
                        d_derived_tbl dctbl = entropy.cur_tbls[sampn];
                        int           s = 0, r;

                        // Section H.2.2: decode the sample difference
                        //was HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
                        {
                            int  nb, look;
                            bool label = false;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                {
                                    return(mcu_num);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    nb    = 1;
                                    label = true;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                    {
                                        return(mcu_num);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }

                            if (!label)
                            {
                                //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                if ((nb = dctbl.look_nbits[look]) != 0)
                                {
                                    //was DROP_BITS(nb);
                                    bits_left -= nb;
                                    s          = dctbl.look_sym[look];
                                }
                                else
                                {
                                    nb = HUFF_LOOKAHEAD + 1;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                    {
                                        return(mcu_num);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }
                        }

                        if (s != 0)
                        {
                            if (s == 16)
                            {
                                s = 32768;                                 // special case: always output 32768
                            }
                            else
                            {                             // normal case: fetch subsequent bits
                                //was CHECK_BIT_BUFFER(br_state, s, return mcu_num);
                                if (bits_left < s)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                    {
                                        return(mcu_num);
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }

                                //was r = GET_BITS(s);
                                r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                                //was s=HUFF_EXTEND(r, s);
                                s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);
                            }
                        }

                        // Output the sample difference
                        int ind = entropy.output_ptr_index[sampn];
                        entropy.output_ptr[ind][entropy.output_ptr_ind[ind]++] = (int)s;
                    }

                    // Completed MCU, so update state
                    //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                    cinfo.src.input_bytes       = br_state.input_bytes;
                    cinfo.src.next_input_byte   = br_state.next_input_byte;
                    cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                    entropy.bitstate.get_buffer = get_buffer;
                    entropy.bitstate.bits_left  = bits_left;
                }
            }

            return(nMCU);
        }
Пример #10
0
        // Macros to declare and load/save bitread local variables.
        //#define BITREAD_STATE_VARS \
        //	ulong get_buffer; \
        //	int bits_left; \
        //	bitread_working_state br_state

        //#define BITREAD_LOAD_STATE(cinfop, permstate) \
        //	br_state.cinfo=cinfop; \
        //	br_state.next_input_byte=cinfop.src.next_input_byte; \
        //	br_state.bytes_in_buffer=cinfop.src.bytes_in_buffer; \
        //	get_buffer=permstate.get_buffer; \
        //	bits_left=permstate.bits_left;

        //#define BITREAD_SAVE_STATE(cinfop, permstate) \
        //	cinfop.src.next_input_byte=br_state.next_input_byte; \
        //	cinfop.src.bytes_in_buffer=br_state.bytes_in_buffer; \
        //	permstate.get_buffer=get_buffer; \
        //	permstate.bits_left=bits_left

        // These macros provide the in-line portion of bit fetching.
        // Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
        // before using GET_BITS, PEEK_BITS, or DROP_BITS.
        // The variables get_buffer and bits_left are assumed to be locals,
        // but the state struct might not be (jpeg_huff_decode needs this).
        //	CHECK_BIT_BUFFER(state,n,action);
        //		Ensure there are N bits in get_buffer; if suspend, take action.
        //		val = GET_BITS(n);
        //		Fetch next N bits.
        //		val = PEEK_BITS(n);
        //		Fetch next N bits without removing them from the buffer.
        //	DROP_BITS(n);
        //		Discard next N bits.
        // The value N should be a simple variable, not an expression, because it
        // is evaluated multiple times.

        //#define CHECK_BIT_BUFFER(state, nbits, action) \
        //	{ if(bits_left<(nbits)) { \
        //		if(!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) { action; } \
        //		get_buffer=(state).get_buffer; bits_left=(state).bits_left; } }

        //#define GET_BITS(nbits) (((int)(get_buffer>>(bits_left-=(nbits))))&((1<<(nbits))-1))

        //#define PEEK_BITS(nbits) (((int)(get_buffer>>(bits_left-(nbits))))&((1<<(nbits))-1))

        //#define DROP_BITS(nbits) (bits_left-=(nbits))

        // Load up the bit buffer to a depth of at least nbits
        // Out-of-line code for bit fetching.
        // Note: current values of get_buffer and bits_left are passed as parameters,
        // but are returned in the corresponding fields of the state struct.

        // On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
        // of get_buffer to be used. (On machines with wider words, an even larger
        // buffer could be used.) However, on some machines 32-bit shifts are
        // quite slow and take time proportional to the number of places shifted.
        // (This is true with most PC compilers, for instance.) In this case it may
        // be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
        // average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
        static bool jpeg_fill_bit_buffer(ref bitread_working_state state, ulong get_buffer, int bits_left, int nbits)
        {
            int MIN_GET_BITS = 57;

            // Copy heavily used state fields into locals (hopefully registers)
            byte[]          input_bytes     = state.input_bytes;
            int             next_input_byte = state.next_input_byte;
            uint            bytes_in_buffer = state.bytes_in_buffer;
            jpeg_decompress cinfo           = state.cinfo;

            // Attempt to load at least MIN_GET_BITS bits into get_buffer.
            // (It is assumed that no request will be for more than that many bits.)
            // We fail to do so only if we hit a marker or are forced to suspend.
            if (cinfo.unread_marker == 0)
            {                   // cannot advance past a marker
                while (bits_left < MIN_GET_BITS)
                {
                    // Attempt to read a byte
                    if (bytes_in_buffer == 0)
                    {
                        if (!cinfo.src.fill_input_buffer(cinfo))
                        {
                            return(false);
                        }
                        input_bytes     = cinfo.src.input_bytes;
                        next_input_byte = cinfo.src.next_input_byte;
                        bytes_in_buffer = cinfo.src.bytes_in_buffer;
                    }
                    bytes_in_buffer--;
                    int c = input_bytes[next_input_byte++];

                    // If it's 0xFF, check and discard stuffed zero byte
                    if (c == 0xFF)
                    {
                        // Loop here to discard any padding FF's on terminating marker,
                        // so that we can save a valid unread_marker value. NOTE: we will
                        // accept multiple FF's followed by a 0 as meaning a single FF data
                        // byte. This data pattern is not valid according to the standard.
                        do
                        {
                            if (bytes_in_buffer == 0)
                            {
                                if (!cinfo.src.fill_input_buffer(cinfo))
                                {
                                    return(false);
                                }
                                input_bytes     = cinfo.src.input_bytes;
                                next_input_byte = cinfo.src.next_input_byte;
                                bytes_in_buffer = cinfo.src.bytes_in_buffer;
                            }
                            bytes_in_buffer--;
                            c = input_bytes[next_input_byte++];
                        } while(c == 0xFF);

                        if (c == 0)
                        {
                            // Found FF/00, which represents an FF data byte
                            c = 0xFF;
                        }
                        else
                        {
                            // Oops, it's actually a marker indicating end of compressed data.
                            // Save the marker code for later use.
                            // Fine point: it might appear that we should save the marker into
                            // bitread working state, not straight into permanent state. But
                            // once we have hit a marker, we cannot need to suspend within the
                            // current MCU, because we will read no more bytes from the data
                            // source. So it is OK to update permanent state right away.
                            cinfo.unread_marker = c;
                            // See if we need to insert some fake zero bits.
                            break;
                        }
                    }

                    // OK, load c into get_buffer
                    get_buffer *= 256;
                    get_buffer |= (uint)c;
                    bits_left  += 8;
                }                 // end while
            }

            if (cinfo.unread_marker != 0)
            {
                // We get here if we've read the marker that terminates the compressed
                // data segment. There should be enough bits in the buffer register
                // to satisfy the request; if so, no problem.
                if (nbits > bits_left)
                {
                    // Uh-oh. Report corrupted data to user and stuff zeroes into
                    // the data stream, so that we can produce some kind of image.
                    // We use a nonvolatile flag to ensure that only one warning message
                    // appears per data segment.
                    jpeg_entropy_decoder huffd;
#if D_LOSSLESS_SUPPORTED
                    if (cinfo.process == J_CODEC_PROCESS.JPROC_LOSSLESS)
                    {
                        huffd = (jpeg_entropy_decoder)((jpeg_lossless_d_codec)cinfo.coef).entropy_private;
                    }
                    else
#endif
                    huffd = (jpeg_entropy_decoder)((jpeg_lossy_d_codec)cinfo.coef).entropy_private;
                    if (!huffd.insufficient_data)
                    {
                        WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HIT_MARKER);
                        huffd.insufficient_data = true;
                    }
                    // Fill the buffer with zero bits
                    get_buffer <<= MIN_GET_BITS - bits_left;
                    bits_left    = MIN_GET_BITS;
                }
            }

            // Unload the local registers
            state.input_bytes     = input_bytes;
            state.next_input_byte = next_input_byte;
            state.bytes_in_buffer = bytes_in_buffer;
            state.get_buffer      = get_buffer;
            state.bits_left       = bits_left;

            return(true);
        }
Пример #11
0
        // 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.)
        static bool decode_mcu(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dshuff(cinfo))
                    {
                        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 (!entropy.insufficient_data)
            {
                bitread_working_state br_state = new bitread_working_state();

                savable_state_sq state;
                state.last_dc_val = new int[MAX_COMPS_IN_SCAN];

                // Load up working state
                //was BITREAD_STATE_VARS;
                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;

                //was state=entropy.saved;
                entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

                // Outer loop handles each block in the MCU
                for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
                {
                    short[]       block = MCU_data[blkn];
                    d_derived_tbl dctbl = entropy.dc_cur_tbls[blkn];
                    d_derived_tbl actbl = entropy.ac_cur_tbls[blkn];
                    int           s = 0, k, r;

                    // Decode a single block's worth of coefficients

                    // Section F.2.2.1: decode the DC coefficient difference
                    //was HUFF_DECODE(s, br_state, dctbl, return false, label1);
                    {
                        int  nb, look;
                        bool label = false;
                        if (bits_left < HUFF_LOOKAHEAD)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer;
                            bits_left  = br_state.bits_left;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                nb    = 1;
                                label = true;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }

                        if (!label)
                        {
                            //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                            look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                            if ((nb = dctbl.look_nbits[look]) != 0)
                            {
                                //was DROP_BITS(nb);
                                bits_left -= nb;
                                s          = dctbl.look_sym[look];
                            }
                            else
                            {
                                nb = HUFF_LOOKAHEAD + 1;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }
                    }

                    if (s != 0)
                    {
                        //was CHECK_BIT_BUFFER(br_state, s, return false);
                        if (bits_left < s)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                        }
                        //was r = GET_BITS(s);
                        r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                        //was s=HUFF_EXTEND(r, s);
                        s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);
                    }

                    if (entropy.dc_needed[blkn])
                    {
                        // Convert DC difference to actual value, update last_dc_val
                        int ci = cinfo.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)
                        block[0] = (short)s;
                    }

                    if (entropy.ac_needed[blkn])
                    {
                        // Section F.2.2.2: decode the AC coefficients
                        // Since zeroes are skipped, output area must be cleared beforehand
                        for (k = 1; k < DCTSIZE2; k++)
                        {
                            //was HUFF_DECODE(s, br_state, actbl, return false, label2);
                            {
                                int  nb, look;
                                bool label = false;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                    if (bits_left < HUFF_LOOKAHEAD)
                                    {
                                        nb    = 1;
                                        label = true;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }

                                if (!label)
                                {
                                    //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                    look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                    if ((nb = actbl.look_nbits[look]) != 0)
                                    {
                                        //was DROP_BITS(nb);
                                        bits_left -= nb;
                                        s          = actbl.look_sym[look];
                                    }
                                    else
                                    {
                                        nb = HUFF_LOOKAHEAD + 1;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }
                            }

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

                            if (s != 0)
                            {
                                k += r;
                                //was CHECK_BIT_BUFFER(br_state, s, return false);
                                if (bits_left < s)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was r = GET_BITS(s);
                                r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                                //was s=HUFF_EXTEND(r, s);
                                s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);


                                // 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.
                                block[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 (k = 1; k < DCTSIZE2; k++)
                        {
                            //was HUFF_DECODE(s, br_state, actbl, return false, label3);
                            {
                                int  nb, look;
                                bool label = false;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                    if (bits_left < HUFF_LOOKAHEAD)
                                    {
                                        nb    = 1;
                                        label = true;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }

                                if (!label)
                                {
                                    //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                    look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                    if ((nb = actbl.look_nbits[look]) != 0)
                                    {
                                        //was DROP_BITS(nb);
                                        bits_left -= nb;
                                        s          = actbl.look_sym[look];
                                    }
                                    else
                                    {
                                        nb = HUFF_LOOKAHEAD + 1;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }
                            }

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

                            if (s != 0)
                            {
                                k += r;
                                //was CHECK_BIT_BUFFER(br_state, s, return false);
                                if (bits_left < s)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was DROP_BITS(s);
                                bits_left -= s;
                            }
                            else
                            {
                                if (r != 15)
                                {
                                    break;
                                }
                                k += 15;
                            }
                        }
                    }
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;

                //was entropy.saved=state;
                state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Пример #12
0
        // MCU decoding for AC successive approximation refinement scan.
        static bool decode_mcu_AC_refine(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int   Se = cinfo.Se;
            short p1 = (short)(1 << cinfo.Al);                  // 1 in the bit position being coded
            short m1 = (short)((-1) << cinfo.Al);               // -1 in the bit position being coded

            short[] block = null;

            // 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[DCTSIZE2];

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // If we've run out of data, don't modify the MCU.
            if (!entropy.insufficient_data)
            {
                // Load up working state
                //was BITREAD_STATE_VARS;
                bitread_working_state br_state = new bitread_working_state();

                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;
                uint  EOBRUN     = entropy.saved.EOBRUN;          // only part of saved state we need

                // There is always only one block per MCU
                block = MCU_data[0];
                d_derived_tbl tbl = entropy.ac_derived_tbl;

                // initialize coefficient loop counter to start of band
                int k = cinfo.Ss;

                if (EOBRUN == 0)
                {
                    for (; k <= Se; k++)
                    {
                        int s = 0, r;

                        //was HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
                        {
                            int  nb, look;
                            bool label = false;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    nb    = 1;
                                    label = true;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }

                            if (!label)
                            {
                                //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                if ((nb = tbl.look_nbits[look]) != 0)
                                {
                                    //was DROP_BITS(nb);
                                    bits_left -= nb;
                                    s          = tbl.look_sym[look];
                                }
                                else
                                {
                                    nb = HUFF_LOOKAHEAD + 1;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }
                        }

                        r  = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            if (s != 1)
                            {
                                WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);                                  // size of new coef should always be 1
                            }
                            //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                            if (bits_left < 1)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was if (GET_BITS(1))
                            if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                            {
                                s = p1;                                                                      // newly nonzero coef is positive
                            }
                            else
                            {
                                s = m1;                            // newly nonzero coef is negative
                            }
                        }
                        else
                        {
                            if (r != 15)
                            {
                                EOBRUN = (uint)(1 << r);                             // EOBr, run length is 2^r + appended bits
                                if (r != 0)
                                {
                                    //was CHECK_BIT_BUFFER(br_state, r, goto undoit);
                                    if (bits_left < r)
                                    {
                                        if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r))
                                        {
                                            goto undoit;
                                        }
                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                    }
                                    //was r = GET_BITS(r);
                                    r       = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1);
                                    EOBRUN += (uint)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 thiscoef = jpeg_natural_order[k];
                            if (block[thiscoef] != 0)
                            {
                                //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                                if (bits_left < 1)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was if (GET_BITS(1))
                                if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                                {
                                    if ((block[thiscoef] & p1) == 0)
                                    {                                     // do nothing if already set it
                                        if (block[thiscoef] >= 0)
                                        {
                                            block[thiscoef] += p1;
                                        }
                                        else
                                        {
                                            block[thiscoef] += m1;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (--r < 0)
                                {
                                    break;                                       // reached target zero coefficient
                                }
                            }
                            k++;
                        } while(k <= Se);

                        if (s != 0)
                        {
                            int pos = jpeg_natural_order[k];
                            // Output newly nonzero coefficient
                            block[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 <= Se; k++)
                    {
                        int thiscoef = jpeg_natural_order[k];
                        if (block[thiscoef] != 0)
                        {
                            //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                            if (bits_left < 1)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was if (GET_BITS(1))
                            if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                            {
                                if ((block[thiscoef] & p1) == 0)
                                {                                 // do nothing if already changed it
                                    if (block[thiscoef] >= 0)
                                    {
                                        block[thiscoef] += p1;
                                    }
                                    else
                                    {
                                        block[thiscoef] += m1;
                                    }
                                }
                            }
                        }
                    }
                    // Count one block completed in EOB run
                    EOBRUN--;
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;
                entropy.saved.EOBRUN        = EOBRUN;        // only part of saved state we need
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);

undoit:
            // Re-zero any output coefficients that we made newly nonzero
            while (num_newnz > 0)
            {
                block[newnz_pos[--num_newnz]] = 0;
            }

            return(false);
        }
Пример #13
0
        // 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.
        static bool decode_mcu_DC_refine(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            short p1 = (short)(1 << cinfo.Al);          // 1 in the bit position being coded

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        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
            //was BITREAD_STATE_VARS;
            bitread_working_state br_state = new bitread_working_state();

            //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
            br_state.cinfo           = cinfo;
            br_state.input_bytes     = cinfo.src.input_bytes;
            br_state.next_input_byte = cinfo.src.next_input_byte;
            br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
            ulong get_buffer = entropy.bitstate.get_buffer;
            int   bits_left  = entropy.bitstate.bits_left;

            // Outer loop handles each block in the MCU
            for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
            {
                short[] block = MCU_data[blkn];

                // Encoded data is simply the next bit of the two's-complement DC value
                //was CHECK_BIT_BUFFER(br_state, 1, return false);
                if (bits_left < 1)
                {
                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                    {
                        return(false);
                    }
                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                }

                //was if(GET_BITS(1))
                if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                {
                    block[0] |= p1;
                }
                // Note: since we use |=, repeating the assignment later is safe
            }

            // Completed MCU, so update state
            //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
            cinfo.src.input_bytes       = br_state.input_bytes;
            cinfo.src.next_input_byte   = br_state.next_input_byte;
            cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
            entropy.bitstate.get_buffer = get_buffer;
            entropy.bitstate.bits_left  = bits_left;

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Пример #14
0
        // MCU decoding for AC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool decode_mcu_AC_first(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int Se = cinfo.Se;
            int Al = cinfo.Al;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        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 (!entropy.insufficient_data)
            {
                // Load up working state.
                // We can avoid loading/saving bitread state if in an EOB run.
                uint EOBRUN = entropy.saved.EOBRUN;               // only part of saved state we need

                // There is always only one block per MCU
                if (EOBRUN > 0)
                {
                    EOBRUN--;                          // if it's a band of zeroes... ...process it now (we do nothing)
                }
                else
                {
                    //was BITREAD_STATE_VARS;
                    bitread_working_state br_state = new bitread_working_state();

                    //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                    br_state.cinfo           = cinfo;
                    br_state.input_bytes     = cinfo.src.input_bytes;
                    br_state.next_input_byte = cinfo.src.next_input_byte;
                    br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                    ulong         get_buffer = entropy.bitstate.get_buffer;
                    int           bits_left  = entropy.bitstate.bits_left;
                    short[]       block      = MCU_data[0];
                    d_derived_tbl tbl        = entropy.ac_derived_tbl;

                    for (int k = cinfo.Ss; k <= Se; k++)
                    {
                        int s = 0, r;

                        //was HUFF_DECODE(s, br_state, tbl, return false, label2);
                        {
                            int  nb, look;
                            bool label = false;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    nb    = 1;
                                    label = true;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }

                            if (!label)
                            {
                                //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                if ((nb = tbl.look_nbits[look]) != 0)
                                {
                                    //was DROP_BITS(nb);
                                    bits_left -= nb;
                                    s          = tbl.look_sym[look];
                                }
                                else
                                {
                                    nb = HUFF_LOOKAHEAD + 1;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }
                        }

                        r  = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            k += r;
                            //was CHECK_BIT_BUFFER(br_state, s, return false);
                            if (bits_left < s)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was r = GET_BITS(s);
                            r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                            //was s=HUFF_EXTEND(r, s);
                            s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);

                            // Scale and output coefficient in natural (dezigzagged) order
                            block[jpeg_natural_order[k]] = (short)(s << Al);
                        }
                        else
                        {
                            if (r == 15)
                            {                             // ZRL
                                k += 15;                  // skip 15 zeroes in band
                            }
                            else
                            {                             // EOBr, run length is 2^r + appended bits
                                EOBRUN = (uint)(1 << r);
                                if (r != 0)
                                {                                 // EOBr, r > 0
                                    //was CHECK_BIT_BUFFER(br_state, r, return false);
                                    if (bits_left < r)
                                    {
                                        if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r))
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                    }
                                    //was r = GET_BITS(r);
                                    r       = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1);
                                    EOBRUN += (uint)r;
                                }
                                EOBRUN--;                                       // this band is processed at this moment
                                break;                                          // force end-of-band
                            }
                        }
                    }

                    //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                    cinfo.src.input_bytes       = br_state.input_bytes;
                    cinfo.src.next_input_byte   = br_state.next_input_byte;
                    cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                    entropy.bitstate.get_buffer = get_buffer;
                    entropy.bitstate.bits_left  = bits_left;
                }

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

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Пример #15
0
        // 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.)

        // MCU decoding for DC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool decode_mcu_DC_first(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int Al = cinfo.Al;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        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 (!entropy.insufficient_data)
            {
                // Load up working state
                //was BITREAD_STATE_VARS;
                bitread_working_state br_state = new bitread_working_state();

                savable_state state;
                state.last_dc_val = new int[MAX_COMPS_IN_SCAN];

                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;

                //was state=entropy.saved;
                state.EOBRUN = entropy.saved.EOBRUN;
                entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

                // Outer loop handles each block in the MCU
                for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
                {
                    short[]             block   = MCU_data[blkn];
                    int                 ci      = cinfo.MCU_membership[blkn];
                    jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                    d_derived_tbl       tbl     = entropy.derived_tbls[compptr.dc_tbl_no];

                    int s = 0;

                    // Decode a single block's worth of coefficients

                    // Section F.2.2.1: decode the DC coefficient difference
                    //was HUFF_DECODE(s, br_state, tbl, return false, label1);
                    {
                        int  nb, look;
                        bool label = false;
                        if (bits_left < HUFF_LOOKAHEAD)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer;
                            bits_left  = br_state.bits_left;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                nb    = 1;
                                label = true;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }

                        if (!label)
                        {
                            //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                            look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                            if ((nb = tbl.look_nbits[look]) != 0)
                            {
                                //was DROP_BITS(nb);
                                bits_left -= nb;
                                s          = tbl.look_sym[look];
                            }
                            else
                            {
                                nb = HUFF_LOOKAHEAD + 1;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }
                    }

                    if (s != 0)
                    {
                        //was CHECK_BIT_BUFFER(br_state, s, return false);
                        if (bits_left < s)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                        }
                        //was r = GET_BITS(s);
                        int r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                        //was s=HUFF_EXTEND(r, s);
                        s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);
                    }

                    // 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)
                    block[0] = (short)(s << Al);
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;

                //was entropy.saved=state;
                entropy.saved.EOBRUN = state.EOBRUN;
                state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }