Skip to content

Instantly share code, notes, and snippets.

@marcan
Last active October 21, 2024 16:56
Show Gist options
  • Save marcan/d537c81efc6d0ff57d54273edd6765fd to your computer and use it in GitHub Desktop.
Save marcan/d537c81efc6d0ff57d54273edd6765fd to your computer and use it in GitHub Desktop.
Two images in one using the PNG gamma header trick.
#!/bin/sh
# PNG Gamma trick (by @marcan42 / [email protected])
#
# This script implements an improved version of the gamma trick used to make
# thumbnail images on reddit/4chan look different from the full-size image.
#
# Sample output (SFW; images by @Miluda):
# https://mrcn.st/t/homura_gamma_trick.png
# https://www.reddit.com/r/test/comments/6edthw/ (click for fullsize)
# https://twitter.com/marcan42/status/869855956842143744
#
# Some backstory, explanation and example (slightly NSFW):
# https://www.reddit.com/r/touhou/comments/6e6lga/a/di83t02/
#
# No idea who came up with the concept; this is an old trick, but past
# implementations I've seen were less correct than this one :-)
#
# This trick works on at least Reddit, 4chan and similar imageboards, Google
# Drive, Slack, and probably many others. It does not work on Twitter, as
# Twitter always preprocesses PNG images and strips the gAMA chunk. It does,
# however, work with e.g. imgur embed previews on Twitter.
#
# *Different* one-liner trick that works on Twitter (for grayscale images):
# https://twitter.com/marcan42/status/869858577116086272
#
# License: public domain
high="$1" # High image (full-size original view)
low="$2" # Low image (thumbnail) (should be the same size)
output="output.png"
if [ ! -z "$3" ]; then
output="$3" # Output image
fi
size=$(convert "$high" -format "%wx%h" info:)
# Give a slight brightness boost to the high source, then apply the gamma.
# This ensures that the pixels look mostly white.
convert "$high" -alpha off +level 3.5%,100% -gamma 20 high_gamma.png
# Since the low image will be washed out, use gamma to darken it a bit, then
# reduce its brightness to ensure that its pixels become black after PNG gamma.
# 77% brightness gets crushed down to 0x00 or 0x01, enough for our purposes.
low_gamma="-alpha off -gamma 0.8 +level 0%,77%"
# To get rid of the slight "halo" of the high image, we're going to cancel it
# out from the low image. The equation that we need is:
# output = ¾low + ¼ (what we want, for high = white)
# output = ¾output_low + ¼high (what we get)
# Solve for output_low:
# ¾output_low + ¼high = ¾low + ¼
# ¾output_low = ¾low + ¼ - ¼high
# output_low = low + ⅓ - ⅓high
# This assumes "dumb" resizing (not gamma-correct). For gamma-correct resizing,
# or for viewing at 1:1 (which is equivalent to gamma-correct resizing, because
# physics, assuming your monitor isn't mangling things), this operation would
# have to be done in a linear colorspace. In practice, the vast majority of
# resizing implementations are not gamma-correct, so this works.
convert \( "$low" $low_gamma \) high_gamma.png \
-compose Mathematics -define compose:args='0,-0.33,1,0.33' \
-composite low_adjusted.png
# Now compose both images together using the mask, then set the gamma metadata.
# Note that the typical display gamma is 2.2 and image gamma is the reciprocal
# 1/2.2. Since we're adding a gamma of 20, we need 1/2.2/20 = 0.022727.
# We also force the PNG encoder to include the gAMA chunk (and no other
# spurious metadata).
convert low_adjusted.png high_gamma.png -size $size pattern:gray25 -composite \
-set gamma 0.022727 -define png:include-chunk=none,gAMA "$output"
@MrBober
Copy link

MrBober commented Jul 21, 2023

For those who still don't know how to use it:

  1. You need a POSIX-compliant shell (like bash)
    It's something that will be present on pretty much all Linux distributions and many other UNIX-like systems like BSD or MacOS.
    On Windows it won't come pre-installed so you need to either use WSL (Windows Subsystem for Linux, which is a compatibility layer allowing you to execute Linux programs) and install some distro like Ubuntu (which will allow you to execute it just fine), or you need to download some port of bash for Windows, like for example Git Bash. You can probably just search how to get bash on windows on google and you'll find some tutorials.
  2. If you're on a UNIX-like system and downloaded the script, you can move to a directory containing the script you just downloaded using cd (change directory) command and running
  • 'bash gamma-trick.sh image1.png image2.png output.png` (replace the file names in the command)
  • or first running chmod +x gamma-trick.sh (to make the file executable) and then ./gamma-trick.sh image1.png image2.png output.png (./ just means the current directory, it has to be before the file you want to execute so that the shell doesn't interpret it as a command, if the file is not in your current directory you can do folder/gamma-trick.sh to run it and it'll work just fine)
    If you're on Windows and are using WSL then it's basically the same as the process described before and if you're using something like Git Bash you can probably just omit the chmod +x thing, but I'm not sure, either way doing bash gamma-trick.sh should work.

Oh yeah, you'll also wanna make sure you have imagemagick installed, which with Linux or WSL you can probably do with your package manager, by running apt install imagemagick (might differ depending on distro), I suppose you can also install it with Homebrew on MacOS.

When I was running the script I encountered some problems and I had to also use exiftool to set the gAMA tag, so you might also want to install that and add exiftool -overwrite_original -gamma="44" "$output" at the end of the file.

@BIazerKing
Copy link

BIazerKing commented Sep 23, 2023

For those who still don't know how to use it:

  1. You need a POSIX-compliant shell (like bash)
    It's something that will be present on pretty much all Linux distributions and many other UNIX-like systems like BSD or MacOS.
    On Windows it won't come pre-installed so you need to either use WSL (Windows Subsystem for Linux, which is a compatibility layer allowing you to execute Linux programs) and install some distro like Ubuntu (which will allow you to execute it just fine), or you need to download some port of bash for Windows, like for example Git Bash. You can probably just search how to get bash on windows on google and you'll find some tutorials.
  2. If you're on a UNIX-like system and downloaded the script, you can move to a directory containing the script you just downloaded using cd (change directory) command and running
  • 'bash gamma-trick.sh image1.png image2.png output.png` (replace the file names in the command)
  • or first running chmod +x gamma-trick.sh (to make the file executable) and then ./gamma-trick.sh image1.png image2.png output.png (./ just means the current directory, it has to be before the file you want to execute so that the shell doesn't interpret it as a command, if the file is not in your current directory you can do folder/gamma-trick.sh to run it and it'll work just fine)
    If you're on Windows and are using WSL then it's basically the same as the process described before and if you're using something like Git Bash you can probably just omit the chmod +x thing, but I'm not sure, either way doing bash gamma-trick.sh should work.

Oh yeah, you'll also wanna make sure you have imagemagick installed, which with Linux or WSL you can probably do with your package manager, by running apt install imagemagick (might differ depending on distro), I suppose you can also install it with Homebrew on MacOS.

When I was running the script I encountered some problems and I had to also use exiftool to set the gAMA tag, so you might also want to install that and add exiftool -overwrite_original -gamma="44" "$output" at the end of the file.

ive done everything and it says

Invalid Parameter - -format
Invalid Parameter - -alpha
Invalid Parameter - 2.png

would you know on how to fix this

@ReimarPB
Copy link

ReimarPB commented Dec 4, 2023

ive done everything and it says

Invalid Parameter - -format Invalid Parameter - -alpha Invalid Parameter - 2.png

would you know on how to fix this

Sounds like the script is using Windows' built-in convert command which is different from the command from ImageMagick that is meant to be used, although they share the same name.

Make sure you have downloaded ImageMagick before you run the script, and that you've enabled both "Add application directory to system PATH" and "Install legacy utilities (e.g. convert)" during setup, and after that restarted your terminal.

To further debug, you can write where convert in your terminal, and the output should be something like this:

C:\Program Files\ImageMagick-7.1.1-Q16-HDRI\convert.exe
C:\Windows\System32\convert.exe

Note that it finds two programs, one from ImageMagick and the other from Windows' system folder. The one that shows up first (which in this case is ImageMagick) is the one that will be executed when you type convert in your terminal.

@Kevinqui1
Copy link

ive done everything and it says
Invalid Parameter - -format Invalid Parameter - -alpha Invalid Parameter - 2.png
would you know on how to fix this

Sounds like the script is using Windows' built-in convert command which is different from the command from ImageMagick that is meant to be used, although they share the same name.

Make sure you have downloaded ImageMagick before you run the script, and that you've enabled both "Add application directory to system PATH" and "Install legacy utilities (e.g. convert)" during setup, and after that restarted your terminal.

To further debug, you can write where convert in your terminal, and the output should be something like this:

C:\Program Files\ImageMagick-7.1.1-Q16-HDRI\convert.exe
C:\Windows\System32\convert.exe

Note that it finds two programs, one from ImageMagick and the other from Windows' system folder. The one that shows up first (which in this case is ImageMagick) is the one that will be executed when you type convert in your terminal.

For those who still don't know how to use it:

  1. You need a POSIX-compliant shell (like bash)
    It's something that will be present on pretty much all Linux distributions and many other UNIX-like systems like BSD or MacOS.
    On Windows it won't come pre-installed so you need to either use WSL (Windows Subsystem for Linux, which is a compatibility layer allowing you to execute Linux programs) and install some distro like Ubuntu (which will allow you to execute it just fine), or you need to download some port of bash for Windows, like for example Git Bash. You can probably just search how to get bash on windows on google and you'll find some tutorials.
  2. If you're on a UNIX-like system and downloaded the script, you can move to a directory containing the script you just downloaded using cd (change directory) command and running
  • 'bash gamma-trick.sh image1.png image2.png output.png` (replace the file names in the command)
  • or first running chmod +x gamma-trick.sh (to make the file executable) and then ./gamma-trick.sh image1.png image2.png output.png (./ just means the current directory, it has to be before the file you want to execute so that the shell doesn't interpret it as a command, if the file is not in your current directory you can do folder/gamma-trick.sh to run it and it'll work just fine)
    If you're on Windows and are using WSL then it's basically the same as the process described before and if you're using something like Git Bash you can probably just omit the chmod +x thing, but I'm not sure, either way doing bash gamma-trick.sh should work.

Oh yeah, you'll also wanna make sure you have imagemagick installed, which with Linux or WSL you can probably do with your package manager, by running apt install imagemagick (might differ depending on distro), I suppose you can also install it with Homebrew on MacOS.

When I was running the script I encountered some problems and I had to also use exiftool to set the gAMA tag, so you might also want to install that and add exiftool -overwrite_original -gamma="44" "$output" at the end of the file.

after running the 'bash gamma-trick.sh image1.png image2.png output.png' in git bash, i get 2 photos. The 'output.png' is one photo and the other photo is called 'high_gamma.png'

What do I do to like join them?

@ReimarPB
Copy link

after running the 'bash gamma-trick.sh image1.png image2.png output.png' in git bash, i get 2 photos. The 'output.png' is one photo and the other photo is called 'high_gamma.png'

What do I do to like join them?

The output.png file should be the final result

@Kevinqui1
Copy link

after running the 'bash gamma-trick.sh image1.png image2.png output.png' in git bash, i get 2 photos. The 'output.png' is one photo and the other photo is called 'high_gamma.png'
What do I do to like join them?

The output.png file should be the final result

Why when i send it to discord it stays the same even if u click it? like ive seen just now some pictures that can be resized when clicked

@MinerovyLP
Copy link

can you help me
the image generated with the script does not have a gAMA chunk in its metadata and doesnt work
do you know why ?
i tried both imagemagick legacy and the new version

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