#!/usr/bin/env/python """ by Kris Schnee """ __author__ = "Kris Schnee" __license__ = "" ##### DEPENDENCIES ##### ## Standard ## Third-party import pygame ## Mine ##### CONSTANTS ##### ##### CLASSES ##### class Mask: def __init__(self): self.img = None def Load(self,filename): ## Create a Pygame Surface object. self.img = pygame.image.load(filename) def Save(self,filename): pygame.image.save(self.img,filename) def Write(self,text): if not self.img: raise "Need to load an image first." ## Set up the pixel location we'll be writing to. x = 0 y = 0 x_max = self.img.get_width() y_max = self.img.get_height() for c in text: ## Get binary value bin = self.ToBin(ord(c)) ## Write each 0 or 1 to the next pixel. for char in bin: if char == "0": self.img.set_at((x,y),(0,0,0,255)) else: ## Change the red channel by +- 1. ## (This method only is readable by comparison to the original image.) pixel = self.img.get_at((x,y)) ## if pixel[0] == 255: ## self.img.set_at((x,y),(pixel[0]-1,pixel[1],pixel[2],pixel[3])) ## else: ## self.img.set_at((x,y),(pixel[0]+1,pixel[1],pixel[2],pixel[3])) ## You know what? Just make it black/grey. self.img.set_at((x,y),(128,128,128,255)) ## Advance to next pixel if possible. x += 1 if x == x_max: x = 0 y += 1 if y == y_max: raise "Error: This message was too long for this size image." def ToBin(self,n): bstr = lambda n, l=16: n<0 and binarystr((2L<>1).lstrip('0')+str(n&1) or '0' return bstr(n) ##### OTHER FUNCTIONS ##### ##### AUTORUN ##### if __name__ == "__main__": ## Do the following if this code is run by itself: m = Mask() m.Load("darwin.png") m.Save("before.png") ## Write a placebo image that might be changed by this program's saving method. f = open("flag.txt","r") text = f.read() f.close() m.Write(text) m.Save("after.png")