Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- # This creates an JPEG file with four different appearances depending on how the image is decoded.
- # The dct* tools are available at https://gitgud.io/dcttransform/dcttransform
- if (($# != 5)); then
- echo "Usage: $0 input1 input2 input3 input4 output"
- exit
- fi
- for i in {1..4}; do
- if [ ! -f "${!i}" ]; then
- echo "input file does not exist: $1"
- exit
- fi
- done
- set -x -e
- # Working directory.
- work=$(mktemp -d)
- for i in {1..4}; do
- cp -- "${!i}" "$work/input$i"
- done
- pushd "$work" || exit
- # The quantization table used in the files created.
- # All values are set to 32.
- yes 32 | head -n 64 > qtable.txt
- # Create two color palettes.
- # 8colors.jpg contains the colors obtained when pushing Y, Cb, Cr outside the valid ranges.
- # These are the intended colors for the final image.
- # 8legal.jpg contains the colors obtained by setting Y, Cb, Cr to 128 +/- 32.
- # Images are mapped to this palette before JPEG compression;
- # then the DCT coefficients are upscaled to send them out of the valid range.
- convert -size 64x8 xc: ppm:- \
- | cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 > 8blank.jpg
- dcttransform '
- a = new Uint16Array(3*8*64);
- i = 0;
- for (c=0;c<3;c++) for(z=-1;z<=1;z+=2) for(y=-1;y<=1;y+=2) for(x=-1;x<=1;x+=2) {
- a[64*i] = 64*[x,y,z][c];
- i++;
- }
- a
- ' 8blank.jpg > 8colors.jpg
- dcttransform 'dct.map(x => x/8)' 8colors.jpg > 8legal.jpg
- # Create two more color palettes.
- # These are similar to the above except that an additional value for Y, Cb, Cr has been added in the middle.
- # This middle color will be created in the final image by using one of the AC components for dithering.
- convert -size 216x8 xc: ppm:- \
- | cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 > 27blank.jpg
- dcttransform '
- a = new Uint16Array(3*27*64);
- i = 0;
- for(c=0;c<3;c++) for(z=-1;z<=1;z++) for(y=-1;y<=1;y++) for(x=-1;x<=1;x++) {
- a[64*i] = 64*[x,y,z][c];
- a[64*i+4] = 64*([x,y,z][c]==0);
- i++;
- }
- a
- ' 27blank.jpg > 27colors.jpg
- convert 27colors.jpg -colorspace LAB -resize 12.5% -scale 800% 27colors.png
- dcttransform 'dct.map((x, i) => (i%64==0) ? x/8 : 0)' 27colors.jpg > 27legal.jpg
- composite -blend 85% 27colors.png 27legal.jpg 27intermediate1.png
- composite -blend 35% 27colors.png 27legal.jpg 27intermediate2.png
- # Quantize all images to the colors in the palette.
- # Pixelate into 8x8 blocks.
- # The images are desaturated a bit before dithering as it seems to improve results.
- for i in 1 3 4; do
- convert "input$i" -colorspace sRGB -resize 12.5% +level 20% -remap 27colors.png +dither -remap 27intermediate1.png -remap 27intermediate2.png -remap 27legal.jpg -scale 800% "quant$i-27.ppm"
- done
- for i in 2 4; do
- convert "input$i" -colorspace sRGB -resize 12.5% +level 20% -remap 8colors.jpg +dither -remap 8legal.jpg -scale 800% "quant$i-8.ppm"
- done
- # JPEG compress the images using our quantization table.
- for f in *.ppm; do
- convert "$f" ppm:- \
- | cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 "$f" > "${f%.*}.jpg"
- dctextract < "${f%.*}.jpg" > "${f%.*}.dct"
- done
- # Combine the images.
- cat quant{1-27,2-8,3-27,4-27,4-8}.dct \
- | dcteval '
- n = dct.length/5;
- a = new Uint16Array(n);
- for (i = 0; i < n; i += 64) {
- // DC component
- a[i] = (
- 512*Math.sign(dct[i]) +
- + 128*Math.sign(dct[i]) * (dct[i+2*n]==0) +
- + 256*Math.sign(dct[i+n]) * (dct[i]==0 ? +1 : -1)
- - 128*Math.sign(dct[i+n]) * (dct[i]==0 && dct[i+2*n]==0)
- - 128*Math.sign(dct[i+2*n])
- - 64*Math.sign(dct[i+3*n])
- - 32*Math.sign(dct[i+4*n])
- );
- // AC component 4 in x direction
- a[i+4] = (
- 512*(dct[i]==0 && dct[i+2*n]!=0)
- + 128*(dct[i+2*n]==0)
- + 64*(dct[i+3*n]==0)
- );
- // AC component 4 in y direction
- a[i+32] = (
- 128*(dct[i+2*n]==0)
- + 512*(dct[i]==0 && dct[i+2*n]==0)
- );
- }
- a
- ' > output.dct
- dctreplace output.dct < quant1-27.jpg > output.jpg
- # Clean up.
- popd
- cp -- "$work/output.jpg" "$5"
- rm -r -- "$work"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement