Milktea Skrevet 27. oktober 2007 Del Skrevet 27. oktober 2007 Hei, vet ikke om det er lov å komme med slike forespørsler, men det gjenstår vel bare å se? Har et spesielt format, SPR, som består av bitmaps med en fargeindeks. Jeg trenger et script som kan lese en mappe, ta for seg en og en fil av typen .spr, hente ut første BMP lagret og lagre dette i en separat mappe. Så har det seg slik at jeg har funnet et gammelt script som leser en og en fil av formatet, men dumper alle rammene som en HTML-fil med hver pixel som en <span> med bakgrunnsfarge. Det jeg ber om er at noen kan skrive scriptet om slik det altså lagrer det første bildet som BMP i en undermappe, og muligheten for å kunne massedumping ved å spesifisere en mappe til SPR-filene. Informasjon om formatet: magic 2 int16 'PS', magic identifier minor_ver 1 int8 Minor version major_ver 1 int8 Major version num_pal_imgs 2 int16 Number of palette images num_flat_imgs 2 int16 Number of flat images present in version > 1.1 { * array pal images pal_image * uint8 pal image RLE encoded in version 2.1+ } { * array flat images flat_image * uint8 flat image present in version 2.0+ } palette 256*4 int32 Palette present in version 1.1+ (seek to end - 1024) Scriptet: #file to read SPR format files #read the file name off of the command line my $TargetFile=shift||die "No target SPR file specified.\n"; my @temp=split("\\x5C", $TargetFile); my $TargetFileName=$temp[-1]; #pull off the file name #see if it exists if (!stat($TargetFile)) {die "The SPR file '$TargetFile' does not exist.\n";} #open the input file and and output file open(FHI, $TargetFile) or die "Unable to read from target file '$TargetFile'.\n"; open(FHO, ">".$TargetFileName.".html") or die "Unable to create output file.\n"; #create the initial HTML page header and style section print FHO "<html>\n"; print FHO "<head>\n"; print FHO "<style>\n"; print FHO "TT {\n"; print FHO " font-size: 8pt;\n"; print FHO "}\n"; print FHO "</style>\n"; print FHO "</head>\n"; print FHO "<body>\n"; my @PaletteArray; my @FrameArray; my %FrameHash; #start reading the data in my $FileHeader=ReadFileBytes(2); my $FileMajorVersion=unpack("C1", ReadFileBytes(1)); my $FileMinorVersion=unpack("C1", ReadFileBytes(1)); my $ImageCount=unpack("C4", ReadFileBytes(4)); print FHO "<h1>$TargetFileName</h1>\n"; print "File ".$TargetFileName."\n"; print "Header ".$FileHeader."\n"; print "Major version ".$FileMajorVersion."\n"; print "Minor version ".$FileMinorVersion."\n"; print "Image count ".$ImageCount." frames\n"; print FHO "Header: ".$FileHeader."<br>\n"; print FHO "Major version: ".$FileMajorVersion."<br>\n"; print FHO "Minor version: ".$FileMinorVersion."<br>\n"; print FHO "Image count: ".$ImageCount." frames<br>\n"; #read the graphic section of the sprite for my $FrameNum (0..$ImageCount-1) { #need to read the size data in backwards #I'm sure there's a better way to do this, but this was faster than looking for the correct method my $HB; my $LB; $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageX=hex(unpack("H4", $HB.$LB)); #88 $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageY=hex(unpack("H4", $HB.$LB)); #86 $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageLength=hex(unpack("H4", $HB.$LB)); #7568? my $ImageData=ReadFileBytes($ImageLength); # "--------------------" print "\n"; print "Image #".$FrameNum."\n"; print "Image X ".$ImageX."\n"; print "Image Y ".$ImageY."\n"; print "Data Length ".$ImageLength."\n"; #compression runs from left to right in 2 char pairs #when palette "00" is encountered, next byte is count of pixels to repeat the "00" color unless - # the next byte is also "00", then it is just a simple bit and the next byte is NOT a count #only the background color 00 is ever compressed (and sometimes it is not compressed) #compression can wrap to the next line my @SpriteFramePixelArrary; my $DataIndex=0; my $RawData=""; #walk the length of the array while ($DataIndex<$ImageLength) { my $temp=""; my $BitLength=1; my $Bit=unpack("H2", substr($ImageData, $DataIndex, 1)); #check for the background bit to be set if ($Bit eq "00") { $DataIndex++; $BitLength=hex(unpack("H2", substr($ImageData, $DataIndex, 1))); #is it compressed data? if ($BitLength==0) { #nope, not compressed data, reset the bit length $BitLength=1; $DataIndex--; #Oops, uncompressed data, go backwards 1 byte since we looked ahead } #end uncompressed data chack if } #end background bit check if #now uncompress the data into a temp array for my $subindex (1..$BitLength) {push(@SpriteFramePixelArrary, $Bit); $temp.=$Bit." ";} #print $temp; $RawData.=$Bit." "; $DataIndex++; } #end for #this is just for the command line, we don't really need to show this print "Raw Data:\n"; print $RawData."\n"; #put the data into a hash so we can get at it later $FrameHash{$FrameNum}->{X}=$ImageX; $FrameHash{$FrameNum}->{Y}=$ImageY; @{$FrameHash{$FrameNum}->{DATA}}=@SpriteFramePixelArrary; } #end frames for #read the pallette info here my $PaletteData=ReadFileBytes(1024); #allways the same size #now make a nice color chart in a 16 x 16 grid #in case you were wondering, the first color in the palette is the transparancy color for all the frames print FHO "<h1>Palette data</h1>\n"; print FHO "Format: Palette#-RRGGBB (red green blue)<br>\n"; my $IndexLocation=0; my $IndexNum=0; for my $XIndex (1..16) { for my $YIndex (1..16) { #dig out the color values in 4 byte chunks my $RGBChunk=substr($PaletteData, $IndexLocation, 4); my $Red=uc(unpack("H2", substr($RGBChunk, 0, 1))); my $Green=uc(unpack("H2", substr($RGBChunk, 1, 1))); my $Blue=uc(unpack("H2", substr($RGBChunk, 2, 1))); my $Trans=unpack("H2", substr($RGBChunk, 3, 1)); #we don't care about this value print FHO "<span style=\"background-color: #$Red$Green$Blue;\"><tt>".uc(sprintf("%02x", $IndexNum))."-$Red$Green$Blue</tt></span> "; $IndexLocation=$IndexLocation+4; $IndexNum++; push(@PaletteArray, "$Red$Green$Blue"); #add it into an array for later } #end Y for print FHO "<br>\n"; } #end X for #now make some nice color HTML pictures of the sprite data we worked on earlier now that we know the colors #why HTML? because I'm too lazy to add GD module code here. for my $FrameNum (0..$ImageCount-1) { #@SpriteFramePixelArrary print FHO "<h1>Frame ".($FrameNum+1)."</h1>\n"; print FHO "Size: ".$FrameHash{$FrameNum}->{X}." x ".$FrameHash{$FrameNum}->{Y}."<br>\n"; my $IndexLocation=0; for my $YIndex (1..$FrameHash{$FrameNum}->{Y}) { for my $XIndex (1..$FrameHash{$FrameNum}->{X}) { my $ColorPaletteIndex=hex($FrameHash{$FrameNum}->{DATA}[$IndexLocation]); print FHO "<span style=\"background-color: #".$PaletteArray[$ColorPaletteIndex]."\"><tt>".uc($FrameHash{$FrameNum}->{DATA}[$IndexLocation])."</tt></span> "; $IndexLocation++; } #end Y for print FHO "<br>\n"; } #end X for } #end second frame for print FHO "<br>\n"; print FHO "</body>\n"; print FHO "</html>\n"; close(FHO); close(FHI); print "All done.\n"; exit; # ---------- Subs go here ---------- sub ReadFileBytes { my $BytesToRead=shift||return 0; my $DataRead; sysread(FHI, $DataRead, $BytesToRead); return $DataRead; } __END__ Aner ikke hvor mye arbeid dette vil ta, så si ifra om jeg ber om alt for mye. Lenke til kommentar
Milktea Skrevet 27. oktober 2007 Forfatter Del Skrevet 27. oktober 2007 Eksempelfil, i tilfelle noen vil prøve seg. Lenke til kommentar
trtrtr Skrevet 28. oktober 2007 Del Skrevet 28. oktober 2007 Dette programmet konverter .spr filer til .bmp http://sourceforge.net/projects/spriteviewer Programmet er på spansk, men det er såpass enkelt at det ikke er noe problem (Archivo->Exportar->Spr a Bmp). Fikk forøvrig beskjed om at mingwm10.dll manglet, men fant en versjon av denne dll'en og la den inn i program katalogen, så virket det greitt. Lenke til kommentar
trtrtr Skrevet 4. november 2007 Del Skrevet 4. november 2007 Heisann, hadde litt for mye ledig tid og såg litt på .bmp formatet. Modifiserte vedlagte script slik at det nå dumper ut .spr som .BMP. Om du ønsker å konvertere flere .spr filer i en fei, foreslår jeg at du piper dir/ls output til "perl -ne" og således kjører en batch jobb. #!/usr/bin/perl use strict; $| = 1; #file to read SPR format files #read the file name off of the command line my $TargetFile=shift||die "No target SPR file specified.\n"; my @temp=split("\\x5C", $TargetFile); my $TargetFileName=$temp[-1]; #pull off the file name #see if it exists if (!stat($TargetFile)) {die "The SPR file '$TargetFile' does not exist.\n";} #open the input file and and output file open(FHI, "<", $TargetFile) or die "Unable to read from target file '$TargetFile'.\n"; open(OUT, ">", $TargetFileName.".bmp") or die "Unable to create output file.\n"; binmode OUT; my @PaletteArray; my @FrameArray; my %FrameHash; #start reading the data in my $FileHeader=ReadFileBytes(2); my $FileMajorVersion=unpack("C1", ReadFileBytes(1)); my $FileMinorVersion=unpack("C1", ReadFileBytes(1)); my $ImageCount=unpack("C4", ReadFileBytes(4)); print "File ".$TargetFileName."\n"; print "Header ".$FileHeader."\n"; print "Major version ".$FileMajorVersion."\n"; print "Minor version ".$FileMinorVersion."\n"; print "Image count ".$ImageCount." frames\n"; #read the graphic section of the sprite for my $FrameNum (0..$ImageCount-1) { #need to read the size data in backwards #I'm sure there's a better way to do this, but this was faster than looking for the correct method my $HB; my $LB; $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageX=hex(unpack("H4", $HB.$LB)); #88 $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageY=hex(unpack("H4", $HB.$LB)); #86 $LB=ReadFileBytes(1); $HB=ReadFileBytes(1); my $ImageLength=hex(unpack("H4", $HB.$LB)); #7568? my $ImageData=ReadFileBytes($ImageLength); # "--------------------" print "\n"; print "Image #".$FrameNum."\n"; print "Image X ".$ImageX."\n"; print "Image Y ".$ImageY."\n"; print "Data Length ".$ImageLength."\n"; #compression runs from left to right in 2 char pairs #when palette "00" is encountered, next byte is count of pixels to repeat the "00" color unless - # the next byte is also "00", then it is just a simple bit and the next byte is NOT a count #only the background color 00 is ever compressed (and sometimes it is not compressed) #compression can wrap to the next line my @SpriteFramePixelArrary; my $DataIndex=0; my $RawData=""; #walk the length of the array while ($DataIndex<$ImageLength) { my $temp=""; my $BitLength=1; my $Bit=unpack("H2", substr($ImageData, $DataIndex, 1)); #check for the background bit to be set if ($Bit eq "00") { $DataIndex++; $BitLength=hex(unpack("H2", substr($ImageData, $DataIndex, 1))); #is it compressed data? if ($BitLength==0) { #nope, not compressed data, reset the bit length $BitLength=1; $DataIndex--; #Oops, uncompressed data, go backwards 1 byte since we looked ahead } #end uncompressed data chack if } #end background bit check if #now uncompress the data into a temp array for my $subindex (1..$BitLength) { push(@SpriteFramePixelArrary, $Bit); $temp.=$Bit." "; } #print $temp; $RawData.=$Bit." "; $DataIndex++; } #end for #put the data into a hash so we can get at it later $FrameHash{$FrameNum}->{X}=$ImageX; $FrameHash{$FrameNum}->{Y}=$ImageY; @{$FrameHash{$FrameNum}->{DATA}}=@SpriteFramePixelArrary; # } #end frames for #read the pallette info here my $PaletteData=ReadFileBytes(1024); #allways the same size #now make a nice color chart in a 16 x 16 grid #in case you were wondering, the first color in the palette is the transparancy #color for all the frames my $IndexLocation=0; my $IndexNum=0; for my $XIndex (1..16) { for my $YIndex (1..16) { #dig out the color values in 4 byte chunks my $RGBChunk=substr($PaletteData, $IndexLocation, 4); my $Red=uc(unpack("H2", substr($RGBChunk, 0, 1))); my $Green=uc(unpack("H2", substr($RGBChunk, 1, 1))); my $Blue=uc(unpack("H2", substr($RGBChunk, 2, 1))); my $Trans=unpack("H2", substr($RGBChunk, 3, 1)); #we don't care about this value $IndexLocation=$IndexLocation+4; $IndexNum++; push(@PaletteArray, "$Red$Green$Blue"); #add it into an array for later } #end Y for } #end X for # # #Generate BMP header and dump in color table and image data # # #which frame to convert my $frameNr = 0; #image data my @imgData = @{$FrameHash{$frameNr}{DATA}}; #width my $sizeX = $FrameHash{$frameNr}->{X}; #height my $sizeY = $FrameHash{$frameNr}->{Y}; my $rowSize = $sizeX; #Each row of bitmap data contains multiple of 4 bytes. #Find minimum row size. while ($rowSize % 4) { $rowSize++; } #size headers + size color table + size image data my $totalSizeBMPFile = (14 + 40) + (256*4) + ($rowSize*$sizeY); my $offsetToBitData = $totalSizeBMPFile - ($rowSize*$sizeY); print "\ntotalsize:", $totalSizeBMPFile; select OUT; #1.structure BITMAPFILEHEADER #--------------------------- print "BM"; print pack ("I", $totalSizeBMPFile); print pack ("S", 0); print pack ("S", 0); print pack ("I", $offsetToBitData); #2.structure BITMAPINFOHEADER #---------------------------- #size of this struct print pack ("I", 40); #width print pack ("I", $sizeX); #height print pack ("I", $sizeY); #biplanes print pack ("S", 1); #color bits pr pixel. 256 colors => 1 color byte (8bits) pr pixel print pack ("S", 8); #Add some padding to make header 40 bytes print pack ("I6", 0); #3.structure RGBQUAD (color table) #--------------------------------- for my $pal (@PaletteArray) { my @palBytes = ($pal)=~/(..)/g; #Hm, had to experiment bit here to find right order.. #red print pack ("H2", $palBytes[2]); #green print pack ("H2", $palBytes[1]); #blue print pack ("H2", $palBytes[0]); #rgbreserved print pack ("H2",0); } #4.dump out image data. Last row comes first. #--------------------------- my $c = ($sizeX*$sizeY) - $sizeX; for (my $row = 0; $row < $sizeY; $row++) { for (my $col = 0; $col < $sizeX; $col++) { print pack ("H2", $imgData[$c]); $c++; } $c = $c - ($sizeX*2); #Padding for each row for (1..($rowSize - $sizeX)) { print pack ("H2", 0); } } print STDOUT "\nDONE"; # ---------- Subs go here ---------- sub ReadFileBytes { my $BytesToRead=shift||return 0; my $DataRead; sysread(FHI, $DataRead, $BytesToRead); return $DataRead; } __END__ Lenke til kommentar
Milktea Skrevet 23. november 2007 Forfatter Del Skrevet 23. november 2007 Å, takker så mye! Godt en hjelpsom sjel har litt tid til overs. :!: Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå