Files
gimp/plug-ins/perl/examples/miff
1999-10-27 20:13:42 +00:00

188 lines
5.4 KiB
Perl
Executable File

#!/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 <pcg\@goof.com>",
"1999-10-26",
"<Save>/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 = <<EOF;
id=ImageMagick
{
CREATOR: file_miff_save gimp plug-in, see http://www.gimp.org/
$hdr}
EOF
Gimp->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 <pcg\@goof.com>",
"1999-09-14",
"<Load>/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 (<FILE>) {
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 .= $_;
$_ = <FILE>;
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;