Newbie: working with binary files/extract png from a binary file

Discussion in 'Ruby' started by Jim, Jan 30, 2008.

  1. Jim

    Jim Guest


    I am reverse engineering a binary file that has an embedded PNG image
    in it. I opened the file in a hex editor and found the png header
    information, but how to use Ruby to extract the PNG to it's own file?
    Jim, Jan 30, 2008
    1. Advertisements

  2. Do you know the absolute starting position of the embedded PNG?

    You can get the data as a string like this:

    start_pos = 5 # or whatever
    end_pos = -1 # assume end of file
    png_data ='file_with_png', "rb") { |f|[start_pos..end_pos]

    Note that "rb" means open for read ("r") and treat as binary data ("b")
    (avoids munging "\r\n" on windows).

    If the end_pos has to be determined by reading a field, then this will
    take a little tinkering. I assume PNG has a length field somewhere? So
    you'll have to extract that (using String#unpack, perhaps) and chop off
    that many bytes from the start of the png_data string.
    Joel VanderWerf, Jan 30, 2008
    1. Advertisements

  3. Jim

    Adam Shelly Guest

    You can find it:

    fp ="has_embedded_png.dat","rb")
    m= /\211PNG/.match(
    raise "no PNG" if !m
    There's no total length field, just a series of 'chunks' each with
    its own length.
    Luckily, the 'IEND' chunk is always last, so you can just extract
    chunks until you get to that one:

    def extract_chunk(input, output)
    lenword =
    length = lenword.unpack('N')[0]
    type =
    data = length>0 ? : ""
    crc =
    return nil if length<0 || !(('A'..'z')===type[0,1])
    #return nil if validate_crc(type+data, crc)
    output.write lenword
    output.write type
    output.write data
    output.write crc
    return type

    def extract_png(input, output)
    hdr =
    raise "Not a PNG File" if hdr[0,4]!= "\211PNG"
    raise "file not in binary mode" if hdr[4,4]!="\r\n\032\n"
    loop do
    chunk_type = extract_chunk(input,output)
    p chunk_type
    break if chunk_type.nil? || chunk_type == 'IEND'

    ofp ="out.png","wb")

    Adam Shelly, Jan 30, 2008
  4. Jim

    Jim Guest

    Thank you both for your information and effort.

    Adam, your code worked out of the box. Tell me you didn't write that
    off the top of your head?

    fp ="has_embedded_png.dat","rb")
    # fp is a file pointer

    m= /\211PNG/.match(
    # ( is a String of binary data. Using a regular ex. to locate
    the PNG header

    raise "no PNG" if !m
    # exception if there is not a header match
    # I understand seek, Not sure what m.begin(0) is actually doing?

    Docs say: Returns the offset of the start of the nth element of the
    match array in the string.

    I still don't get it.
    Jim, Jan 30, 2008
  5. Jim

    Adam Shelly Guest

    I patched it together based on wikipedia's PNG entry and parts of a
    WAV file reader I wrote earlier - they are both chunk-based file
    formats. It took a few failed tests before I got it right.
    the PNG header
    from the same docs:
    "MatchData acts as an array. ... mtch[0] is equivalent to ... the
    entire matched string. "

    so m.begin(0) returns the offset of the start of the matched string
    (in this case, the start of the png header). Since the string
    contains the contents of the whole file, the string offset is the same
    as the file offset we need.
    Adam Shelly, Jan 31, 2008
  6. Jim

    Jim Guest

    OK, it's really not that hard is it? read N bytes from the stream. From the spec we know PNG
    has an header (they call a signature) that is 8 bytes. Check it. If
    it's a PNG, read the chunks until IEND

    The only other thing is unpack("N"). From the docs it takes a string
    of 4 bytes and returns a Fixnum.

    Thanks again for the code. The file I'm extracting is a SketchUp 3d
    model, btw.
    Jim, Feb 1, 2008
  7. Jim


    Le vendredi 1 février 2008 12:21:15 UTC+1, Jim a écrit :

    i would like to know how change the size of png extract cause is thumbailsand i would like to have bigger png extract

    thanks a lot

    , Dec 24, 2013
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.