-
-
Save Davr1/1c76979ef9e9c75d49b429b40e060afc to your computer and use it in GitHub Desktop.
Two images in one using the PNG gamma header trick.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
rem PNG Gamma trick (by @marcan42 / [email protected]) | |
rem | |
rem This script implements an improved version of the gamma trick used to make | |
rem thumbnail images on reddit/4chan look different from the full-size image. | |
rem | |
rem Sample output (SFW; images by @Miluda): | |
rem https://mrcn.st/t/homura_gamma_trick.png | |
rem https://www.reddit.com/r/test/comments/6edthw/ (click for fullsize) | |
rem https://twitter.com/marcan42/status/869855956842143744 | |
rem | |
rem Some backstory, explanation and example (slightly NSFW): | |
rem https://www.reddit.com/r/touhou/comments/6e6lga/a/di83t02/ | |
rem | |
rem No idea who came up with the concept; this is an old trick, but past | |
rem implementations I've seen were less correct than this one :-) | |
rem | |
rem This trick works on at least Reddit, 4chan and similar imageboards, Google | |
rem Drive, Slack, and probably many others. It does not work on Twitter, as | |
rem Twitter always preprocesses PNG images and strips the gAMA chunk. It does, | |
rem however, work with e.g. imgur embed previews on Twitter. | |
rem | |
rem *Different* one-liner trick that works on Twitter (for grayscale images): | |
rem https://twitter.com/marcan42/status/869858577116086272 | |
rem | |
rem License: public domain | |
set high="%~1" &rem High image (full-size original view) | |
set low="%~2" &rem Low image (thumbnail) (should be the same size) | |
set output="output.png" | |
if not "%~3"=="" ( | |
set output="%~3" &rem Output image | |
) | |
for /f "tokens=*" %%a in ('convert %high% -format "%%wx%%h" info:') do (set size=%%a) | |
rem Give a slight brightness boost to the high source, then apply the gamma. | |
rem This ensures that the pixels look mostly white. | |
convert %high% -alpha off +level 3.5%%,100%% -gamma 20 high_gamma.png | |
rem Since the low image will be washed out, use gamma to darken it a bit, then | |
rem reduce its brightness to ensure that its pixels become black after PNG gamma. | |
rem 77% brightness gets crushed down to 0x00 or 0x01, enough for our purposes. | |
set low_gamma=-alpha off -gamma 0.8 +level 0%%,77%% | |
rem To get rid of the slight "halo" of the high image, we're going to cancel it | |
rem out from the low image. The equation that we need is: | |
rem output = ¾low + ¼ (what we want, for high = white) | |
rem output = ¾output_low + ¼high (what we get) | |
rem Solve for output_low: | |
rem ¾output_low + ¼high = ¾low + ¼ | |
rem ¾output_low = ¾low + ¼ - ¼high | |
rem output_low = low + ⅓ - ⅓high | |
rem This assumes "dumb" resizing (not gamma-correct). For gamma-correct resizing, | |
rem or for viewing at 1:1 (which is equivalent to gamma-correct resizing, because | |
rem physics, assuming your monitor isn't mangling things), this operation would | |
rem have to be done in a linear colorspace. In practice, the vast majority of | |
rem 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 | |
rem Now compose both images together using the mask, then set the gamma metadata. | |
rem note that the typical display gamma is 2.2 and image gamma is the reciprocal | |
rem 1/2.2. Since we're adding a gamma of 20, we need 1/2.2/20 = 0.022727. | |
rem We also force the PNG encoder to include the gAMA chunk (and no other | |
rem 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% | |
rem Remove leftover files | |
del low_adjusted.png high_gamma.png |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How do I use this? I'm dumb.