Click here to Skip to main content
Licence 
First Posted 12 Jan 2004
Views 154,410
Bookmarked 49 times

A C# MPEG1 Image Compression Class

By | 22 Jan 2004 | Article
This article shows how to compress an image using the MPEG1 format

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

About the Author

Mike Donovan

Engineer

United States United States

Member

I hold the Division 1 record for most hours slept in a college semester.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questioncompressing image to save space in DB and avoid slow of dataflow in a network PinmemberMember 87648576:11 27 Mar '12  
GeneralDecompression PinmemberMylumca23:33 18 Feb '09  
Generalimage decompression PinmemberMylumca23:31 18 Feb '09  
QuestionCan you implements the MPEG4 Image Compression Class in CSharp PinmemberMember 467890418:40 19 Aug '08  
GeneralAVI TO MPEG Pinmemberpratik_at_work18:47 3 Feb '08  
GeneralHard coded frame rate Pinmembersamjindal0:08 18 Oct '07  
Generalmpeg format Pinmembercua23:09 14 May '07  
GeneralDirectShow.NET PinmemberBarryDorman11:08 15 Feb '07  
The DirectShow Class Library is a good way to convert a sequence of images into a video file. The DirectShow algorithm takes the other frames into account too. This can save a lot of space, especially if the background doesn't change much. However, this is still a great article and a wonderful learning tool, thanks for the contribution.
QuestionReal time vedio capturing PinmemberMember #248359418:06 11 Feb '07  
QuestionFrame and Compression Rates PinmemberRichard Moult5:44 10 Jan '07  
GeneralThanx Mike Pinmemberjunaid1091:43 11 Oct '06  
Generalmedia player Pinmemberxenia gr22:39 3 Sep '06  
GeneralHELP Pinmemberhghgc20:42 31 Aug '06  
GeneralSequence PinmemberKladrian7:20 9 Jul '06  
GeneralRe: Sequence PinmemberUsman Syed22:05 18 Dec '06  
GeneralRe: Sequence Pinmembersamjindal22:32 22 Oct '07  
QuestionBroken exe file ? Pinmemberm0w3:58 31 Mar '06  
Questionhow to build dll file? Pinmemberuumeme4:57 2 Feb '06  
GeneralResolution of the image is changed Pinmemberjjohn200523:10 26 Jan '06  
GeneralMultiple BMPs PinmemberLego3:12 21 Oct '04  
Questionhow to write data in jpeg PinsussAnonymous21:44 9 Sep '04  
GeneralNice work PinmemberRonnie Wulfsohn6:41 2 May '04  
QuestionHow Can I change From MPEG Fuctions to JPEG Functions PinsussDevXII0:17 1 May '04  
GeneralGot Confused!!! PinsussDEV0523:12 30 Apr '04  
Generalmpeg-1 Pinmemberniveen47:30 19 Apr '04  

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

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120529.1 | Last Updated 23 Jan 2004
Article Copyright 2004 by Mike Donovan
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid