Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strip metadata from PNG mods/default textures #2380

Closed
wants to merge 1 commit into from
Closed

Strip metadata from PNG mods/default textures #2380

wants to merge 1 commit into from

Conversation

Zweihorn
Copy link
Contributor

Reduces significantly the size of PNG texture files found being sized 4 kB and above.
The selected files were processed with the optipng -o2 -strip all <file> command line.

The OptiPNG program shall attempt to optimize PNG files, i.e. reduce their size to a minimum, without losing semantic information. In addition, this program shall perform a suite of auxiliary functions like integrity checks, metadata recovery and pixmap-to-PNG conversion.

A brief test with a MT 5.0.1 client with digging dirt and emptying buckets of lava, river water and water showed no apparent issues but burned all trees nearby.

Hope this helps.

M  default_acacia_tree_top.png
M  default_aspen_tree.png
M  default_aspen_wood.png
M  default_desert_stone_block.png
M  default_desert_stone_brick.png
M  default_dirt.png
M  default_fence_aspen_wood.png
M  default_gravel.png
M  default_ice.png
M  default_jungletree.png
M  default_jungletree_top.png
M  default_lava.png
M  default_meselamp.png
M  default_obsidian_block.png
M  default_river_water_flowing_animated.png
M  default_river_water_source_animated.png
M  default_sandstone_block.png
M  default_silver_sand.png
M  default_stone_brick.png
M  heart.png

All PNG files sized 4 kB and above were processed as follows:

$ for i in "heart.png
default_dirt.png
default_river_water_flowing_animated.png
default_lava.png
default_jungletree.png
default_jungletree_top.png
default_meselamp.png
default_acacia_tree_top.png
default_river_water_source_animated.png
default_gravel.png
default_sandstone_block.png
default_aspen_tree.png
default_desert_stone_brick.png
default_desert_stone_block.png
default_stone_brick.png
default_fence_aspen_wood.png
default_ice.png
default_silver_sand.png
default_aspen_wood.png
default_obsidian_block.png"; do optipng -o2 -strip all $i ; done

** Processing: heart.png
16x16 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 42 colors (1 transparent) in palette
Stripping metadata...
Input IDAT size = 320 bytes
Input file size = 14830 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 126
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 125
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 119
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 117

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 117

Output IDAT size = 117 bytes (203 bytes decrease)
Output file size = 325 bytes (14505 bytes = 97.81% decrease)

** Processing: default_dirt.png
16x16 pixels, 4 bits/pixel, 16 colors in palette
Stripping metadata...
Input IDAT size = 155 bytes
Input file size = 5889 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 155
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 155
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 155
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 155
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 155

Output IDAT size = 155 bytes (no change)
Output file size = 272 bytes (5617 bytes = 95.38% decrease)

** Processing: default_river_water_flowing_animated.png
16x256 pixels, 4x8 bits/pixel, RGB+alpha
Stripping metadata...
Input IDAT size = 5723 bytes
Input file size = 5851 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 4186

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 4186

Output IDAT size = 4186 bytes (1537 bytes decrease)
Output file size = 4243 bytes (1608 bytes = 27.48% decrease)

** Processing: default_lava.png
16x16 pixels, 8 bits/pixel, 221 colors in palette
Stripping metadata...
Input IDAT size = 283 bytes
Input file size = 5706 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 283
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 283
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 283
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 283
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 283

Output IDAT size = 283 bytes (no change)
Output file size = 1015 bytes (4691 bytes = 82.21% decrease)

** Processing: default_jungletree.png
16x16 pixels, 8 bits/pixel, 254 colors in palette
Stripping metadata...
Input IDAT size = 283 bytes
Input file size = 5592 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 283
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 283
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 283
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 283
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 283
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 283

Output IDAT size = 283 bytes (no change)
Output file size = 1114 bytes (4478 bytes = 80.08% decrease)

** Processing: default_jungletree_top.png
16x16 pixels, 8 bits/pixel, 117 colors in palette
Stripping metadata...
Input IDAT size = 268 bytes
Input file size = 5175 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 268
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 268
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 268
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 268

Output IDAT size = 268 bytes (no change)
Output file size = 688 bytes (4487 bytes = 86.71% decrease)

** Processing: default_meselamp.png
16x16 pixels, 8 bits/pixel, 199 colors in palette
Stripping metadata...
Input IDAT size = 281 bytes
Input file size = 5103 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 281
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 256
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 256
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 256
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 256

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 256

Output IDAT size = 256 bytes (25 bytes decrease)
Output file size = 922 bytes (4181 bytes = 81.93% decrease)

** Processing: default_acacia_tree_top.png
16x16 pixels, 8 bits/pixel, 132 colors in palette
Stripping metadata...
Input IDAT size = 225 bytes
Input file size = 5010 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 225

Output IDAT size = 225 bytes (no change)
Output file size = 690 bytes (4320 bytes = 86.23% decrease)

** Processing: default_river_water_source_animated.png
16x256 pixels, 4x8 bits/pixel, RGB+alpha
Reducing image to 8 bits/pixel, 178 colors (178 transparent) in palette
Stripping metadata...
Input IDAT size = 4807 bytes
Input file size = 4935 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 2112

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 2112

Output IDAT size = 2112 bytes (2695 bytes decrease)
Output file size = 2905 bytes (2030 bytes = 41.13% decrease)

** Processing: default_gravel.png
16x16 pixels, 8 bits/pixel, 103 colors in palette
Stripping metadata...
Input IDAT size = 254 bytes
Input file size = 4715 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 254
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 252
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 252
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 252

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 252

Output IDAT size = 252 bytes (2 bytes decrease)
Output file size = 630 bytes (4085 bytes = 86.64% decrease)

** Processing: default_sandstone_block.png
16x16 pixels, 8 bits/pixel, 35 colors in palette
Stripping metadata...
Input IDAT size = 189 bytes
Input file size = 4548 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 189
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 185
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 185
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 185
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 177
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 172
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 172
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 172

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 172

Output IDAT size = 172 bytes (17 bytes decrease)
Output file size = 346 bytes (4202 bytes = 92.39% decrease)

** Processing: default_aspen_tree.png
16x16 pixels, 8 bits/pixel, 77 colors in palette
Reducing image to 8 bits/pixel, grayscale
Stripping metadata...
Input IDAT size = 231 bytes
Input file size = 4429 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 255
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 253
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 253
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 253

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 253

Output IDAT size = 253 bytes (22 bytes increase)
Output file size = 310 bytes (4119 bytes = 93.00% decrease)

** Processing: default_desert_stone_brick.png
16x16 pixels, 8 bits/pixel, 48 colors in palette
Stripping metadata...
Input IDAT size = 185 bytes
Input file size = 4420 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 185
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 183
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 175
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 175

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 175

Output IDAT size = 175 bytes (10 bytes decrease)
Output file size = 388 bytes (4032 bytes = 91.22% decrease)

** Processing: default_desert_stone_block.png
16x16 pixels, 8 bits/pixel, 40 colors in palette
Stripping metadata...
Input IDAT size = 173 bytes
Input file size = 4368 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 173
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 171
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 169
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 169

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 169

Output IDAT size = 169 bytes (4 bytes decrease)
Output file size = 358 bytes (4010 bytes = 91.80% decrease)

** Processing: default_stone_brick.png
16x16 pixels, 8 bits/pixel, 36 colors in palette
Stripping metadata...
Input IDAT size = 172 bytes
Input file size = 4196 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 172
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 172
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 169
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 151
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 151

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 151

Output IDAT size = 151 bytes (21 bytes decrease)
Output file size = 328 bytes (3868 bytes = 92.18% decrease)

** Processing: default_fence_aspen_wood.png
16x16 pixels, 4 bits/pixel, 12 colors in palette
Stripping metadata...
Input IDAT size = 130 bytes
Input file size = 4170 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 130
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 127
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 127
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 127

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 127

Output IDAT size = 127 bytes (3 bytes decrease)
Output file size = 232 bytes (3938 bytes = 94.44% decrease)

** Processing: default_ice.png
16x16 pixels, 8 bits/pixel, 18 colors in palette
Stripping metadata...
Input IDAT size = 112 bytes
Input file size = 4114 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 112
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 110
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 99

Selecting parameters:
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 99

Output IDAT size = 99 bytes (13 bytes decrease)
Output file size = 222 bytes (3892 bytes = 94.60% decrease)

