Skip to content

Instantly share code, notes, and snippets.

@MCJack123
Created June 27, 2019 03:06
Show Gist options
  • Save MCJack123/fc38b3ef79ba3ae533defe4fcb7c509b to your computer and use it in GitHub Desktop.
Save MCJack123/fc38b3ef79ba3ae533defe4fcb7c509b to your computer and use it in GitHub Desktop.
PNG manipulation module in Python 2/3
import png # pip install pypng
class pixel:
def __init__(self, x=0, y=0, r=0, g=0, b=0, a=0):
self.x = x
self.y = y
self.r = r
self.g = g
self.b = b
self.a = a
def clone(self, r=None, g=None, b=None, a=None):
return pixel(self.x, self.y, self.r if r is None else r, self.g if g is None else g, self.b if b is None else b, self.a if a is None else a)
class image_scripter:
progress = 0.0
# Create a scripter from a file name or file object
def __init__(self, file):
self._image_in = png.Reader(file)
self.width, self.height, data, self.metadata = self._image_in.read()
self._image_in_data = []
self._image_out_data = None
y = 0
for row in data:
self._image_in_data.insert(y, [] * (self.width * self.metadata["planes"]))
for x in range(0, self.width * self.metadata["planes"], self.metadata["planes"]):
self._image_in_data[y].insert(int(x/self.metadata["planes"]), pixel(int(x/self.metadata["planes"]), y, row[x], row[x+1] if self.metadata["planes"] > 1 else 0, row[x+2] if self.metadata["planes"] > 2 else 0, row[x+3] if self.metadata["planes"] > 3 else 0))
y+=1
# Returns a pixel at a location
def get(self, x, y):
return self._image_in_data[y][x]
# Sets a pixel
def set(self, px):
self._image_in_data[px.y][px.x] = px
# Operates on the image using a function
# Any previous output will cycle to input
# Prototype: func(scripter, pixel)
def operate(self, func):
if self._image_out_data != None:
self._image_in_data = self._image_out_data
self._image_out_data = []
for i in range(0, self.height): self._image_out_data.insert(i, [] * (self.width * self.metadata["planes"]))
i = 0
for row in self._image_in_data:
for px in row:
self.progress = i / (self.width * self.height)
self._image_out_data[px.y].insert(px.x, func(self, px))
i+=1
self.progress = 1.0
# Writes the output to a file
def write(self, file):
img = png.Writer(self.width, self.height, size=self.metadata["size"], greyscale=self.metadata["greyscale"], alpha=self.metadata["alpha"], planes=self.metadata["planes"], bitdepth=self.metadata["bitdepth"], interlace=self.metadata["interlace"], gamma=self.metadata["gamma"])
rows = []
for i in range(0, self.height): rows.insert(i, [0] * (self.width * self.metadata["planes"]))
y=0
for r in self._image_out_data:
x=0
for px in r:
rows[y][x*self.metadata["planes"]] = px.r
if self.metadata["planes"] > 1: rows[y][x*self.metadata["planes"]+1] = px.g
if self.metadata["planes"] > 2: rows[y][x*self.metadata["planes"]+2] = px.b
if self.metadata["planes"] > 3: rows[y][x*self.metadata["planes"]+3] = px.a
x+=1
y+=1
fp = open(file, "wb")
img.write(fp, rows)
fp.close()
# Opens an image, operates on it, and writes the output to a file
def run(input, func, output):
scripter = image_scripter(input)
scripter.operate(func)
scripter.write(output)
# Turns image grayscale and flips it upside down
import imagescripter
def test(scripter, pixel):
p = scripter.get(pixel.x, scripter.height - pixel.y - 1)
avg = int((p.r + p.g + p.b) / 3)
return p.clone(avg, avg, avg)
imagescripter.run("input.png", test, "output.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment