Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Howto Extract PNG from binary file @ 0x80?

Reply
Thread Tools

Howto Extract PNG from binary file @ 0x80?

 
 
flamesrock
Guest
Posts: n/a
 
      12-11-2004
Hi,

As a newbie to the language, I have no idea where to start..please bare
with me..

The simcity 4 savegame file has a png image stored at the hex location
0x80. What I want to extract it and create a file with the .png
extension in that directory.

Can somebody explain with a snippet of code how I would accomplish
this? I've looked around but the information is too vague and I don't
know how to start.

-thanks in advance

 
Reply With Quote
 
 
 
 
Fredrik Lundh
Guest
Posts: n/a
 
      12-11-2004
"flamesrock" <(E-Mail Removed)> wrote:

> As a newbie to the language, I have no idea where to start..please bare
> with me..
>
> The simcity 4 savegame file has a png image stored at the hex location
> 0x80. What I want to extract it and create a file with the .png
> extension in that directory.
>
> Can somebody explain with a snippet of code how I would accomplish
> this? I've looked around but the information is too vague and I don't
> know how to start.


there are *many* ways to ignore the first 128 bytes when you read a file
(you can seek to the right location, you can read 128 bytes and throw them
a way, you can read one byte 128 times and throw each one of them away,
you can read all data and remove the first 128 bytes, etc).

here's a snippet that understands the structure of the PNG, and stops copying
when it reaches the end of the PNG:

import struct

def pngcopy(infile, outfile):

# copy header
header = infile.read(
if header != "\211PNG\r\n\032\n":
raise IOError("not a valid PNG file")
outfile.write(header)

# copy chunks, until IEND
while 1:
chunk = infile.read(
size, cid = struct.unpack("!l4s", chunk)
outfile.write(chunk)
outfile.write(infile.read(size))
outfile.write(infile.read(4)) # checksum
if cid == "IEND":
break

to use this, open the input file (the simcity file) and the output file
(the png file you want to create) in binary mode, use the "seek"
method to move to the right place in the simcity file, and call "pngcopy"
with the two file objects.

infile = open("mysimcityfile", "rb")
infile.seek(0x80)
outfile = open("myimage.png", "wb")
pngcopy(infile, outfile)
outfile.close()
infile.close()

hope this helps!

</F>



 
Reply With Quote
 
 
 
 
Aaron
Guest
Posts: n/a
 
      12-23-2004
On Sat, 11 Dec 2004 10:53:19 +0100, Fredrik Lundh wrote:

> "flamesrock" <(E-Mail Removed)> wrote:
>
>> As a newbie to the language, I have no idea where to start..please bare
>> with me..
>>
>> The simcity 4 savegame file has a png image stored at the hex location
>> 0x80. What I want to extract it and create a file with the .png
>> extension in that directory.
>>
>> Can somebody explain with a snippet of code how I would accomplish
>> this? I've looked around but the information is too vague and I don't
>> know how to start.

>
> there are *many* ways to ignore the first 128 bytes when you read a file
> (you can seek to the right location, you can read 128 bytes and throw them
> a way, you can read one byte 128 times and throw each one of them away,
> you can read all data and remove the first 128 bytes, etc).
>
> here's a snippet that understands the structure of the PNG, and stops copying
> when it reaches the end of the PNG:
>
> import struct
>
> def pngcopy(infile, outfile):
>
> # copy header
> header = infile.read(
> if header != "\211PNG\r\n\032\n":
> raise IOError("not a valid PNG file")
> outfile.write(header)
>
> # copy chunks, until IEND
> while 1:
> chunk = infile.read(
> size, cid = struct.unpack("!l4s", chunk)
> outfile.write(chunk)
> outfile.write(infile.read(size))
> outfile.write(infile.read(4)) # checksum
> if cid == "IEND":
> break
>
> to use this, open the input file (the simcity file) and the output file
> (the png file you want to create) in binary mode, use the "seek"
> method to move to the right place in the simcity file, and call "pngcopy"
> with the two file objects.
>
> infile = open("mysimcityfile", "rb")
> infile.seek(0x80)
> outfile = open("myimage.png", "wb")
> pngcopy(infile, outfile)
> outfile.close()
> infile.close()
>
> hope this helps!
>
> </F>


Thanks! And what a pleasant surprise! I just noticed you authored the book
I've been studying - Python Standard Library. Its awesome

Oh- and Sorry for the late response. Google groups wouldn't allow me to
followup. I'm using pan now.

 
Reply With Quote
 
flamesrock
Guest
Posts: n/a
 
      01-04-2005
Well, I've been working on getting this code to work, and I think I
*almost* have it...

First, according to ghex, it seems the PNG starts at the 97th byte of
the file
infile = open("mysimcityfile.sc4", "rb")
infile.seek(97)
print (infile.read(4))
output:
flamesrock@flames:~/score$ python sc4png.py
PNG
(for 5 bytes it outputs an extra line, and for 6- 
(the biology symbol for a male)) So to debug further, I took out the
exception and modified the code like this:

#import struct
#
#def pngcopy(infile, outfile):
#
# # copy header
# header = infile.read(4)
# #if header != "\211PNG\r\n\032\n":
# # raise IOError("not a valid PNG file")
# outfile.write(header)
#
# # copy chunks, until IEND
# while 1:
# chunk = infile.read(
# size, cid = struct.unpack("!l4s", chunk)
# outfile.write(chunk)
# outfile.write(infile.read(size))
# outfile.write(infile.read(4)) # checksum
# if cid == "IEND":
# break
#
#
#infile = open("mysimcityfile.sc4", "rb")
#infile.seek(97)
#outfile = open("myimage.png", "wb")
#pngcopy(infile, outfile)
#outfile.close()
#infile.close()

returning the following output:
flamesrock@flames:~/score$ python sc4png.py
Traceback (most recent call last):
File "sc4png.py", line 26, in ?
pngcopy(infile, outfile)
File "sc4png.py", line 14, in pngcopy
size, cid = struct.unpack("!l4s", chunk)
struct.error: unpack str size does not match format

Any ideas on how to fix it? If I understand this page correctly,
http://www.python.org/doc/current/li...le-struct.html
a png is basically a 'big endian string of 14 chars'? Changing it to
!14b" gives a"ValueError: unpack tuple of wrong size"
-thanks in advance for any help

 
Reply With Quote
 
Robert Kern
Guest
Posts: n/a
 
      01-04-2005
flamesrock wrote:

[snip]

> flamesrock@flames:~/score$ python sc4png.py
> Traceback (most recent call last):
> File "sc4png.py", line 26, in ?
> pngcopy(infile, outfile)
> File "sc4png.py", line 14, in pngcopy
> size, cid = struct.unpack("!l4s", chunk)
> struct.error: unpack str size does not match format
>
> Any ideas on how to fix it? If I understand this page correctly,
> http://www.python.org/doc/current/li...le-struct.html
> a png is basically a 'big endian string of 14 chars'? Changing it to
> !14b" gives a"ValueError: unpack tuple of wrong size"
> -thanks in advance for any help


No, the chunk header is specified as "!l4s" where that second character
is a lower-case "L", not one "1". The struct is "a 4-byte long integer
in big-endian format followed by a 4-character string".

I think the error you are running into is that the chunk you are passing
in does not have 8 characters. Is your input truncated somehow?

--
Robert Kern
http://www.velocityreviews.com/forums/(E-Mail Removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
Reply With Quote
 
flamesrock
Guest
Posts: n/a
 
      01-04-2005
Hmm...I'm not sure exactly. One of the things I've read is that
sometimes stuff is compressed in a savegame file, but I don't know why
they'd do that with a png..

I have some code that does the exact same thing in php only I don't
understand php syntax and how they did it. Does it give any clues as to
whether its truncated or not? (assuming you understand php)
http://simcitysphere.com/sc4Extractor.php.txt (original, only extracts
png)
http://simcitysphere.com/regionFileDecode_inc.php.txt (extracts png and
some fancy stuff like image map position)

-thanks

 
Reply With Quote
 
Robert Kern
Guest
Posts: n/a
 
      01-04-2005
Don't seek to position 97. Seek to 96. You're off by one. That's why
there's the test for the header (which you removed).

Files (and Python strings for that matter) are 0-indexed. The first
character is 0, the second 1, and so on. If you want the 97th character,
you have to seek to position 96.

--
Robert Kern
(E-Mail Removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
Reply With Quote
 
flamesrock
Guest
Posts: n/a
 
      01-04-2005
omg, it works!! thankyou!!!!!
and thankyou again, Frederick for the original code!

I've discovered a weird thing when changing header = infile.read( to
header = infile.read(4):
For some reason, the extracted png image is the exact same size as the
savegame archive (10.1 megs.) When reading 8bytes, its closer to
~200kb. Any clue as to why that is?

-thanks

#import struct
#
#def pngcopy(infile, outfile):
#
# # copy header
# header = infile.read(
# if header != "\211PNG\r\n\032\n":
# raise IOError("not a valid PNG file")
# outfile.write(header)
#
# # copy chunks, until IEND
# while 1:
# chunk = infile.read(
# size, cid = struct.unpack("!l4s", chunk)
# outfile.write(chunk)
# outfile.write(infile.read(size))
# outfile.write(infile.read(4)) # checksum
# if cid == "IEND":
# break
#
#
#infile = open("mysimcityfile.sc4", "rb")
#infile.seek(96)
###print (infile.read(4))
#outfile = open("myimage.png", "wb")
#pngcopy(infile, outfile)
#outfile.close()
#infile.close()

(http://simcitysphere.com/peachville.sc4)

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Newbie: working with binary files/extract png from a binary file Jim Ruby 6 12-24-2013 08:09 AM
Creating a 24-bit PNG with binary transparency? Leif K-Brooks HTML 7 07-20-2009 09:40 AM
howto extract type pattern from xsd shema file / or DOM Document object from JAVA andrzej.gdula@gmail.com Java 0 10-11-2007 09:18 AM
howto generate html email with reference to a png-picture (inline) thomas.frei@web.de Perl Misc 1 10-02-2007 06:18 PM
ANN: PNG image CAPTCHA with PNG canvas available (SkimpyGimpy) aaronwmail-usenet@yahoo.com Python 0 04-18-2007 07:33 PM



Advertisments