Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#
Article

A C# MPEG1 Image Compression Class

Rate me:
Please Sign up or sign in to vote.
4.73/5 (25 votes)
22 Jan 20046 min read 239.1K   7.7K   54   53
This article shows how to compress an image using the MPEG1 format

Image 1

Introduction

There is a lot of support in C# for image conversion and compression, but I have never found a good tool to convert images into the MPEG format. I wish someone had done it for me, but since they didn't I wrote a class called MPEGFunctions that provides the functions you need to convert a bitmap image to an MPEG1 I Frame. The code is functional but definitely not optimized or efficient. I think the MPEGFunctions class and the provided sample application are a pretty good learning tool if you want to learn more about MPEG image compression.

There are a couple reasons why I needed a program like this. The first is that I have some MPEG animations on my web site, and I wanted to put up a short title screen at the beginning of the video clips. I can create a title screen using something like Microsoft Paint, convert it to an MPEG sequence of 2 second duration, and then play it with Windows Media Player (Media Player won't display JPEGs but will display my MPEG sequences). Another reason is I work with digital set top boxes, and I needed a way to create MPEG still frames that the boxes could display. Set top boxes are good at rendering MPEG but usually can't display JPEGs.

Background

The MPEG1 standard (ISO/IEC 11172 Part 2) describes the process used to encode and compress an image into the MPEG1 format. A good tutorial link I found on the web that helped me a lot can be found here:

or do a Google search on: jpeg dct cmpt365.

The source code for the MPEGFunctions class is in the file named Class1.cs. The source code for the ImageFunctions class is in the ImageFunctions.cs file.

The simplest MPEG frame type is the I Frame. To convert an image to an MPEG I Frame you need to start with an RGB bitmap and go through the following steps:

  1. Pad the bitmap in both the height and width dimensions so that the bitmap dimensions are even multiples of 16. You need to do this because the basic building block of an MPEG image is a 16x16 pixel macro block. Use the ImageFunctions.padWidth and ImageFunctions.padHeight functions.
  2. Break the image into 16x16 pixel macro blocks.
  3. For each macroblock create 4 8x8 pixel Y blocks, and sub sample the macro block to create 1 8x8 pixel CR block and 1 8x8 pixel CBblock. Convert the RGB values for the pixels into Y, CR, and CB color components. Use the MPEGFunctions.getYMatrix, MPEGFunctions.getCRMatrix, and MPEGFunctions.getCBMatrix functions.
  4. Calculate the Discrete Cosine Transform (DCT) for each block. Use the MPEGFunctions.calculateDCT function.
  5. Quantize the DCT coefficients. Use the MPEGFunctions.Quantize function.
  6. Rearrange the DCT coefficients for each block using a zigzag scan. Use the MPEGFunctions.Zigzag function.
  7. Calculate the Huffman Code sequences for the DC DCT coefficients. Use the MPEGFunctions.DCHuffmanEncode function.
  8. Calculate the Huffman Code sequences for the AC DCT coefficients. Use the MPEGFunctions.ACHuffmanEncode function.
  9. Repeat steps 3 through 8 for each macro block in the image.
  10. Write the MPEG headers, Huffman Codes, and MPEG trailers to a memory stream, file, or other output format.

Using the code

The sample application shows how to use the MPEGFunctions class.

  • Use File->Open to select any C# supported image format (GIF, JPEG, BMP, etc.). The image will be placed into pictureBox1. If the image is smaller than 352x352 pixels it will be displayed at its normal size. If it is bigger, it will be stretched/squeezed to fit in the 352x352 picture box. The image will be padded if necessary to make the dimensions evenly divisible by 16.
  • If you select WriteToFile->MPEG IFrame the image will be converted to an MPEG1 IFrame and written to the selected output file. You can open the output file with Windows Media Player and it will display.
  • If you select WriteToFile->MPEG Sequence the image will be converted to an IFrame. The converted image will be repeated for the number of frames selected in the dialog box. The entire sequence will be written to the selected output file. You can open the output file with Windows Media Player and it will play at a rate of 30 frames per second.
  • If you click on a location in pictureBox1 the associated 16x16 pixel macroblock will be displayed in pictureBox2. The macroblock is stretched to fit the pictureBox2 dimensions.
  • If you select the "Block Details" button you will be taken to a new dialog box where you can see the R, G, and B pixel values for the macroblock.
  • If you select the "Convert To YPrPb" button you will be taken to a new dialog box where you can see the Y, Pr, and Pb values for the macroblock.
  • If you select the "Calculate DCT" button you will be taken to a new dialog box where the DCT transformed values for the selected block will be displayed.
  • If you select the "Quantize" button you can see the results of the quantization step.
  • If you select the "ZigZag Order" button you can see the results of reordering the DCT coefficients.
  • If you select "DC Encode" you can see the binary string produced by Huffman encoding the DC value.
  • If you select "AC Encode" you can see the binary string produced by Huffman encoding the AC values.

Points of Interest

MPEG I Frames are very similar to JPEG images, in fact the process to create a JPEG is virtually identical to MPEG. The syntax of the final bitstream is different, but with some simple changes you could turn the MPEGFunctions class into a JPEGFunctions class. However, in C# it is so simple to save images as JPEGs that it really isn't necessary. You can see how simple it is to convert a bitmap to JPEG in my sample application in the UserControl1.WriteJPEG function.

MPEG is not really designed to be a format for single image compression. It is actually supposed to be used for video compression, and a lot of its usefulness comes from using previous and future video frames to make predictions for what any single video frame will look like. These are called P and B frames and allow video to be compressed even more efficiently than if only I Frames are used.

Conclusion

So far I can only do MPEG I frames, but I hope to keep going with this project and add the functions needed to create MPEG P and B frames. I will also create a JPEGFunctions class someday that is similar to the MPEGFunctions class. Hopefully in 3 months or so there will be an update to this project.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Engineer
United States United States
I hold the Division 1 record for most hours slept in a college semester.

Comments and Discussions

 
SuggestionBugfix and optimizations Pin
Member 1012304426-May-14 2:37
Member 1012304426-May-14 2:37 
GeneralRe: Bugfix and optimizations Pin
jfriedman13-Jun-14 9:40
jfriedman13-Jun-14 9:40 
GeneralMy vote of 5 Pin
jfriedman30-Oct-12 15:59
jfriedman30-Oct-12 15:59 
Questioncompressing image to save space in DB and avoid slow of dataflow in a network Pin
Member 876485727-Mar-12 6:11
Member 876485727-Mar-12 6:11 
GeneralDecompression Pin
Mylumca18-Feb-09 23:33
Mylumca18-Feb-09 23:33 
Generalimage decompression Pin
Mylumca18-Feb-09 23:31
Mylumca18-Feb-09 23:31 
QuestionCan you implements the MPEG4 Image Compression Class in CSharp Pin
Member 467890419-Aug-08 18:40
Member 467890419-Aug-08 18:40 
GeneralAVI TO MPEG Pin
pratik_at_work3-Feb-08 18:47
pratik_at_work3-Feb-08 18:47 
GeneralHard coded frame rate Pin
samjindal18-Oct-07 0:08
samjindal18-Oct-07 0:08 
Generalmpeg format Pin
cua14-May-07 23:09
cua14-May-07 23:09 
GeneralDirectShow.NET Pin
Barry Dorman15-Feb-07 11:08
Barry Dorman15-Feb-07 11:08 
QuestionReal time vedio capturing Pin
Member 248359411-Feb-07 18:06
Member 248359411-Feb-07 18:06 
QuestionFrame and Compression Rates Pin
Richard Moult10-Jan-07 5:44
Richard Moult10-Jan-07 5:44 
GeneralThanx Mike Pin
junaid10911-Oct-06 1:43
junaid10911-Oct-06 1:43 
Generalmedia player Pin
xenia gr3-Sep-06 22:39
xenia gr3-Sep-06 22:39 
GeneralHELP Pin
xenia gr31-Aug-06 20:42
xenia gr31-Aug-06 20:42 
GeneralSequence Pin
Kladrian9-Jul-06 7:20
Kladrian9-Jul-06 7:20 
GeneralRe: Sequence Pin
Usman Syed18-Dec-06 22:05
Usman Syed18-Dec-06 22:05 
GeneralRe: Sequence Pin
samjindal22-Oct-07 22:32
samjindal22-Oct-07 22:32 
QuestionBroken exe file ? Pin
m0w31-Mar-06 3:58
m0w31-Mar-06 3:58 
Questionhow to build dll file? Pin
uumeme2-Feb-06 4:57
uumeme2-Feb-06 4:57 
GeneralResolution of the image is changed Pin
jjohn200526-Jan-06 23:10
jjohn200526-Jan-06 23:10 
GeneralMultiple BMPs Pin
Lego21-Oct-04 3:12
Lego21-Oct-04 3:12 
Questionhow to write data in jpeg Pin
Anonymous9-Sep-04 21:44
Anonymous9-Sep-04 21:44 
hi all,
i am currently working on image compression . encountered a problem that after encoding(huffman and run length) the image(BMP). i got the binary coeff. can anybody tell me how to write this data in a jped file and display it.
regards
sambhav
kumar@brandwidthtech.com
GeneralNice work Pin
Ronnie Wulfsohn2-May-04 6:41
Ronnie Wulfsohn2-May-04 6:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.