Advertisement
Guest User

Ui, cat maid, Miku

a guest
Apr 15th, 2019
577
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 4.56 KB | None | 0 0
  1. #!/bin/bash
  2. set -x -e
  3. # This creates an JPEG file with three different appearances depending on how the image is decoded.
  4. # Ui will appear when using a decoder without integer overflows.
  5. # A cat maid will appear when using a decoder that wraps the DCT coefficients (after multiplication by the quantization table) into the range [-8192..8191].
  6. # Miku will appear when using a decoder that wraps the final Y, Cb, Cr values into the range 128 + [-512..512].
  7. # The dct* tools are available at https://gitgud.io/dcttransform/dcttransform
  8.  
  9. # Download the original images.
  10. curl https://raikou1.donmai.us/49/0f/__hirasawa_ui_k_on__490fc72508f093d39d489de73fc034bd.jpg > ui.jpg
  11. curl https://raikou1.donmai.us/75/5c/__original_drawn_by_moonyan__755cf95729cb727b5e5d08149a527804.jpg > catmaid.jpg
  12. curl https://danbooru.donmai.us/data/__nakano_miku_go_toubun_no_hanayome_drawn_by_mery_apfl0515__ff3cd29d48e5bd98b8318dd225a1c828.png > miku.png
  13.  
  14. # The quantization table used in the files created.
  15. # All values that will be used are set to 32.
  16. # The last entry (unused) has been set to a large value because it seems to force some programs to use one of the decoding methods I'm targeting.
  17. (for i in {1..63}; do echo 32; done; echo 4096) > qtable.txt
  18.  
  19. # Create two color palettes.
  20. # 8colors.jpg contains the colors obtained when pushing Y, Cb, Cr outside the valid ranges.
  21. # 8legal.jpg contains the colors obtained by setting Y, Cb, Cr to 128 +/- 32.
  22. convert -size 512x512 xc:red ppm:- | cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 > blank512.jpg
  23. dcttransform 'dct.map((x,i) => {if (i%64) return 0; x=(i>>6)%64; c=(i>>18); return 64*((Math.floor(x/8)&(1<<c)) ? 1 : -1)})' blank512.jpg > 8colors.jpg
  24. dcttransform 'dct.map((x,i) => {if (i%64) return 0; x=(i>>6)%64; c=(i>>18); return 8*((Math.floor(x/8)&(1<<c)) ? 1 : -1)})' blank512.jpg > 8legal.jpg
  25.  
  26. # Quantize all images to the colors in 8colors.jpg.
  27. # Also pixelate into 1x8 blocks. I don't have this working yet when vertical AC components are involved.
  28. # The images are desaturated a bit before dithering as it seems to improve results.
  29. for f in ui.jpg catmaid.jpg miku.png; do convert "$f" -resize 100%x12.5% -colorspace YCbCr +level 25% -colorspace sRGB -remap 8colors.jpg -scale 100%x800% "${f%.*}-quant.ppm"; done
  30.  
  31. # Remap all images from the 8colors.jpg colors to the 8legal.jpg colors and JPEG compress them using our quantization table.
  32. # Miku will be JPEG compressed at a later step.
  33. for f in ui catmaid miku; do convert "$f-quant.ppm" +dither -remap 8legal.jpg "$f-legal.ppm"; done
  34. for f in ui catmaid; do cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 "$f-legal.ppm" > "$f-legal.jpg"; done
  35.  
  36. # Ui is encoded in the DCT coefficients by adding/subtracting 512 (+/- 16384 after multiplication by the quantization table).
  37. # This will be discarded in the decoders that show the cat maid.
  38. # The file produced here will be further multiplied by 128, but for now we need it to be in the legal range.
  39. dcttransform 'n=dct.length; a=new Uint16Array(n); for(i=0;i<n;i++) a[i]=Math.sign(dct[i])*4; a' ui-legal.jpg > ui-enc.jpg
  40.  
  41. # Decompose Ui into Y, Cb, Cr components.
  42. dctextract < ui-enc.jpg > ui-enc.dct
  43. nbytes=$(stat -c %s ui-enc.dct)
  44. for i in {0..2}; do (tail -c +$((i*nbytes/3+1)) ui-enc.dct | head -c $((nbytes/3)); head -c $((2*nbytes/3)) /dev/zero) > "ui-enc-$i.dct"; done
  45. for i in {0..2}; do dctreplace "ui-enc-$i.dct" < ui-enc.jpg > "ui-enc-$i.jpg"; done
  46.  
  47. # Decompose Miku into Y, Cb, Cr components.
  48. convert miku-legal.ppm -colorspace YCbCr -separate miku-legal-%d.ppm
  49.  
  50. # Miku is encoded in the last 10 bits of the final Y, Cb, Cr values, as an offset of +/- 256 from one of the wrap points (128 - 512 + 1024n).
  51. # Ui has contaminated these bits and needs to be corrected.
  52. # The correction is done before JPEG compression.
  53. # The cat maid (not yet added) will contribute +/- 512.
  54. # Here, the 128 + [-512..512] range is compressed into 128 + [-128..127]; it will be multiplied by -4 later.
  55. for i in {0..2}; do convert "miku-legal-$i.ppm" "ui-enc-$i.jpg" -fx 'mod(2*u+32*v+128/255,256/255)' "miku-enc-$i.ppm"; done
  56. for i in {0..2}; do cjpeg -qtables qtable.txt -qslots 0 -sample 1x1 "miku-enc-$i.ppm" > "miku-enc-$i.jpg"; done
  57.  
  58. # Recombine channels.
  59. for i in {0..2}; do dctextract < "miku-enc-$i.jpg" | head -c $((nbytes/3)); done > miku-enc.dct
  60.  
  61. # Combine Ui, cat maid, and Miku (+ Ui correction).
  62. dctextract < catmaid-legal.jpg > catmaid-legal.dct
  63. cat ui-enc.dct catmaid-legal.dct miku-enc.dct | dcteval 'n=dct.length/3; a=new Uint16Array(n); for(i=0;i<n;i++) a[i]=128*dct[i]+16*dct[i+n]-4*dct[i+2*n]; a' > ucm.dct
  64. dctreplace ucm.dct < ui-legal.jpg > ucm.jpg
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement