import logging
import math
import BaseJpegDecode
import bmp24
zigzag = [ 0,
1, 8,
16, 9, 2,
3,10,17,24,
32,25,18,11, 4,
5,12,19,26,33,40,
48,41,34,27,20,13,6,
7,14,21,28,35,42,49,56,
57,50,43,36,29,22,15,
23,30,37,44,51,58,
59,52,45,38,31,
39,46,53,60,
61,54,47,
55,62,
63]
def adjust(value):
value += 128
if value < 0:
return 0
elif value > 255:
return 255
return int(value)
class jpeg2bmp(BaseJpegDecode.BaseJpegDecode):
def __init__(self):
super(jpeg2bmp, self).__init__()
self._values = [0]*64
self.bmp = bmp24.bmp24()
def bmp_output_string(self):
self.bmp.width = self.width
self.bmp.height = self.height
return self.bmp.output_string()
def outputDot(self, mcu, block, x, y, value):
rgb = (value, value, value)
mcu_x = mcu % (self.width/16)
mcu_y = mcu / (self.width/16)
if self._yblock == 2:
if block == 0:
self.bmp.point(mcu_x * 16 + x, mcu_y * 8 + y, rgb)
elif block == 1:
self.bmp.point(mcu_x * 16 + 8 + x, mcu_y * 8 + y, rgb)
elif self._yblock == 4:
if block <= 3:
ox, oy = [(0,0),(8,0),(0,8),(8,8)][block]
self.bmp.point(mcu_x * 16 + ox + x, mcu_y * 16 + oy + y, rgb)
else:
raise ValueError('yblock error')
def _rDCT(self, mcu, block, s):
N=8
for y in range(N):
for x in range(N):
sum = 0.0
for v in range(N):
cv = 1.0
if v == 0:
cv /= math.sqrt(2)
for u in range(N):
cu = 1.0
if u == 0:
cu /= math.sqrt(2)
vu = v*8+u
cosxu = math.cos((x*2+1)*u*math.pi/(N*2))
cosyv = math.cos((y*2+1)*v*math.pi/(N*2))
sum += cu * cv * s[vu] * cosxu * cosyv
sum /= (N/2)
self.outputDot(mcu, block, x, y, adjust(sum))
def _output(self, mcu, block, scan, value):
if self._yblock == 2:
sc = [0,0,1,1][block]
else:
sc = [0,0,0,0,1,1][block]
self._values[zigzag[scan]] = value * self.qt[sc][scan]
if scan == 63:
self._rDCT(mcu, block, self._values)
def outputDC(self, mcu, block, value):
self._values = [0]*64
self._output(mcu, block, 0, value)
if block == 0:
print("%02X" % adjust(value * self.qt[0][0] / 8)),
if (mcu % (self.width/16)) == (self.width/16)-1:
print
def outputAC(self, mcu, block, scan, value):
self._output(mcu, block, scan, value)
def outputMARK(self, c):
pass
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('infiles', nargs='*')
args = parser.parse_args()
decode = jpeg2bmp()
for i, filename in enumerate(args.infiles):
with open(filename, "rb") as f:
data = f.read()
print("%s %d" % (filename, len(data)))
decode.clear()
for c in data:
decode.input(ord(c))
image_data = decode.bmp_output_string()
output_filename = "output%d.bmp" % i
with open(output_filename, "wb") as f:
f.write(image_data)
print output_filename