📄 class1.cs
字号:
using System;
using System.IO;
using System.Drawing;
namespace BitmapImage
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class MPEGFunctions
{
// Class of functions and variables needed to encode images
// using the MPEG1 format
// The MemoryStream ms is provided to store the bitstream
// produced by encoding the image's blocks
private MemoryStream ms = new MemoryStream();
private double[,] cosine = new double[8,8];
private double SQRT2o2 = Math.Sqrt(2.0) / 2.0;
// MPEG1 default quantization matrix
private byte[,] defaultQ = new byte[8,8] {{8,16,19,22,26,27,29,34},
{16,16,22,24,27,29,34,37},
{19,22,26,27,29,34,34,38},
{22,22,26,27,29,34,37,40},
{22,26,27,29,32,35,40,48},
{26,27,29,32,35,40,48,58},
{26,27,29,34,38,46,56,69},
{27,29,35,38,46,56,69,83}};
// MPEG1 default DC Huffman codes
public int[] DCLumCode = new int[9] {4, 0, 1, 5, 6, 14, 30, 62, 126};
public int[] DCLumSize = new int[9] {3, 2, 2, 3, 3, 4, 5, 6, 7};
public int[] DCChromCode = new int[9] {0, 1, 2, 6, 14, 30, 62, 126, 254};
public int[] DCChromSize = new int[9] {2, 2, 2, 3, 4, 5, 6, 7, 8};
// MPEG1 default AC Huffman codes
private int[] ACcode = new int[111] {
6,6,10,14,12,14,10,8,14,10,78,70,68,64,28,26,16, // AC=1, run=0->16
62,52,50,46,44,62,60,58,56,54,62,60,58,56,54, // AC=1, run=17->31
8,12,8,72,30,18,60,42,34,34,32,52,50,48,46,44,42, // AC=2, run=0->16
10,74,22,56,36,36,40, // AC=3, run=0->6
12,24,40,38, // AC=4, run=0->3
76,54,40, // AC=5, run=0->2
66,44, // AC=6
20,42,
58,62,
48,60,
38,58,
32,56,
52,54,
50,52,
48,50,
46,38,
62,36,
62,34,
58,32,
56,54,52,50,48,46,44,42,40,38,36,34,32, // AC=19->31, run=0
48,46,44,42,40,38,36,34,32}; // AC=32->40, run=0
private int[] ACsize = new int[111] {
3,4,5,6,6,7,7,7,8,8,9,9,9,9,11,11,11, // AC=1, run=0->16
13,13,13,13,13,14,14,14,14,14,17,17,17,17,17, // AC=1, run=17->31
5,7,8,9,11,11,13,13,13,14,14,17,17,17,17,17,17, // AC=2, run=0->16
6,9,11,13,13,14,17, // AC=3, run=0->6
8,11,13,14, // AC=4, run=0->3
9,13,14,
9,14,
11,14,
13,16,
13,16,
13,16,
13,16,
14,16,
14,16,
14,16,
14,17,
15,17,
15,17,
15,17,
15,15,15,15,15,15,15,15,15,15,15,15,15, // AC=19->31, run=0
16,16,16,16,16,16,16,16,16}; // AC=32->40, run=0
// MPEG1 sequence header
public byte[] seqHeaderBits = new byte[100]
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,1, // Sequence Header
0,0,0,1,0,1,1,0,0,0,0,0, // HSize = 352
0,0,0,0,1,1,1,1,0,0,0,0, // VSize = 240
1,1,0,0,0,1,0,0, // Pel Shape=1.125,Picture Rate=29.97
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // Bit Rate = 4096*400
1, // Marker Bit
0,0,0,0,0,1,0,1,0,0, // VBV Buffer Size = 20 * 16384
0,0,0,255,255,255,255};
// MPEG1 GOP header
public byte[] GOPHeaderBits = new byte[68]
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0, // GOP Header
1,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0, // Time Code = 00:00:00
1,0,0,0,0,0,0,255,255,255,255}; // Closed GOP, Broken Link
// MPEG1 picture header
public byte[] picHeaderBits = new byte[68]
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, // Picture Header
0,0,0,0,0,0,0,0,0,0, // Temporal Reference
0,0,1, // Picture Type = I Frame
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // VBV Delay = 32768
0,0,0,255,255,255,255};
// MPEG1 slice header
public byte[] sliceHeaderBits = new byte[44]
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, // Slice Header
0,1,0,0,0, // Q Scale = 8
0,255,255,255,255,255,255}; // Extra Slice Bit
public byte[] EOPBits = new byte[8] {255,255,255,255,255,255,255,255};
public MPEGFunctions()
{
int i, j;
// Calculate frequently used cosine matrix
for (i=0; i<8; i++)
for (j=0; j<8; j++)
cosine[j,i] = Math.Cos(Math.PI*j*(2.0*i + 1)/16.0);
}
// The memory stream can be used to store the encoded picture
// by using the writeToMS function anytime a block is encoded
public MemoryStream getMS()
{
return ms;
}
// Perform the DCT on the A block
// See the JPEG DCT definition for the formula
public double[,] calculateDCT (byte[,] A)
{
int k1, k2, i, j;
double Cu, Cv;
double[,] B = new double[8,8];
for (k1=0; k1<8; k1++)
for (k2=0; k2<8; k2++)
{
B[k1,k2] = 0.0;
for (i=0; i<8; i++)
for (j=0; j<8; j++)
B[k1,k2] += A[i,j] * cosine[k1,i] * cosine[k2,j];
if (k1==0)
Cu = SQRT2o2;
else
Cu = 1.0;
if (k2==0)
Cv = SQRT2o2;
else
Cv= 1.0;
B[k1,k2] *= (0.25*Cu*Cv);
}
return B; // Return Frequency Component matrix
}
// Quantize the DCT coefficients using the defaultQ array
// In MPEG, always divide the DC value by eight
public int[,] Quantize (double[,] S)
{
int i, j;
int[,] S1 = new int[8,8];
for (i=0; i<8; i++)
for (j=0; j<8; j++)
S1[i,j] = (int) Math.Round((S[i,j] / (double) defaultQ[i,j]));
return S1; // Return quantized Frequency Component matrix
}
// Quantize the DCT coefficients using the supplied Q array
// In MPEG, always divide the DC value by eight
public int[,] Quantize (double[,] S, double[,] Q)
{
int i, j;
int[,] S1 = new int[8,8];
for (i=0; i<8; i++)
for (j=0; j<8; j++)
S1[i,j] = (int) Math.Round((S[i,j] / Q[i,j]));
return S1; // Return quantized Frequency Component matrix
}
// Function to encode the DC values
public byte[] DCHuffmanEncode(int DC, int[] eco, int[] esi)
{
byte[] DCbits = new byte[24];
int cat, tempval, i;
bool invert;
int tempbits;
for (i=0; i<24; i++)
DCbits[i] = 255;
// Set flag if DC is negative
invert = false;
if (DC<0)
invert = true;
DC = Math.Abs(DC);
// Determine the number of bits needed to represent DC
cat = 0;
tempval = DC;
while (tempval >= 1)
{
cat++;
tempval >>= 1;
}
// Write bits for Huffman code into DCbits[] array
tempval = (int) Math.Pow(2, esi[cat]-1);
for (i=0; i<esi[cat]; i++)
{
tempbits = eco[cat] & tempval;
DCbits[i] = (byte) (tempbits >> (esi[cat] - 1 - i));
tempval >>= 1;
}
// Write bits for DC into DCbits[] array
tempval = (int) Math.Pow(2, cat-1);
for (i=esi[cat]; i<esi[cat]+cat; i++)
{
tempbits = DC & tempval;
DCbits[i] = (byte) (tempbits >> (cat-1-i+esi[cat]));
tempval >>= 1;
}
// If necessary, invert bits to represent negative DC
if (invert)
for (i=esi[cat]; i<esi[cat]+cat; i++)
{
if (DCbits[i] == 0)
DCbits[i] = 1;
else
DCbits[i] = 0;
}
return DCbits; // Return array of bits representing DC value
}
// Re order all coefficients after DCT is performed
public int[] Zigzag (int[,] S1)
{
int[] index = new int[64] {0,1,7,8,-7,-7,1,7,7,7,8,
-7,-7,-7,-7,1,7,7,7,7,7,8,
-7,-7,-7,-7,-7,-7,1,7,7,7,7,7,7,7,1,
-7,-7,-7,-7,-7,-7,8,7,7,7,7,7,1,
-7,-7,-7,-7,8,7,7,7,1,
-7,-7,8,7,1};
int i;
int[] zz = new int[64];
int a, b;
int S1pointer = 0;
for (i=0; i<64; i++)
{
S1pointer += index[i];
a = S1pointer/8;
b = S1pointer%8;
zz[i] = S1[a,b];
}
return zz; // Return sorted array with DC value at position 0
}
// This function takes the array pointed to by zz and encodes
// the values using the Huffman code pointed to by eco[].
public byte[] ACHuffmanEncode(int[] zz)
{
int MAXACSIZE = 1764; // 63 AC Values * 28 bits
byte[] outBits = new byte[MAXACSIZE];
int run, tempval;
int ACindex = 0;
int i, AC;
int arrayPosition;
int ACbits;
int size;
int code;
int outbitsPosition;
int tempbits;
for (i=0; i<MAXACSIZE; i++)
outBits[i] = 255;
// Start at zz[1] since don't want to include DC value
// Do this to the end of the zz array
arrayPosition = 1;
outbitsPosition = 0;
while (ACindex < MAXACSIZE - 28)
{
// First figure out how many consecutive zeros
run = 0;
while ((zz[arrayPosition]==0) && (arrayPosition<63))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -