#!perl -w # (C) 2003-2007 Willem Jan Hengeveld # Web: http://www.xs4all.nl/~itsme/ # http://wiki.xda-developers.com/ # # $Id: imagedmp.pl 1502 2007-04-15 07:54:20Z itsme $ # use strict; $|=1; use IO::File; use Getopt::Long; my $fn = shift; my $fh= IO::File->new($fn, "r") or die "$fn: $!"; binmode $fh; my $data; $fh->read($data, -s $fh); if ($data =~ /^BM/) { BMP::decode($data, 0); } elsif ($data =~ /^GIF/) { GIF::decode($data, 0); } elsif ($data =~ /^\xff\xd8/) { JPG::decode($data, 0); } elsif ($data =~ /^\x00\x00\x01\x00.\x00...\x00.\x00.\x00/) { ICO::decode($data, 0); } else { printf("unknown image: hdr: %s\n", unpack("H32", $data)); } sub decodestruct { my $ofs= $_[1]; my %struct; my @struct_fields= @{$_[4]}; my @struct_format= @{$_[5]}; if (0) { # for debugging formats die sprintf("fields=%d fmt=%d %s\n", scalar @struct_fields, scalar @struct_format, join(",", @struct_fields)) if (@struct_fields != @struct_format); die sprintf("fmt size=%d len=%d: %s\n", length(pack($_[3], 0..100)), $_[2], $_[3]) if (length(pack($_[3], 0..100)) != $_[2]); die sprintf("fmt fields=%d str=%d: %s\n", scalar unpack($_[3], "\x00" x $_[2]), scalar @struct_fields, $_[3]) if (scalar @{[unpack($_[3], "\x00" x $_[2])]} != @struct_fields); } my @struct_values= unpack($_[3], substr($_[0], $ofs, $_[2])); $struct{$struct_fields[$_]}=$struct_values[$_] for (0..$#struct_fields); printf("%-20s: $struct_format[$_]\n", $struct_fields[$_], $struct_values[$_]) for (0..$#struct_fields); return \%struct; } ################################################################################### package BMPInfo; sub decode { return main::decodestruct($_[0], $_[1], 40, "VVVvvVVVVVV", [qw(biSize biWidth biHeight biPlanes biBitCount biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant)], [qw(%08x %08x %08x %04x %04x %08x %08x %08x %08x %08x %08x)]); } package BMPHdr; sub decode { return main::decodestruct($_[0], $_[1], 14, "vVvvV", [qw(bfType bfSize bfReserved1 bfReserved2 bfOffBits)], [qw(%04x %08x %04x %04x %08x)]); } package BMP; sub decode { my $ofs= $_[1]; my $hdr= BMPHdr::decode($_[0], $ofs); my $info= BMPInfo::decode($_[0], $ofs+14); return { hdr=>$hdr, info=>$info }; } ################################################################################### package ICOHdr; sub decode { return main::decodestruct($_[0], $_[1], 6, "vvv", [qw(idReserved idType idCount)], [qw(%04x %04x %04x)]); } package ICOEntry; sub decode { return main::decodestruct($_[0], $_[1], 16, "CCCCvvVV", [qw(bWidth bHeight bColorCount bReserved wPlanes wBitCount dwBytesInRes dwImageOffset)], [qw(%02x %02x %02x %02x %04x %04x %08x %08x)]); } package ICO; sub decode { my $hdr= ICOHdr::decode($_[0], $_[1]); my @entries= map { ICOEntry::decode($_[0], 6+16*$_) } (0..$hdr->{idCount}-1); my @icons= map { BMPInfo::decode($_[0], $entries[$_]{dwImageOffset}) } (0..$hdr->{idCount}-1); return { hdr=>$hdr, entries=>\@entries, icons=>\@icons }; } ################################################################################### package GIFHdr; sub decode { my $hdr= main::decodestruct($_[0], $_[1], 13, "a3a3vvCCC", [qw(signature version width height packed backgroundColor aspectRatio)], [qw(%s %s %04x %04x %02x %02x %02x)]); $hdr->{colortableEntrySize}= $hdr->{packed}&0x7; $hdr->{colortableSortFlag}= ($hdr->{packed}&0x8)>>3; $hdr->{colortableResolution}= ($hdr->{packed}&0x70)>>4; $hdr->{colortableFlag}= ($hdr->{packed}&0x80)>>7; return $hdr; } package GIF; sub decode { my $hdr= GIFHdr::decode($_[0], $_[1]); return { hdr=>$hdr }; }