📄 class1.cs
字号:
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 + -