** Processing: default_silver_sand.png
16x16 pixels, 4 bits/pixel, 12 colors in palette
Stripping metadata...
Input IDAT size = 155 bytes
Input file size = 4069 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 155
  zc = 1  zm = 8  zs = 2  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 3  f = 0		IDAT size = 155
  zc = 9  zm = 8  zs = 0  f = 5		IDAT size = 155
  zc = 9  zm = 8  zs = 1  f = 5		IDAT size = 155
  zc = 1  zm = 8  zs = 2  f = 5		IDAT size = 155
  zc = 9  zm = 8  zs = 3  f = 5		IDAT size = 155

Output IDAT size = 155 bytes (no change)
Output file size = 260 bytes (3809 bytes = 93.61% decrease)

** Processing: default_aspen_wood.png
16x16 pixels, 4 bits/pixel, 12 colors in palette
Stripping metadata...
Input IDAT size = 119 bytes
Input file size = 4023 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 119
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 117

Selecting parameters:
  zc = 9  zm = 8  zs = 1  f = 0		IDAT size = 117

Output IDAT size = 117 bytes (2 bytes decrease)
Output file size = 222 bytes (3801 bytes = 94.48% decrease)

** Processing: default_obsidian_block.png
16x16 pixels, 4 bits/pixel, 13 colors in palette
Stripping metadata...
Input IDAT size = 95 bytes
Input file size = 3913 bytes

Trying:
  zc = 9  zm = 8  zs = 0  f = 0		IDAT size = 95

Output IDAT size = 95 bytes (no change)
Output file size = 203 bytes (3710 bytes = 94.81% decrease)
@Calinou
Copy link
Member

Calinou commented May 31, 2019

If we're going to optimize all images (and increase Git history size), we might want to optimize it even further. Using oxipng, this can be done with oxipng -o6 --strip --zopfli **/*.png. (Or with parallel, parallel oxipng -o6 --strip --zopfli ::: **/*.png.)

@Zweihorn
Copy link
Contributor Author

Zweihorn commented May 31, 2019

Oh sorry, the listing inside the commit was only ment for transparency.

  1. Does this bother you or GitHub?
  2. Is a reduction of texture files a pointless task?
    However, the file heart.png showed a 97.81% decrease. New size is 325 bytes from 15 kB before.

Naturally, there may be other tools. The optipng tool has other options too and I intentionally avoided to touch all files.

@Calinou
Copy link
Member

Calinou commented May 31, 2019

Does this bother you or GitHub?

By "history size", I meant the total file size of the repository once you clone it. Unlike text files, Git doesn't handle binary files using delta compression; all revisions of a binary file will be downloaded when you clone a repository. A large repository takes more time to clone for people with slower connections; hence, we should try to optimize images once and do it well 🙂

Is a reduction of texture files a pointless task?

Definitely not, it matters when people join a server for the first time.

@sofar
Copy link
Contributor

sofar commented May 31, 2019 via email

@Zweihorn
Copy link
Contributor Author

we should try to optimize images once and do it well

It's best done right before a major release

So you propose to delay for an indefinite period?

You must be joking. No offence but I would call it rather unfortunate that this was missed for the 5.x major release and you want to wait for 6.x apparently.

Please note there are several more files to be reduced in size by 50% or more which are in other folders of the mods tree besides the 'default' mod.

@paramat
Copy link
Contributor

paramat commented May 31, 2019

we might want to optimize it even further.

Depends what this further optimisation includes.

Stripping metadata is well worth doing as it can cause a large file size reduction. However, apart from that, these textures have been optimised several times in the past and small additional optimisations are not important.

So this PR is essentially fine as it is, but it's better to wait until just before release of 5.1.0, which will only be a few months, and include any extra textures in the PR.
👎 For this PR.

I reopened the reminder issue #1831

@Zweihorn
Copy link
Contributor Author

Zweihorn commented Jun 1, 2019

Thank you all for the consideration and the advice. I appreciate the 'maintenance' tag.
Easily understood and waiting for a minor release seems to be reasonable.

This PR and the list of files took already into account the majority of the PNG files can be called optimized. The optimization rates are 80% and better for all of the 20 files selected. So 'mods/default' was overlooked in the past release apparently.

IMHO one should not seek to optimize too far and should avoid tinkering too much with the optimization levels of the tools. AFAIK from some tests on the mods tree the outcome may be limited to the majority of files.

What about an optimization threshold? Taking into account the a.m. 'history size' argument I would propose to set a 10% threshold. Thus intentionally ignoring the huge majority of the PNG files and aim for a reasonable list of files which can be sufficiently optimized.

See you again just before release of 5.1.0 in a few months hopefully. Happy hacking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants