Compression
Uncompressed images, sound and video are huge: three minutes of CD-quality audio is about 32 MB, and a single uncompressed 4K video frame is about 25 MB. Compression reduces file sizes so that data takes less storage and transfers faster. This note covers why compression is needed, the difference between lossy and lossless compression, how each type of file (text, bitmap, vector, sound) can be compressed, and run-length encoding (RLE), which Paper 1 asks you to apply by hand.
Why compress?
Compression reduces the number of bits needed to represent the same data (or acceptably similar data). The benefits all follow from smaller files:
- less storage space is needed, on devices and on servers;
- files transfer faster over networks and use less bandwidth, which matters for downloads, email attachments and web pages;
- streaming audio and video becomes possible at the bit rates real connections provide (see bit streaming);
- costs fall, for example for cloud storage or mobile data.
The costs are processing time (to compress and decompress) and, for lossy methods, some loss of quality.
Lossless and lossy compression
Lossless compression reduces file size without permanently losing any data: when the file is decompressed, it is restored exactly to the original.
Lossy compression reduces file size by permanently removing data, usually data that people are unlikely to notice. The decompressed file is not identical to the original.
Lossless methods work by finding redundancy: patterns and repetition that can be described more briefly. Lossy methods go further and throw away detail judged to be unimportant, so they achieve much greater reductions.
| Lossless | Lossy | |
|---|---|---|
| Original restored exactly? | Yes | No: data is permanently removed |
| Typical reduction | Smaller (often to 50 to 70% of the original) | Much larger (often to 10% or less) |
| Must be used for | Text, program code, spreadsheets, databases, executable files, medical and legal images | Not suitable when every bit matters |
| Suitable for | Any file; images or audio for editing or archiving | Photographs, music, video for viewing or streaming |
| Examples | RLE, ZIP, PNG, FLAC | JPEG, MP3, AAC, MP4 (H.264) |
Justifying a method
The choice always comes down to one question: does the file have to be exactly the same after decompression?
- A text document, a program, a spreadsheet of accounts: yes. Losing a single character could change the meaning or stop the program working, so lossless.
- A photograph for a website or a song to stream: no. Small losses are not noticed, and a much smaller file loads or streams faster, so lossy.
- A photograph a designer will keep editing, or a medical X-ray: yes. Repeated lossy saves degrade the image, and lost detail could matter, so lossless.
Run-length encoding (RLE)
Run-length encoding is a lossless method. A run is a sequence of identical consecutive data items. RLE replaces each run with two values: the number of items in the run and the item itself.
AAAABBBCCD becomes 4A3B2C1D: four A, three B, two C, one D. Ten characters become eight.
RLE works well when data has long runs, such as images with large areas of a single colour (icons, diagrams, cartoons, scanned text documents). It works badly when consecutive items are usually different: ABCDEF becomes 1A1B1C1D1E1F, which is twice the size. Photographs rarely have long runs of identical pixels, so RLE is a poor choice for them.
- Read the data from the start, counting how many consecutive items are the same.
- When the item changes (or the data ends), write the count followed by the item.
- Start a new count for the new item.
- To decompress, read each (count, item) pair and write the item that many times.
- Compare the sizes to decide whether compression has actually helped.
In a bitmap, RLE is applied to pixel colour values, usually row by row, and each run is stored as a pair of bytes: one byte for the count and one for the colour. A single count byte can hold at most 255, so a longer run is split into two.
A row of a greyscale bitmap has 16 pixels. Each pixel is stored in one byte. The row is: 10 white pixels (value 255), 3 black pixels (value 0), then 3 white pixels. Show the RLE of the row as (count, value) byte pairs, and calculate the saving.
Solution
Runs: 10 × 255, then 3 × 0, then 3 × 255.
RLE: 10 255 3 0 3 255, that is three pairs.
Uncompressed: 16 bytes. Compressed: 6 bytes. Saving: 10 bytes, so the compressed row is of the original.
Decompressing these pairs gives back exactly the same 16 values, which is why RLE is lossless.
A 1-byte-per-pixel image row is stored using RLE as the hexadecimal bytes 05 FF 02 00 05 FF. Decode the row and state how many bytes the uncompressed row needs.
Solution
Pairs: 05 FF: 5 pixels of value FF (255); 02 00: 2 pixels of value 0; 05 FF: 5 pixels of 255.
Row: 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255.
Uncompressed: bytes, compared with 6 bytes compressed.
A text file contains the string THE CAT SAT ON THE MAT. Explain why RLE in the form count-then-character is not suitable, and name a more suitable lossless method.
Solution
The string has almost no consecutive repeated characters: every run has length 1. RLE would replace each of the 22 characters with a count and the character, roughly doubling the size.
A dictionary-based method is more suitable: it stores repeated patterns once (here THE, AT and the space appear several times) and replaces later occurrences with short references to the dictionary. This is still lossless.
Write a pseudocode function Encode(Data : STRING) RETURNS STRING that returns the run-length encoding of a non-empty string, as counts followed by characters. For example, Encode("WWWWBBBW") returns "4W3B1W". You may use NUM_TO_STR(x : INTEGER) RETURNS STRING.
Solution
Compare each character with the one before it; while they match, keep counting; when they differ, output the finished run.
FUNCTION Encode(Data : STRING) RETURNS STRING
DECLARE Result : STRING
DECLARE Count : INTEGER
DECLARE Index : INTEGER
Result ← ""
Count ← 1
FOR Index ← 2 TO LENGTH(Data)
IF MID(Data, Index, 1) = MID(Data, Index - 1, 1) THEN
Count ← Count + 1
ELSE
Result ← Result & NUM_TO_STR(Count) & MID(Data, Index - 1, 1)
Count ← 1
ENDIF
NEXT Index
// the final run has not been output yet
Result ← Result & NUM_TO_STR(Count) & RIGHT(Data, 1)
RETURN Result
ENDFUNCTIONTrace for "WWWWBBBW": indexes 2 to 4 match, so Count reaches 4; at index 5 (B after W) "4W" is output; indexes 6 and 7 match, Count reaches 3; at index 8 (W after B) "3B" is output; after the loop the last run "1W" is added. Result "4W3B1W".
The line after the loop is the one most often forgotten: without it, the last run is lost.
How each type of file is compressed
Text files
Text must be compressed losslessly, because every character matters.
- Dictionary-based compression: repeated words or sequences are stored once in a dictionary, and each occurrence in the text is replaced by a short index into the dictionary. Long documents with many repeated words compress very well.
- Variable-length codes (for example Huffman coding): frequently used characters such as
eand the space get short binary codes; rare characters get longer codes. The average number of bits per character falls below 8. - RLE only helps if the text contains long runs of the same character, such as rows of spaces or dashes.
Bitmap images
- Lossless: RLE for images with large areas of identical colour; PNG and GIF use lossless methods that also exploit repeated patterns. Used for diagrams, screenshots and images to be edited.
- Lossy: JPEG removes detail the eye is unlikely to notice. It stores colour information at lower resolution than brightness (the eye is less sensitive to colour detail) and discards fine high-frequency detail. Reducing the colour depth (fewer bits per pixel) or reducing the resolution (fewer pixels) also reduces size and is lossy, because the removed data cannot be recovered.
Vector graphics
A vector graphic is a drawing list of objects and properties, essentially structured text, so it is compressed losslessly: with general-purpose lossless methods (for example a ZIP-style compression of an SVG file), and by removing redundant data such as unnecessary decimal places in coordinates, hidden objects, or comments. Lossy compression would change shapes and positions, which defeats the point of a precise drawing.
Sound files
- Lossy (perceptual) compression, as in MP3 and AAC, removes sounds people cannot hear or will not notice: frequencies outside the range of human hearing, and quieter sounds that are masked by louder sounds at the same time (perceptual masking). It can reduce file size to about a tenth with little audible difference.
- Reducing the sampling rate or sampling resolution, or converting stereo to mono, also reduces size and is lossy.
- Lossless formats such as FLAC exploit patterns in the samples and give back the original exactly, for archiving and professional editing.
"Lossy compression loses quality so you can never use it." Lossy is the right answer whenever the small loss is not noticeable and a much smaller file is valuable: photographs on websites, streamed music and video.
"Lossless compression removes unnecessary data." It removes redundancy (repetition that can be described more briefly) and loses nothing; the original can be reconstructed exactly. Saying it "removes data" suggests lossy.
Assuming RLE always makes files smaller. If runs are short, RLE makes the file larger. Always compare sizes.
Writing RLE pairs the wrong way round. Follow the order the question uses. If it says "count followed by colour", 3 0 means three pixels of value 0, not zero pixels of value 3.
For "justify the use of lossy or lossless compression" questions, there are usually two marks: the choice, and a reason linked to the scenario. "Lossless, because the program file must be identical after decompression or it will not run" earns both; "lossless, because it is better" earns nothing.
When asked "explain how a sound file can be compressed", name the method and describe what is removed or encoded: "perceptual coding removes sounds outside the range of human hearing and sounds masked by louder sounds". Similarly for images: "RLE replaces runs of identical pixels with a count and the pixel value".
In RLE calculations, show the runs, then the encoded values, then both sizes. If the question gives a format (for example one byte for the count, one for the colour), use it exactly.
- Compression reduces file size: less storage, faster transfer, less bandwidth, makes streaming practical.
- Lossless: original restored exactly; removes redundancy. Lossy: data permanently removed; much smaller files.
- Use lossless for text, code, data, and files that will be edited or must be exact; lossy for photos, music and video for viewing.
- RLE (lossless): each run becomes (count, value). Good for long runs; can enlarge data with short runs.
- Text: dictionary or variable-length codes (lossless).
- Bitmap: RLE/PNG (lossless) or JPEG, lower resolution or colour depth (lossy).
- Vector: lossless only (remove redundancy, general-purpose compression).
- Sound: perceptual coding removes inaudible and masked sounds (lossy); FLAC (lossless).
Practice
- State two benefits of compressing a file before sending it by email.
- Explain the difference between lossy and lossless compression.
- Apply RLE (count followed by character) to
RRRRRRGGGBBBBBBBBB. State the original and compressed lengths in characters. - Decode the RLE data
3X1Y4Zand state its length. - A company stores scanned black-and-white documents. Explain why RLE is likely to be effective for these images.
- Explain why lossy compression is not suitable for a program file.
- Describe how perceptual coding reduces the size of a music file.
- A bitmap row of 20 pixels, 1 byte per pixel, is stored with RLE as (count, value) byte pairs. The row contains 20 pixels, each a different colour from its neighbours. Calculate the size of the RLE row and comment on the result.
- A photographer stores original images to edit later, and also publishes them on a website. Recommend a compression type for each use and justify both recommendations.
- A student writes a version of
Encodethat does not have the statement after theFORloop. (a) State the result of their version for"AAAABBBCCD". (b) Explain the error and state which type of error it is. (c) The correct version in this note fails ifDatais an empty string. Explain why and suggest a fix.
Answers
- The file uploads and downloads faster; it is less likely to exceed the attachment size limit; it uses less bandwidth and storage.
- Lossless compression reduces size without losing data, so decompression restores the original exactly. Lossy compression permanently removes some data (usually unnoticeable detail), so the decompressed file differs from the original, but the file can be much smaller.
6R3G9B: 18 characters to 6.XXXYZZZZ, 8 characters.- The documents consist mostly of long runs of white pixels (the page) broken by short runs of black (the text). Each long run is replaced by just a count and a colour, so the file shrinks a lot, and no data is lost.
- Every bit of a program is significant. If data were removed the instructions would change, so the program would not run correctly or at all. Only lossless compression restores it exactly.
- It removes sounds that the human ear cannot perceive, such as frequencies outside the range of human hearing and quieter sounds masked by louder ones played at the same time. Those sounds are not stored, so fewer bits are needed, and listeners notice little difference.
- Every run has length 1, so there are 20 pairs = 40 bytes, twice the 20 uncompressed bytes. RLE makes this data bigger; it should not be used here.
- Originals: lossless, because the photographer needs all the original detail to edit, and repeated lossy saves would degrade quality. Website: lossy (for example JPEG), because a much smaller file loads faster for visitors, and the loss of detail is not noticeable at screen size.
- (a)
"4A3B2C": the final run1Dis missing. (b) The loop only outputs a run when the character changes, so the last run is never output. It is a logic error (the program runs but gives the wrong result). (c) The loop does not run, but the statement after it still addsNUM_TO_STR(1)andRIGHT(Data, 1): the initialCount ← 1assumes there is at least one character. The function would return"1"(or cause a run-time error whenRIGHTis given an empty string). Fix: checkIF LENGTH(Data) = 0 THEN RETURN "" ENDIFat the start.