#!/usr/bin/perl # pcg@goof.com # a fairly complete miff save filter use Gimp; use Gimp::Fu; use Gimp::UI; use Fcntl; # Gimp::set_trace(TRACE_ALL); sub write_layer { my($fh,$l)=@_; my($w,$h)=($l->width,$l->height); my $r = new PixelRgn $l,0,0,$w,$h,0,0; print $fh "rows=$h columns=$w\n", "matte=", $r->bpp&1 ? "False" : "True", "\n", ":\012"; # inefficient as hell, but "what shells?" ;*> for my $y (0..$h-1) { print $fh $r->get_rect2(0,$y,$w,1); } } register "file_miff_save", "save images as miff (Magick Interchange File Format)", "Saves images in the miff (Magick Interchange File Format) format used by the ImageMagick package", "Marc Lehmann", "Marc Lehmann ", "1999-10-26", "/MIFF", "RGB, RGBA, GRAY", # weird, but no matte for !DirectColour [], sub { my($img,$drawable,$filename) = @_; my($new_img,$new_drawable); my $export = Gimp::UI::export_image ($new_img=$img, $new_drawable=$drawable, "MIFF", CAN_HANDLE_GRAY|CAN_HANDLE_RGB|CAN_HANDLE_ALPHA|CAN_HANDLE_LAYERS|CAN_HANDLE_LAYERS_AS_ANIMATION); die "export failed" if $export == EXPORT_CANCEL; my @layers = $new_img->get_layers; sysopen FILE,$filename,O_CREAT|O_TRUNC|O_WRONLY or die "Unable to open '$filename' for writing: $!\n"; my $hdr = eval { $img->parasite_find("gimp-comment")->data }; $hdr = " COMMENT: $hdr\n" if $hdr; $hdr = <tile_cache_ntiles($img->width / Gimp->tile_width + 1); init Progress "Saving '$filename' as MIFF..."; my $scene = 0; for (@layers) { print FILE $hdr, "scene=$scene\n", "class=", $_->is_rgb ? "DirectClass" : "PseudoClass", "\n"; #"gamma=", Gimp->gamma, "\n"; # resolution etc.. write_layer(*FILE,$_); $scene++; update Progress $scene/@layers; } close FILE; $new_img->delete if $export == EXPORT_EXPORT; (); }; sub read_layer { my($img)=shift; local $_=shift; my($w,$h,$d)=($_->{columns},$_->{rows},$_->{_bpp}); my $l = new Layer $img, $w, $h, ( $d == 1 ? GRAY_IMAGE : $d == 2 ? GRAYA_IMAGE : $d == 3 ? RGB_IMAGE : $d == 4 ? RGBA_IMAGE : die "Unsupported image depth ($d channels)\n" ), $_->{scene}, 100, NORMAL_MODE; $l->add_layer($_->{scene}); my $r = new PixelRgn $l,0,0,$w,$h,1,0; seek FILE, $_->{_offset}, 0; for my $y (0..$h-1) { read FILE, $_, $w * $d; $r->set_rect2($_,0,$y); } undef $r; $l; } register "file_miff_load", "load miff images (Magick Interchange File Format)", "Loads images that were saved in the miff (Magick Interchange File Format) format used by the ImageMagick package", "Marc Lehmann", "Marc Lehmann ", "1999-09-14", "/MIFF", undef, [], sub { my($filename) = @_; sysopen FILE,$filename,O_RDONLY or die "Unable to open '$filename' for reading: $!\n"; my(@scenes); my $comment; seek FILE, 0, 2; my $filesize = tell FILE; seek FILE, 0, 0; local $/ = "\012"; init Progress "Loading MIFF image from '$filename'..."; do { my %h; header: while () { die "Unexpected end of file while reading from '$filename'\n" if eof; while($_ =~ /\S/) { if (/:\012$/) { last header; } elsif (s/^\s*(\w+)=(\S+|"(?:[^\\"]+|\\"|\\)*")//) { $h{$1}=$2; } elsif (s/\s*\{//) { while(!s/([^}]*)}//) { $comment .= $_; $_ = ; die "Unexpected end of file while reading comment block from '$filename'\n" if eof; } $comment .= $1; } else { die "Unparseable header line ($_) while reading '$filename'\n"; } } } die "No ImageMagick header found in '$filename'\n" unless $h{id} eq "ImageMagick"; $h{_bpp} = ($h{class} =~ /PseudoClass/ ? 1 : 3) + ($h{matte} =~ /True/i ? 1 : 0); $h{_size} = $h{rows} * $h{columns} * $h{_bpp}; $h{_offset} = tell; push @scenes, \%h; seek FILE, $h{_size}, 1; update Progress tell()/$filesize*0.2; } while !eof; my ($w,$h,$d); for (@scenes) { $w = $_->{columns} if $_->{columns} > $w; $h = $_->{rows} if $_->{rows} > $h; $d = $_->{_bpp} if $_->{_bpp} > $d; } my $img = new Image $w, $h, $d >= 3 ? RGB : GRAY; $img->set_filename($filename); $img->undo_disable; if ($comment) { $comment =~ s/^\s+//s; $comment =~ s/\s+$//s; $img->parasite_attach (new Parasite "gimp-comment", PARASITE_PERSISTENT, $comment); } # resolution etc.. Gimp->tile_cache_ntiles($w / Gimp->tile_width + 1); # horrors, reverse, and line-by-line (!!) for (@scenes) { my $layer = read_layer $img,$_; update Progress tell()/$filesize*0.8 + 0.2; } $img->undo_enable; $img; }; Gimp::on_query { Gimp->register_magic_load_handler("file_miff_load", "miff", "", "0,string,id=ImageMagick"); Gimp->register_save_handler("file_miff_save", "miff", ""); }; exit main;