188 lines
5.4 KiB
Perl
Executable File
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;
|
|
|