Skip to content

Compresses bmp files into a compressed format, and allows for their viewing.

Notifications You must be signed in to change notification settings

misingnoglic/jpeg_compresser

Repository files navigation

Jpeg Project Description

This is the description of my program - how to use it and how it works. Keep in mind that it works on both color and grayscale bitmaps. To use it, you need to install the numpy and Pillow libraries, and you need to run it on Python 3.6.

How to use

The program, jpeg_compressor.py, is a python program that runs with command line arguments. If you don’t want to deal with command line arguments, you can just pass the --interactive argument to have the program prompt you. You can run jpeg_compressor.py -h for all the arguments. The most important one is --action {compress,decompress,both}

If your action is "compress" or “both,” you need to have these options:

  --originalfile ORIGINALFILE

                        Filename for compressed file(either for storing the

                        compressed file or reading it.

  --compressedfile COMPRESSEDFILE

                        Filename for compressed file(either for storing the

                        compressed file or reading it.

  --blocksize BLOCKSIZE

                        Block size for image (for compression)

  --qualityfactor QUALITYFACTOR

                        Quality Factor (generally 30,40, 50)

  --compressionmethod {gzip,zlib,bzip,xz}

                        Compression Method

If your action is decompress, you only need to supply the "compressedfile" and “compressionmethod” arguments. For all actions, you can also supply this argument.

--verbose Prints Messages

If you want the program to annotate what it’s doing, plus tell you the compression ratios. For example:

python jpeg_compressor.py --action both --verbose --originalfile Kodak12gray.bmp --compressedfile file.gz --blocksize 8 --qualityfactor 50 --compressionmethod gzip

This command will first compress "Kodak12gray.bmp" into file.gz, with a blocksize of 8, quality factor of 50, and compress with gzip. It will then uncompress file.gz with gzip, and display the image. Because --verbose is turned on, the program will also print out what it’s doing.

An example of a decompress call to the above image:

python jpeg_compressor.py --action decompress --verbose --compressedfile file.gz --compressionmethod gzip

Notice how for the decompression, you just have to specify the filename and the compression method, since information like the block size is encoded in the image.

How the Program Works:

The code is fairly heavily commented, so I will just give a brief overview of how my program works. The main data structures used are the numpy matrices, and the PIL image format, which is used for reading and writing images.

To compress, the program first reads in the image as a numpy matrix, and then decides whether to send it to the color compressor or the grayscale compressor. These are the steps the compressor takes:

  1. Read the image as a matrix

  2. Crop the image to the block size

  3. Level the matrix by subtracting 128

  4. On each block of the matrix:

    1. Perform the DCT (generate DCT matrix, do dct_matrix * block * transform_dct_matrix)

    2. Quantize it (using the quantization matrix from the standard, modified with the quality factor).

    3. Get all of the items in the zig-zag order and add them to a list

    4. Add the DC component to a list of DC component

  5. Add the DC components in front of the zig_zag list

  6. Encode the height and width of the image into two bytes, using the formula:

high_byte = n/(block_size * 255)
low_byte = (n%(block_size * 255))/block_size
  1. Add the width, height,quality factor, and block size to the zig zag list, so that it is encoded into the image (so the user doesn’t have to know these things).

  2. Add a certain number m to each item in the list, so all of the bytes are above 0. Then, add m.

  3. Compress the list of bytes using the lossless compression given by the user (gzip, bzip, zlib).

  4. Save the compressed version as a file, and report statistics.

If the image is color, steps 2-4 are done on all 3 channels, and added to one long list of zags.

To view the compressed image:

  1. Uncompress the file using the compression method given by the user.

  2. Get the m, and subtract it from each item.

  3. Get all of the relevant metadata (blocksize, quality factor, height, width), and use the height and width to find out if the image is color or b&w

  4. Separate the DC components from the AC components

  5. Create a new matrix that is height x width (if it is color, make height x width x 3)

  6. For each section of the list that is block_size^2:

    1. Restore the original shape (undoing the zig-zag algorithm and adding the DC component for that block)

    2. Multiply by the quantization matrix

    3. Undo the DCT (dctmatrix transform * m * dctmatrix)

    4. Add it to the appropriate part of the new matrix

  7. Re-level the matrix by adding 128

  8. Display the image as a matrix

    1. If the image is a color image, it needs to be saturated (anything less than 0 = 0, anything greater than 255 = 255), and then turn it into an uint8 matrix
  9. Display statistics (how long it took).

Note that for step 6, if the image is color, it will fill the blocks into all 3 channels.

One of the benefits of my style with lots of functions is that it is very easy to plug and change certain parts. For example, to add a new lossless compression, you just have to define the compress/uncompress functions, add it to the dictionary of compression methods, and add it as a command line argument. I added xz at the last minute due to a friend’s advice.

Some things I wish I did better:

  • Be able to encode the DC differences as opposed to just the DC coefficients - when I did it, I just got a max-min greater than 256, so I couldn’t encode it as a byte.

  • Avoid having to add that ‘m’ and subtract it later.

  • Somehow encode the compression technique so that the user does not have to enter it. The problem with this is that the bytes become compressed, so I wouldn’t know what to decompress it with to get the data.

Example run:

>python jpeg_compressor.py --action both --verbose --originalfile Kodak12.bmp --compressedfile file.gz --blocksize 8 --qualityfactor 50 --compressionmethod gzip

Starting program with these arguments:

Namespace(action='both', blocksize=8, compressedfile='file.gz', compressionmethod='gzip', interactive=False, originalfile='Kodak12.bmp', qualityfactor=50, verbose=True)

Image is color image.

Opened color image Kodak12.bmp for compression, split into 3 channels

Leveled each block by subtracting 128

Performed DCT on each block of the image, and zig-zagged the blocks into a list

Encoded the width, height, block size, and compression method

Compressed Kodak12.bmp to file.gz using lossless compression method gzip

Block size 8 and quality factor 50

Took 4.33 seconds

Original file size: 1179704 bytes

New file size: 110256 bytes

Compression Ratio: 10.7

Decompressed file.gz using lossless decompression method gzip

This is a color photo

Restored each block by un-zigzagging, multiplying by the quantization matrix, and undoing the DCT

Re-leveled image by adding 128 to each pixel

Displaying Image (check your task bar)

Time taken: 3.76 seconds

Tables

The following is a result of my compression algorithm on the test images. For each one, I include the filename, original size (in bytes), compression ratio achieved with Pillow’s JPEG converter (with quality = 95 for PSNR 50, q=75 for 40, and q=35 for 30), and the compression ratio received with the blocksize and lossless compression technique. The block sizes I used were 8 and 16, and the lossless compressions I used were gzip, bzip, zlib, and xz.

PSNR = 50

Filename Og. Size (bytes) JPEG Compression ratio Ratio (8/gzip) 16/gzip 8/bzip 16/bzip 8/zlib 16/zlib 8/xz 16/xz
Kodak08.bmp 1179704 5.089 4.945 4.992 5.983 6.406 4.787 4.729 8.492 9.039
Kodak08gray.bmp 394296 1.865 4.863 4.921 5.422 5.5 4.72 4.669 5.617 5.508
Kodak09.bmp 1179704 8.873 11.425 12.698 14.409 16.882 10.89 11.852 17.739 20.375
Kodak09gray.bmp 394296 3.181 11.181 12.337 12.779 14.323 10.67 11.536 13.013 14.12
Kodak12.bmp 1179704 9.005 10.699 11.914 13.83 16.278 10.178 11.064 17.028 19.782
Kodak12gray.bmp 394296 3.139 9.927 11.116 11.692 13.163 9.498 10.35 11.743 12.76
Kodak18.bmp 1179704 5.783 6.156 6.52 7.472 8.28 5.936 6.142 9.393 10.546
Kodak18gray.bmp 394296 2.341 6.481 6.997 7.591 8.122 6.256 6.617 7.677 7.982
Kodak21.bmp 1179704 6.964 7.844 8.083 9.798 10.679 7.555 7.609 13.156 14.344
Kodak21gray.bmp 394296 2.579 8.047 8.271 9.168 9.441 7.778 7.785 9.438 9.45
Kodak22.bmp 1179704 6.776 7.552 8.242 9.104 10.474 7.267 7.702 11.184 12.678
Kodak22gray.bmp 394296 2.598 7.629 8.416 8.927 9.819 7.35 7.849 9.155 9.502

PSNR = 40

Filename Og. Size (bytes) JPEG Compression ratio Ratio (8/gzip) 16/gzip 8/bzip 16/bzip 8/zlib 16/zlib 8/xz 16/xz
Kodak08.bmp 1179704 11.588 5.588 5.75 6.852 7.503 5.391 5.425 9.742 10.497
Kodak08gray.bmp 394296 4.159 5.487 5.658 6.138 6.396 5.308 5.354 6.37 6.362
Kodak09.bmp 1179704 25.103 13.26 14.973 17 20.607 12.669 13.911 21.304 24.522
Kodak09gray.bmp 394296 8.978 12.891 14.509 14.942 17.181 12.319 13.534 15.077 16.651
Kodak12.bmp 1179704 23.742 12.697 14.424 16.808 20.084 12.038 13.329 19.98 23.848
Kodak12gray.bmp 394296 8.247 11.758 13.373 14.039 16.047 11.19 12.416 13.779 15.33
Kodak18.bmp 1179704 14.199 7.038 7.69 8.644 9.929 6.769 7.206 10.846 12.466
Kodak18gray.bmp 394296 5.643 7.42 8.197 8.732 9.639 7.152 7.711 8.836 9.411
Kodak21.bmp 1179704 18.035 9.017 9.436 11.482 12.805 8.674 8.851 15.46 17.001
Kodak21gray.bmp 394296 6.668 9.202 9.619 10.641 11.223 8.898 9.048 10.928 11.016
Kodak22.bmp 1179704 17.369 8.742 9.81 10.658 12.716 8.371 9.134 13.012 15.05
Kodak22gray.bmp 394296 6.567 8.861 10.007 10.383 11.942 8.497 9.334 10.593 11.398

PSNR = 30

Filename Og. Size (bytes) JPEG Compression ratio Ratio (8/gzip) 16/gzip 8/bzip 16/bzip 8/zlib 16/zlib 8/xz 16/xz
Kodak08.bmp 1179704 20.975 6.523 6.888 8.164 9.252 6.264 6.482 11.641 12.694
Kodak08gray.bmp 394296 7.463 6.421 6.772 7.26 7.734 6.18 6.393 7.521 7.617
Kodak09.bmp 1179704 46.697 15.782 18.164 20.887 25.819 15.088 16.835 26.118 30.11
Kodak09gray.bmp 394296 17.338 15.289 17.578 17.994 21.355 14.694 16.329 18.174 20.337
Kodak12.bmp 1179704 45.594 15.865 18.317 21.881 26.292 14.932 16.883 24.406 29.797
Kodak12gray.bmp 394296 16.207 14.572 16.913 17.928 20.558 13.759 15.567 16.882 19.309
Kodak18.bmp 1179704 27.137 8.397 9.499 10.471 12.558 8.056 8.856 13.029 15.361
Kodak18gray.bmp 394296 10.709 8.858 10.11 10.597 12.161 8.529 9.473 10.608 11.641
Kodak21.bmp 1179704 33.775 10.741 11.464 13.93 15.998 10.337 10.706 18.817 20.759
Kodak21gray.bmp 394296 12.705 10.909 11.728 12.747 13.828 10.513 10.972 13.054 13.393
Kodak22.bmp 1179704 33.94 10.621 12.252 13.319 16.184 10.133 11.338 15.513 18.437
Kodak22gray.bmp 394296 12.866 10.763 12.441 12.922 15.111 10.296 11.547 12.724 14.189

About

Compresses bmp files into a compressed format, and allows for their viewing.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages