(please forgive the following unstructured madness...)
This Python package lets you define a binary file-format, and then read and write data in this format. It is a spin-off from PicRW below.
I wanted a fairly easy way to read and write JPEG and TIFF files, and specially their meta-info, like photographer, caption and such. While there are packages for reading this I couldnt find any that could write. I also wanted to learn Python. And then I got greedy, I wanted more...
I didnt want to define yet another language, so everything is in Python. Using small building blocks of objects you define the format in a recursive hierarchial way. You can easily define new classes if you lack any. You can also insert small snippets of code that will be executed while reading or writing data.
As a programmer I love acronyms (ACR) so many things in the code are a three letter name (TLN). How else than producing new exotic acronyms (NEA) can a computer-consultatnt keep his job (KHJ)?
A format is an object from a subclass to the class Fmt.
The easiest way to get a format object is to call a constructor like Const({},{'val':'\0'})
,
which would then match the string '\0'
.
The first parameter will most certainly be {} for the moment,
and the second parameter is a dictionary whith the objects attributes.
Once you have an object like this you can call its read
function which if succesful
will fill its val
attribute reading data from a file, or,
if its val
attribute is properly filled in, you can call its write
function
and have its data written to a file.
Currently we have the following types of fmt's to play whith:
Fmt | Attribute | Use | Default | Dumped |
---|---|---|---|---|
Fmt | A superclass | |||
sup | the super-fmt this fmt belongs to | None | ||
nth | the index this fmt has in its super-fmts val-array, or -1 | -1 | Y | |
dep | the depth for this fmt in the fmt-tree | 0 | Y | |
pos | the position in the file for this fmt | 0 | Y | |
ard | action to be executed before read | None | ||
rda | action to be executed after read | None | ||
awr | action to be executed before write | None | Y | |
wra | action to be executed after write | None | Y | |
nam | the name for this fmt | '' | Y | |
usr | anything, its up to the user to make use of this slot | None | Y | |
FmtE(Fmt) | A superclass, an 'empty' fmt | |||
val | type depends on subclass | '' | Y | |
FmtB(Fmt) | A superclass, a Buff-like fmt | |||
val | read value, type depends on subclass | '' | Y | |
Fmt1(Fmt) | A superclass, a fmt with one sub-fmt | |||
val | the sub-fmt read | None | Y | |
FmtN(Fmt) | A superclass, a fmt with many sub-fmts | |||
val | the sub-fmts read | [] | Y | |
Or(Fmt1) | The first working format in fmt is used | |||
fmt | an array of possible formats of the data | [] | ||
And(FmtN) | All of the formats in fmt are used sequetially | |||
fmt | an array of the formats of the data | [] | ||
For(FmtN) | The format in fmt is repeated lim times | |||
fmt | the format of the data | None | ||
lim | the number of repititions as count or [min,max] | [0,sys.maxint] | Y | |
Until(FmtN) | The format in fmt is repeated until the format in tst succeds | |||
fmt | the format of the data | None | ||
tst | the format for the test | None | ||
kep | append the data to val that match tst? | True | Y | |
Buff(FmtB) | A string of siz bytes | |||
siz | the number of bytes to read | 0 | Y | |
val | the bytes read | None | Y | |
Tuff(FmtB) | A string of bytes until the format in tst succeds (terminated buff) | |||
tst | the format for the test | [Const,{'fmt':'\0'}] | ||
val | the bytes read | None | Y | |
Struct(FmtB) | Using the struct module | |||
fmt | a format string as in module struct | '>H' | Y | |
val | the data read | [] | Y | |
Varlen(FmtB) | Used in Midi | |||
val | the number read | 0 | Y | |
Const(FmtB) | The data must match this | |||
val | the string of bytes to match | None | Y | |
Detour(Fmt1) | Make a detour to det and do the format in fmt, then return | |||
det | the adress to seek to | 0 | Y | |
fmt | the format of the data | None | ||
Seek(FmtE) | Make a detour to val, don't return | |||
val | the adress to seek to | 0 | Y | |
Empty(FmtE) | ||||
Eof(FmtE) | Test for Eof | |||
Tell(FmtE) | Test for val | |||
val | the adress to compare tell whith | 0 | Y |
The red attributes are set by makeFmt
.
The green attributes are set by read
and write
.
A format can also be a string that will be evaluated.
Each Fmt has two functions to make it easier to navigate upwards to a sup-fmt:
iup(i)
which goes up i
steps.
nup(n)
which goes up until a sup whith nam == n
is found.
There are currently three examples of format-descriptions: Tiff, Jpeg and Midi,
they all come in one python-module each.
To use Midi.py
and run it on a file called x.mid, just type:
./Midi.py x.mid > x.mid.py
and you should get a script in x.mid.py.
If you then run the script, you should get py.x.mid
PicRW is more or less dead, use FmtRW instead While i was busy programming PicRW i realized that I should separate the format-description from the code, so take a look at FmtRW instead, it's currently slower, but much more fun.
A Python module that reads and writes JPEG and TIFF images. When the module is run as a script the module will read an image from file and emit a Python script that when run will generate the image file again.
If you have a file x.jpg do this at the prompt:
./PicRW.py -g x.jpg
and you will get a file called x.jpg.py
Edit it and then do this at the prompt:
./x.jpg.py
and you will get a file called py.x.jpg
Some help on the options:
./PicRW.py -h
Have fun!
updated 2004-06-06