Skip to content

Instantly share code, notes, and snippets.

@native-m
Last active November 16, 2019 19:44
Show Gist options
  • Save native-m/1b84e8582578527b86d7775b3b235d4e to your computer and use it in GitHub Desktop.
Save native-m/1b84e8582578527b86d7775b3b235d4e to your computer and use it in GitHub Desktop.
JPEG Emulator
# JPEG Emulator
# licensed under GPLv2 license
#
# What this thing does?
# It emulates jpeg DCT algorithm
#
# Python 3 is required to run this code
#
# HOW TO USE:
# 1. install numpy, scipy, and Pillow package
# 2. then execute:
# python jpegemu.py <input image> <output image> <coef size> <clip>
#
# COMMAND LINE INTERFACE:
# python jpegemu.py <input image> <output image> <coef size> <clip>
# <input image>: image to be processed
# <output image>: output to the resulting image
# <coef mul>: The quantization coefficient multiplication factor, higher means more compression
# <clip>: 'clip' or 'noclip',
# this will limit the color value in range of [-128, 127) ('clip' option),
# otherwise the color will not be clipped/limited ('unclip' option)
import sys
import numpy as np
import math
from PIL import Image, ImageFilter
from scipy.fftpack import dctn, idctn
qcoef = [[16, 11, 10, 16, 24, 40, 51, 61],
[12, 12, 14, 19, 26, 58, 60, 55],
[14, 13, 16, 24, 40, 57, 69, 56],
[14, 17, 22, 29, 51, 87, 80, 62],
[18, 22, 37, 56, 68, 109, 103, 77],
[24, 35, 55, 64, 81, 104, 113, 92],
[49, 64, 78, 87, 103, 121, 120, 101],
[72, 92, 95, 98, 112, 100, 103, 99]]
def main():
inputfile = sys.argv[1]
outputfile = sys.argv[2]
coefmul = int(sys.argv[3])
clip = sys.argv[4]
if sys.argv[4] == 'clip':
clip = True
else:
clip = False
try:
im = Image.open(inputfile)
im2 = Image.new("RGB",im.size,(0,0,0))
except IOError:
print("Cannot open file ", inputfile);
w, h = im.size
total = w/8 * h/8
progress = 0
coef = np.array(qcoef) * coefmul
for y in range(int(math.ceil(h/8))):
for x in range(int(math.ceil(w/8))):
idX = x*8
idY = y*8
parts = im.crop(box=(idX,idY,idX+8,idY+8))
splitRGB = parts.split()
r = np.array(list(splitRGB[0].getdata())).reshape(8,8) - 128
g = np.array(list(splitRGB[1].getdata())).reshape(8,8) - 128
b = np.array(list(splitRGB[2].getdata())).reshape(8,8) - 128
rdct = np.round(dctn(r,norm="ortho") / coef) * coef
gdct = np.round(dctn(g,norm="ortho") / coef) * coef
bdct = np.round(dctn(b,norm="ortho") / coef) * coef
if clip:
rdct = np.clip(idctn(rdct,norm="ortho"),-128,127)
gdct = np.clip(idctn(gdct,norm="ortho"),-128,127)
bdct = np.clip(idctn(bdct,norm="ortho"),-128,127)
else:
rdct = idctn(rdct,norm="ortho")
gdct = idctn(gdct,norm="ortho")
bdct = idctn(bdct,norm="ortho")
r = Image.fromarray(np.round(rdct + 128).astype(np.uint8), mode="L")
g = Image.fromarray(np.round(gdct + 128).astype(np.uint8), mode="L")
b = Image.fromarray(np.round(bdct + 128).astype(np.uint8), mode="L")
im2.paste(Image.merge(mode="RGB", bands=(r,g,b)), box=(idX,idY))
progress += 1
sys.stdout.write("\rProgress " + str(round(100 * (progress / total))) + "%")
sys.stdout.flush()
im2.save(outputfile)
im.close()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment