Hi,

My question is sort of on the difficult side, but I promise I'm a newb
;) So maybe it isn't..


Frederick Lundh himself gave me this chunk of code..and I can't get it
to work. I was hoping someone could spot the error.

The goal is to extract a png image file from a binary simcity 4 file.
#import struct
#
#def pngcopy(infile, outfile):
#
#   # copy header
#   header = infile.read(8)
#   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(8)
#       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("/home/flamesrock/Desktop/peachville.sc4", "rb")
#infile.seek(0x50)
#outfile = open("myimage.png", "wb")
#pngcopy(infile, outfile)
#outfile.close()
#infile.close()

It returns the IO error when I try it on this and other files:
http://simcitysphere.com/peachville.sc4

I've confirmed the position using a hex editor (its the first 'P' or
0x50 in the file)
http://simcitysphere.com/peachville.png

The idea comes from this php code which works -if only I could
understand how to translate it. The code may or may not also extract
data which denotes a relative position on an image map:
also available at http://simcitysphere.com/regionFileDecode_inc.php.txt
<?php
        function fileDecode($inbuf, $Cname)
        {
                  /* length of data */
                  $inlen=strlen($inbuf);

                  $outlen       =       unpack1($inbuf[6],'C') << 16;
                  $outlen       +=      unpack1($inbuf[7],'C') << 8;
                  $outlen       +=      unpack1($inbuf[8],'C');

                  /* position in file */
                  $inpos=9;
                  $outpos=0;

                  $outbuf =array();

                  while (($inpos<$inlen)&&(unpack1($inbuf[$inpos],'C')<0xFC))
                        {


                                 $packcode=$inbuf[$inpos];
                                 $packcode=unpack1($packcode,'C');
                                 $a=unpack1($inbuf[$inpos+1],'C');
                                 $b=unpack1($inbuf[$inpos+2],'C');
                                 //decho("inlen: {$inlen} | outlen: {$outlen} | 
inpos: {$inpos} |
outpos: {$outpos} | packcode: $packcode");
                                 
                                 if (!($packcode&0x80)) {
                                        //decho('match 0x80');
                                        $lena=$packcode&3;
                                        
mmemcpy($outbuf,$outpos,$inbuf,$inpos+2,$lena);
                                        $inpos+=$lena+2;
                                        $outpos+=$lena;
                                        $lenb=(($packcode&0x1c)>>2)+3;
                                        $offset=(($packcode>>5)<<8)+$a+1;
                                        
mmemcpy($outbuf,$outpos,$outbuf,$outpos-$offset,$lenb);
                                        $outpos+=$lenb;
                                        //decho ("Code $packcode len plain: 
$lena len: $lenb offset:
$offset outpos: $outpos");
                                 }
                                 else if (!($packcode&0x40)) {
                                        //decho('match 0x40');
                                        $lena=($a>>6)&3; 
                                        
mmemcpy($outbuf,$outpos,$inbuf,$inpos+3,$lena);
                                        $inpos+=$lena+3;
                                        $outpos+=$lena;
                                        $lenb=($packcode&0x3f)+4;
                                        $offset=($a&0x3f)*256+$b+1;
                                        
mmemcpy($outbuf,$outpos,$outbuf,$outpos-$offset,$lenb);
                                        $outpos+=$lenb;
                                        //decho ("Code $packcode len plain: 
$lena len: $lenb offset:
$offset outpos: $outpos");
                                 }  
                                 else if (!($packcode&0x20)) {
                                        //decho('match 0x20');
                                        $c=unpack1($inbuf[$inpos+3],'C');
                                        $lena=$packcode&3; 
                                        
mmemcpy($outbuf,$outpos,$inbuf,$inpos+4,$lena);
                                        $inpos+=$lena+4;
                                        $outpos+=$lena;
                                        $lenb=(($packcode>>2)&3)*256+$c+5;
                                        
$offset=(($packcode&0x10)<<12)+256*$a+$b+1;
                                        
mmemcpy($outbuf,$outpos,$outbuf,$outpos-$offset,$lenb);
                                        $outpos+=$lenb;
                                        //decho ("Code $packcode len plain: 
$lena len: $lenb offset:
$offset outpos: $outpos");
                                 }  
                                 else {
                                        //decho('match 0x1f');
                                        $len=($packcode&0x1f)*4+4;
                                        
mmemcpy($outbuf,$outpos,$inbuf,$inpos+1,$len);
                                        $inpos+=$len+1;
                                        $outpos+=$len;
                                        //decho ("Code $packcode Plain Chars: 
$len outpos: $outpos");
//Code 224 Plain Chars: 4 outpos: 0
                                 }
                        }

                  /* trailing bytes 
                  if (($inpos<$inlen)&&($outpos<$outlen)) {
                         
mmemcpy($outbuf,$outpos,$inbuf,$inpos+1,unpack1($inbuf[$inpos],'C')&3);
                         $outpos+=unpack1($inbuf[$inpos],'C')&3;
                  }
                  */
                  
                  /*
                  if ($outpos!=$outlen) 
                          decho("Warning: bad length ? {$outpos} instead of 
{$outlen} with
{$Cname}");
                  */
                  $buflen=$outlen;
                  return $outbuf;
        }



        function mmemcpy(&$dest, $destpos, &$src, $srcpos, $len)
                {
                  while ($len--)
                        {
                                //decho ("destpos: $destpos | srcpos: 
{$src[$srcpos]}");
                                $dest[$destpos] = $src[$srcpos];

                                $destpos++;
                                $srcpos++;
                        }
                }


        function unpack1($bytes, $type=false)
        {
                if($type)
                {
                        $dat = unpack("{$type}int",$bytes);
                        return $dat['int'];
                } else {
                        $dat = unpack('Vint',$bytes);
                        return $dat['int'];
                }
        }
?>

ANY replies are welcome. Even if you don't know the answer, something
to point me in the right direction would be greatly appreciated. I'm
completely stuck.

-thanks
_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to