◀ 9.29.39.4 ▶

9.3 — Compression: Lossy vs Lossless

The biggest picture in your project is a 2048 × 2048 level sheet: 654,657 bytes on disk, and exactly 16 MiB as pixels before anything touches it. That gap is not luck. Two families of compression can produce it — and only one of them is allowed to lose anything on the way.

In this lesson you will be able to answer“how do I make a file smaller without losing anything?”
Break It Down~10 min

Your biggest level sheet leaves the project as 654,657 bytes and is 16 MiB of pixels before anything touches it. "Make it smaller" is not one problem: it is working out what the pixels cost raw, knowing which of the two families a file is allowed to use, and being able to say what each one threw away.

First, before anything else: cut that into parts small enough that you could look each one up on its own.

  1. Work out what the pixels cost before any compressionwhat does this part do?Read: the four-bytes-per-colour rule from 9.2, and the size table at the top of this lesson's Concept Lab
  2. Say which family a format belongs towhat does this part do?Read: the lossless-vs-lossy row of the MC trap catalog, and the PNG-vs-JPEG table in this lesson's Concept Lab
  3. Find the repetition a lossless format can exploitwhat does this part do?Read: the worked run-length example in this lesson's Concept Lab
  4. Decide which family each file in the project is allowed to usewhat does this part do?Read: Step 4 of the Build Lab below, and the sprite-slicing pipeline you ran in 7.1
  5. Measure the file you already have before you re-compress itwhat does this part do?Read: the two measurements in Step 3 of the Build Lab below

The split is the whole lesson. "Compress this file" is one job you can only do by opening a tool; these five are five things you can check, argue and measure. The first is arithmetic you already own, the third and fifth are measurements you run on your own project, and the second and fourth are what the exam actually asks — every compression question on the paper is a question about which family a situation demands, and what it is allowed to lose.

The test for a finished split: could you settle the part with a calculator and a file listing? "Work out what the pixels cost" gives you a number; "decide what this file may lose" gives you a reason. A part that needs a compressor installed before you can even think about it is not a part of this problem.

Your turn

Pick two of the parts above and say in one line what each one actually does.

A 64×64 sprite is exactly 16 KiB of pixels raw and 825 bytes as a PNG on disk, and compressing that PNG again gives you 858 bytes — bigger than the file you started with. Explain both numbers in one sentence each, and say which of them would change if the sprite were a photograph instead of flat pixel art.

Your project ships the same 589,301-byte picture twice, and nothing in the project points at the copy in OriginalFiles/. Deleting either copy breaks no reference; deleting the wrong one costs a future re-slice. Which do you delete, and what does your answer assume about the next person to open the project?

Concept Lab ~15 min

Start with what the pixels cost. You already know from 9.2 that a colour is a Color32 — four bytes, one each for R, G, B and A. So one pixel costs four bytes, and a picture's raw size is nothing more than width × height × 4. Here are three real files from your own Assets/Artwork/ folder, with what the file costs on disk — fill the Raw column yourself before you read on:

FilePixelsRaw (w × h × 4)On disk
OriginalFiles/Spike.png64 × 64?825 bytes
OriginalFiles/mainlevbuild.png2048 × 2048?654,657 bytes
Character/Player/Axe1.png1152 × 2112?71,391 bytes
Check your answers fill the Raw column first

Then compare. Each of these is one multiplication, and the number you get is what every ratio in this lesson is measured against.

  • Spike.png: 64 × 64 × 4 = 16,384 bytes (16 KiB)
  • mainlevbuild.png: 2048 × 2048 × 4 = 16,777,216 bytes (16 MiB)
  • Axe1.png: 1152 × 2112 × 4 = 9,732,096 bytes

The gap between those two size columns is the whole lesson. The spike's file is 19.9 times smaller than its pixels and the big level sheet's is 25.6 times smaller than its pixels — and nothing was thrown away to get either number. That is lossless compression.

Lossless: every bit comes back. PNG, ZIP, GIF. The file shrinks because the format found repetition and wrote it down more cleverly, not because it decided any part of the picture was unimportant. Unzip a project and you get the same bytes back, which is why ZIP is what you send somebody when the files matter.

The simplest lossless trick is run-length encoding, RLE: a run of identical values becomes a single (count, value) pair. Two sixteen-symbol rows, one flat and one not:

Raw row (16 symbols):  A A A A A A A A B B B B B B B B
RLE (4 symbols):       8A 8B          8 A's, then 8 B's

Raw row (16 symbols):  1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
RLE (4 symbols):       (7,1)(9,0)     7 ones, then 9 zeros

Sixteen symbols become four. Now feed RLE the wrong picture — a checkerboard, 1 0 1 0 1 0 ... — and every run is one symbol long, so the file comes out bigger than it went in. A compression scheme is a bet on repetition, and pure noise is the bet lost. Hold on to that: it comes back in Step 3.

Lossy: smaller, and forever changed. The original is not recoverable, because the compressed file is the file now. JPEG images, MP3 audio and streaming video work this way. The trick is to throw away what your eyes and ears barely notice — colour detail in a photograph, quiet sounds underneath loud ones — and keep what they do.

Lossless (PNG)Lossy (JPEG)
Edges after compressionPixel-perfectBlurry "ringing" halos
Transparency (alpha)YesNo
Use forSprites, UI, textures with hard edgesPhotos, backgrounds, music
Your project already took the lossy trade — and it is not audio. There is no music and no sound file anywhere under Assets/. The lossy step is the texture import. Open a sprite's .png.meta file and the platform settings read textureCompression: 1 (Normal Quality) with crunchedCompression: 0, and that is where Unity picks DXT/ETC — a GPU format that stores texture blocks approximately. So the same sprite is lossless on disk and lossy on the GPU: exact where it is stored, close enough where it is used. Somebody chose that once, in one dropdown, for every sprite in the project at the same time.

Socratic

The exam asks about tradeoffs, always. Your project keeps its sprites lossless in the file and accepts an approximate texture format on the GPU — the same picture, both families, one pipeline. Why is exactness worth paying for where the file is stored, and a small approximation acceptable where it is used? Who set that threshold, and what would move it?

Build Lab ~20 min

Step 1 — compress by hand. Invent a 16 × 1 "sprite row" (letters or 0/1) and write it out raw, then RLE it. Compute the ratio for a few rows of your own: repetitive rows shrink wildly, and noisy rows RLE can explode. Why does a checkerboard defeat RLE — and what defeats even a clever format? Pure noise, which is why a photograph is the one thing a lossless format cannot rescue.

Step 2 — price your own artwork. Open Assets/Artwork/ and sort by size. The biggest picture in the project is Platformer/OriginalFiles/mainlevbuild.png: 2048 × 2048, 654,657 bytes. Raw it would be 2048 × 2048 × 4 = 16,777,216 bytes, exactly 16 MiB — so that PNG is 25.6 times smaller than the pixels it stores. Do the same arithmetic on two more before you move on: Character/Player/Axe1.png (1152 × 2112) and Top_Down/OriginalFiles/Spike.png (64 × 64). Then find the picture the project ships twice: MainLev2.0.png is 589,301 bytes, and the same 589,301 bytes sit in both OriginalFiles/ and Sliced/.

Step 3 — watch lossless run out of room. Lossless compression does not make everything smaller. It makes uncompressed things smaller. The biggest file in your Assets/ folder is not a picture at all — it is _Scenes/Overworld.unity, 2,377,344 bytes of scene text. Compress it (right-click → Compress, or Send to → Compressed folder) and it collapses to roughly 65,000 bytes: about 36 times smaller, and it still opens as exactly the same scene. Now compress Top_Down/OriginalFiles/Spike.png the same way and it comes out bigger than you started — around 858 bytes against 825.

Those two results are one law, not two quirks. The scene is text that had never been compressed, so there was repetition left to find. The PNG had already been through exactly this, so there was nothing left to find. Compressing a file that is already compressed buys you nothing — which is why zipping a folder of PNGs saves you almost nothing, while zipping a folder of text saves you a great deal.

Step 4 — feel the quality knob, on a file that has one. PNG has no quality setting, because there is nothing to trade. JPEG does. Export one of your sprites as a JPEG at quality 80, then 50, then 20 (Preview, GIMP, or any converter), then zoom to 400% and look at the outline. The halos you can see are the "lossy" in action — a decision about what the eye will forgive, taken before the player ever sees it. At which quality would you stop noticing mid-fight? That threshold, and not zero, is what a streaming service is chasing.

Checkpoint — before moving on, you must be able to:

Reference Docs

Need a deeper explanation? These pages cover the same concepts:

Next: 9.4 — Your Scene Is Data: Metadata & Files

0/4 answered

Answers save on this device as you type. At the end of class, click Download and upload the file to the Canvas assignment.

Saved on this device only — the Dashboard tracks your progress.