Readme written

This commit is contained in:
Niles Rogoff 2016-11-30 19:40:57 -05:00 committed by Niles Rogoff
parent 557f81ff7c
commit 0e3460ce4e
No known key found for this signature in database
GPG Key ID: B78B908F23430F80
3 changed files with 89 additions and 8 deletions

Binary file not shown.

View File

@ -1,14 +1,14 @@
#!/usr/bin/env python3
# PNG Metadata Editor
# Niles Rogoff 2016
import struct, zlib, copy
import zlib, copy
class color_types(object):
GREYSCALE = 0
RGB = 2
PALETTE = 3
GREYSCALE_WITH_ALPHA = 4
RGB_WITH_ALPHA = 6
class PME(object):
class color_types(object):
GREYSCALE = 0
RGB = 2
PALETTE = 3
GREYSCALE_WITH_ALPHA = 4
RGB_WITH_ALPHA = 6
def _int(self, binary):
return int.from_bytes(binary, byteorder="big")
def _bytes(self, integer, length):
@ -40,7 +40,7 @@ class PME(object):
]
self.width = self.height = 0 # the user can decide
self.bit_depth = 8 # a sane default
self.color_type = self.color_types.RGB_WITH_ALPHA
self.color_type = color_types.RGB_WITH_ALPHA
self.compression_method = 0
self.filter_method = 0 # The only one as far as I know
self.interlace_method = 0

81
readme.md Normal file
View File

@ -0,0 +1,81 @@
# PNG Metadata Editor
This library was written for a competition between me and Ethan, who was going to write this same thing in Java. He failed.
You can initialize a PME instance by passing it a filename to an already existing file, or no arguments, like this:
img = new libpme.PME("test.png");
# or
img = new libpme.PME();
If the file is not valid, it will throw an exception
## Properties
These are the values that you can access or change. Most are self explanatory. Changing any of these will automatically call `recalculate_IHDR`. If you really want to suppress this behavior, just back up the IHDR chunk before changing the value. The defaults for an object created with no filename are displayed in parenthesis
width (0)
height (0)
bit_depth (8)
color_type (color_types.RGB_WITH_ALPHA (6))
compression_method (0)
filter_method (0)
interlace_method (0)
## Methods
Here are the methods you can call on an image, in no particular order
### `recalculate_properties`
This simply recalculates the seven properties listed above from the data currently in the IHDR chunk.
img.height = 400
img.chunks[0][2] = b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x06\x00\x00\x00'
# img.height remains unchanged at 400
img.recalculate_properties()
# img.height is now set to 0
### `recalculate_IHDR`
This takes the seven properties listed above and destructively replaces the first chunk's data and crc with updated fields
img.width = 0
# img.chunks[0][2] is now set to b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x06\x00\x00\x00'
img.width = 400
img.recalculate_IHDR()
# img.chunks[0][2] is now set to b'\x00\x00\x01\x90\x00\x00\x00\x00\x08\x06\x00\x00\x00'
### `recalculate_crc`
This takes an index of a chunk (see below) and overwrites the crc in that chunk with a newly calculated crc based on that chunk's label and data
img.color_type = libpme.color_types.RGB
img.width = img.height = 1
img.chunks[1][2] = b'\x00\xFF\x00\x00' # a 1x1 red image, assuming that the second chunk is the only IDAT chunk
img.recalculate_crc(1) # img.chunks[1][3] is now set to b'T\xbb\xd3\xea'
### `recalculate_length`
This takes an index of a chunk (see below) and updates the length of that chunk with a newly calculated length based on that chunk's data
img.color_type = libpme.color_types.RGB
img.width = img.height = 1
img.chunks[1][2] = img.compress(b'\x00\xFF\x00\x00') # a 1x1 red image, assuming that the second chunk is the only IDAT chunk
img.recalculate_length(1) # img.chunks[1][0] is now set to b'\x00\x00\x00\x04'
### `save`
This saves the image to the disk, overwriting a file if it was already there. If the object was created from an existing file and no arguments are passed, it will use the original file.
img.save("red1.png")
img.save() # Only if the object was created from an existing file.
### `get_concatenated_idat_data`
Concatenates the (still compressed) data of each IDAT chunk, then returns it.
img.width = 2
img.chunks.insert(2, [b'\x00\x00\x00\x03', b'IDAT', img.compress(b'\x00\xFF\x00'), b'j\xee\xb3\xd0']) # making it a 2x1 image with a red and a green pixel
img.decompress(img.get_concatenated_idat_data()) # returns '\x00\xFF\x00\x00\x00\xFF\x00';
### `write_raw_idat_data`
Deletes all IDAT chunks except the first one, then sets that chunk's data to the argument it was passed, and recalculates its crc and length.
img.write_raw_idat_data(img.compress(b'\x00\x00\x00\xFF\x00\x00\xFF')) # a 2x1 image with all blue pixels
## Indexes
Any function that takes an index can be passed either the numerical index of the chunk (so 0 for IDAT, 1 for the second chunk, -1 for the last chunk, etc..), or a list that exists in `img.chunks`, or a 4-length bytes object that is equal to the label of one of the chunks in the image. If a chunk with that label appears more than once, the first one will be used