⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class1.cs

📁 mpeg4压缩算法程序
💻 CS
📖 第 1 页 / 共 2 页
字号:
					run++;
					arrayPosition++;
				}

				// Read in the AC value after the zeros
				AC = zz[arrayPosition];
				arrayPosition++;

				//	Set up exit condition from loop if at end of block
				if (arrayPosition >= 63)
				{
					//	Reset other values
					AC = 0;
					run = 0;
					ACbits = ACindex;
					ACindex = MAXACSIZE + 200;
				}

				//	Determine Huffman code and number of bits needed to
				//	represent the run,level combination.  See MPEG1 spec.
				if ((run<=31) && (Math.Abs(AC)==1))
				{
					code=ACcode[run];
					size=ACsize[run];
					//	If AC is negative, the sign bit in the Huffman code
					//	equals 1, else it equals 0. So if negative, add 1 to code.
					if (AC < 0)
						code += 1;
				}
				else if ((run<=16) && (Math.Abs(AC)==2))
				{
					code=ACcode[32+run];
					size=ACsize[32+run];
					if (AC < 0)
						code += 1;
				}
				else if ((run<=6) && (Math.Abs(AC)==3))
				{
					code=ACcode[49+run];
					size=ACsize[49+run];
					if (AC < 0)
						code += 1;
				}
				else if ((run<=3) && (Math.Abs(AC)==4))
				{
					code=ACcode[56+run];
					size=ACsize[56+run];
					if (AC < 0)
						code += 1;
				}
				else if ((run<=2) && (Math.Abs(AC)==5))
				{
					code=ACcode[60+run];
					size=ACsize[60+run];
					if (AC < 0)
						code += 1;
				}
				else if ((run<=1) && ((Math.Abs(AC)>=6) && (Math.Abs(AC)<=18)))
				{
					code=ACcode[63+run+((Math.Abs(AC)-6)*2)];
					size=ACsize[63+run+((Math.Abs(AC)-6)*2)];
					if (AC < 0)
						code += 1;
				}
				else if ((run==0) && ((Math.Abs(AC)>=19) && (Math.Abs(AC)<=40)))
				{
					code=ACcode[89+Math.Abs(AC)-19];
					size=ACsize[89+Math.Abs(AC)-19];
					if (AC < 0)
						code += 1;
				}
				else if ((run==0) && (AC==0))	// EOB condition
				{
					code = 2;
					size = 2;
				}
				else
				{
					code = escapecode(run, AC);
					if (Math.Abs(AC) >= 128)
						size = 28;
					else
						size = 20;
				}

				// Write bits for Huffman code into bits[] array
				tempval = (int) Math.Pow(2,size-1);
				for (i=0; i<size; i++)
				{
					tempbits = code & tempval;
					outBits[i+outbitsPosition]  = (byte) (tempbits >> (size-i-1));
					tempval >>= 1;
				}

				outbitsPosition += size;

				// Increase index for bits array (don't exceed array size) 
				ACindex += size;
			}

			return outBits;
		}
	
		//	Function that calculates the Huffman code value for MPEG run,level
		//	combinations that don't have defined codes.
		private int escapecode(int run, int AC)
		{
			int intval = 0;
			int code = 0;

			//	Last 8 or 16 bits in the code are the AC value
			//	For positve values, use normal binary encoding.
			//	For negative values from -1 to -127, use 2's complement value.
			//	For negative values from -128 to -255, use 16 bit value with MSB=1,
			//	and 2's complement of AC.
			if (AC > 0)
				intval = AC;
			else
			{
				if (AC >= -127)
					intval = 256 + AC;
				else 
					intval = 32768 + 256 + AC;
			}

			//	Construct escape code using 000001 as first 6 bits, 
			//	binary representation of run as next 6 bits,
			//	and either 8 or 16 bits representation of AC from above.
			if (Math.Abs(AC) < 128)
				code = 16384 + 256*run + intval;
			else
				code = 4194304 + 65536*run + intval;

			return (code);
		}

		// Write the Macroblock header for I frame blocks
		public void writeMbHeader(byte[] left)
		{
			int i = 0;

			//	Search leftoverBits[] for first -1 value
			while (left[i] !=  255)
				i++;

			//	Write MB Header values '1 1' to leftoverBits[]
			left[i++] = 1;
			left[i] = 1;
		}

		//	Function to take the encoded bits from the latest block and
		//	write them to a memory stream
		public void writeToMS(byte[] left, byte[] DC, byte[] AC, ref long outBytes)
			{
			int i, j, bytevalue, leftBits;
			byte[] bitArray = new byte[2100];
			int bitIndex = 0;
			int outputbytes = 0;

			// The worst case is 63 AC values that are each 28 bits long 
			// plus a 24 bit DC value
			for (i=0; i<2100; i++)
				bitArray[i] = 0;

			//	Write the leftover bits from the previous block to bitArray[]
			i = 0;
			while (left[i] != 255)
				bitArray[bitIndex++] = left[i++];

			//	Write the DC bits from the current block to bitArray[]
			i = 0;
			while (DC[i] != 255)
				bitArray[bitIndex++] = DC[i++];

			//	Write the AC bits from the current block to bitArray[]
			i = 0;
			while (AC[i] != 255)
				bitArray[bitIndex++] = AC[i++];

			//	Calculate the number of bytes to write to the MemoryStream and 
			//	how many bits will be left over
			outputbytes = bitIndex / 8;
			leftBits = bitIndex % 8;

			//	Write the bytes to the MemoryStream
			for (i=0; i<outputbytes; i++)
			{
				bytevalue = 0;
				for (j=0; j<8; j++)
					bytevalue += (int) ((bitArray[i*8 + j] * Math.Pow(2,(7-j))));
				ms.WriteByte((byte) bytevalue);
			}

			//	Store the leftover bits in left[] and fill the rest with -1's
			for (i=0; i<leftBits; i++)
				left[i] = bitArray[outputbytes*8 + i];
			for (i=leftBits; i<10; i++)
				left[i] = 255;

			outBytes += outputbytes;
		}

		//	Function to write the final leftover bits to the memoryStream and
		//	then stuff with 0's to byte align for next picture
		public void writeEOP(byte[] left, byte[] EOP)
		{
			int i;
			int j, leftBits;
			int bytevalue;
			byte[] bitArray = new byte[20];
			int bitIndex = 0;
			int outputbytes = 0;

			for (i=0; i<20; i++)
				bitArray[i] = 0;

			//	Write the leftover bits from the previous block to bitArray[]
			i=0;
			while (left[i] != 255)
				bitArray[bitIndex++] = left[i++];

			//	Write the EOP bits from the current block to bitArray[]
			i=0;
			while (EOP[i] != 255)
				bitArray[bitIndex++] = EOP[i++];

			//	Calculate the number of bytes to write to the MemoryStream and 
			//	how many bits will be left over
			outputbytes = bitIndex / 8;
			leftBits = bitIndex % 8;

			//	If one full byte needs to be written
			if (outputbytes == 1)
			{
				bytevalue = 0;
				for (j=0; j<8; j++)
					bytevalue = (byte) (2*bytevalue + bitArray[j]);
				ms.WriteByte((byte) bytevalue);
			}
				//	Else pad leftover bits with zeros and write to MemoryStream
			else
			{
				bytevalue = 0;
				for (j=0; j<8; j++)
					bytevalue = (byte) (2*bytevalue + bitArray[j]);
				ms.WriteByte((byte) bytevalue);
			}

			//	Leftover is cleared so re-initialize leftover bits to -1's
			for (j=0; j<10; j++)
				left[j] = 255;
		}

		// Function to get the Y values for an RGB macroblock
		// pointed to by [vblock,hblock] out of Bitmap img
		public byte[,] getYMatrix(Bitmap img, int vblock, int hblock)
		{
			int i, j;
			double tempdouble;
			byte[,] Y = new byte[16,16];

			for (i=0; i<16; i++)
				for (j=0; j<16; j++)
				{
					tempdouble = (219.0*(0.59*img.GetPixel((hblock*16 + j),(vblock*16 + i)).R +
						0.30*img.GetPixel((hblock*16 + j),(vblock*16 + i)).G + 
						0.11*img.GetPixel((hblock*16 + j),(vblock*16 + i)).B) / 255.0) + 16.0;
					Y[i,j] = (byte) (Math.Round(tempdouble));	// Y is limited from 16 to 235
				}
			return Y;
		}

		// Function to get the CR values for an RGB macroblock
		// pointed to by [vblock,hblock] out of Bitmap img
		// In MPEG1, use subsampling to make one 8x8 block of Pr values
		public byte[,] getCRMatrix(Bitmap img, int vblock, int hblock)
		{
			int i, j;
			double tempdouble;
			byte[,] CR = new byte[8,8];

			for (i=0; i<8; i++)
				for (j=0; j<8; j++)
				{
					tempdouble = (224.0*(0.50*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).R -
						0.42*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).G - 
						0.08*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).B) / 255.0) + 128.0;
					CR[i,j] = (byte) (Math.Round(tempdouble));	// Cr is limited from 16 to 235
				}
			return CR;
		}

		// Function to get the CB values for an RGB macroblock
		// pointed to by [vblock,hblock] out of Bitmap img
		// In MPEG1, use subsampling to make one 8x8 block of Pb values
		public byte[,] getCBMatrix(Bitmap img, int vblock, int hblock)
		{
			int i, j;
			double tempdouble;
			byte[,] CB = new byte[8,8];

			for (i=0; i<8; i++)
				for (j=0; j<8; j++)
				{
					tempdouble = (224.0*(-0.17*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).R -
						0.33*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).G + 
						0.50*img.GetPixel((hblock*16 + j*2),(vblock*16 + i*2)).B) / 255.0) + 128.0;
					CB[i,j] = (byte) (Math.Round(tempdouble));	// Cb is limited from 16 to 235
				}
			return CB;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -