simple_compression
This program is my first dabbling in image compression. It turns out that storing pixel data as gradients isn’t any smaller than indexing. Anyway, it was fun novel idea I had been meaning to try for a while (coded July 2010).
import struct from PIL import Image import math def writeUnsignedShort(stream,v): stream.write(struct.pack('<H', v)) def readUnsignedShort(stream): s = stream.read(2) p, = struct.unpack('<H', s) return p def writeDouble(stream,v): stream.write(struct.pack('d', v)) def readDouble(stream): s = stream.read(8) p, = struct.unpack('d', s) return p def writeUnsignedChar(stream,v): stream.write(struct.pack('c', chr(v))) def readUnsignedChar(stream): s = stream.read(1) p, = struct.unpack('c', s) return ord(p) def testOut(): s = open("byte_test","wb") writeUnsignedShort(s,10) s.close() s = open("byte_test","rb") print readUnsignedShort(s) s.close() class CompressedFile: def __init__(self): self.m = 0.0 self.b = 0.0 self.inds = [] self.size = [0,0] def writeFile(self, s): writeUnsignedShort(s, self.size[0]) writeUnsignedShort(s, self.size[1]) writeDouble(s, self.m) writeDouble(s, self.b) writeUnsignedShort(s, len(self.inds)) for ind in self.inds: writeUnsignedShort(s, ind) #writeUnsignedChar(s, ind) def readFile(self, s): self.size[0] = readUnsignedShort(s) self.size[1] = readUnsignedShort(s) self.m = readDouble(s) self.b = readDouble(s) inds_len = readUnsignedShort(s) for ind in range(inds_len): self.inds.append(readUnsignedShort(s)) #self.inds.append(readUnsignedChar(s)) ##double slope ##double intercept ##unsigned short size ## unsigned short pixel_index def linearRegression(points): #points are stored in this form [(x,y), ...] sum_xy = 0 sum_x = 0 sum_y = 0 sum_x2 = 0 for point in points: sum_xy+=point[0]*point[1] sum_x+=point[0] sum_y+=point[1] sum_x2+=point[0]**2 n = float(len(points)) m = (n*sum_xy - sum_x * sum_y)/(n*sum_x2-sum_x**2) #slope b = (sum_y-m*sum_x)/n #intercept return m, b def processSector(data): #data is [(R,G,B), ...] #let's just compress red to start with buffer = [] #[(value,old_index), ...] for i in range(len(data)): buffer.append((data[i][0],i)) buffer.sort() #sort from lowest to highest by first element #print buffer linreg_buffer = [] for i in range(len(buffer)): linreg_buffer.append((i,buffer[i][0])) m,b = linearRegression(linreg_buffer) print "slope", m, "intercept", b return_vals = [] #in original order with form [amplitude_index, ...] #create array to insert stuff into for i in range(len(buffer)): return_vals.append(0) for amplitude in range(len(buffer)): return_vals[buffer[amplitude][1]] = amplitude #buffer[amplitude][1] is the original ind return m,b,return_vals #just deal with one sector (255x255) for now def compressImage_single(): image = Image.open("vax.bmp") pixels = image.getdata() m,b,inds = processSector(pixels) f = CompressedFile() f.m = m f.b = b f.inds = inds f.size = list(image.size) s = open("output.compressed", "wb") f.writeFile(s) s.close() def compressImage(): image = Image.open("vax.bmp") pixels = image.getdata() m,b,inds = processSector(pixels) f = CompressedFile() f.m = m f.b = b f.inds = inds f.size = list(image.size) s = open("output.compressed", "wb") f.writeFile(s) s.close() ####now write it back and display the image def decompressImage_single(): s = open("output.compressed", "rb") f = CompressedFile() f.readFile(s) s.close() print "read:", f.m,f.b,f.size image = Image.new("RGB",tuple(f.size)) pixels = image.load() for i in range(f.size[0]*f.size[1]): x = i % f.size[0] y = math.ceil(i/f.size[0]) val = int(round(f.inds[i]*f.m+f.b)) #inds[i] amplitude or x value pixels[x, y] = (val,val,val) image.save("output.bmp") def decompressImage(): s = open("output.compressed", "rb") f = CompressedFile() f.readFile(s) s.close() print "read:", f.m,f.b,f.size image = Image.new("RGB",tuple(f.size)) pixels = image.load() for i in range(f.size[0]*f.size[1]): x = i % f.size[0] y = math.ceil(i/f.size[0]) val = int(round(f.inds[i]*f.m+f.b)) #inds[i] amplitude or x value pixels[x, y] = (val,val,val) image.save("output.bmp") #image must be evenly compressImage() decompressImage() #print linearRegression([(0,0),(2,2)])