On Wed, 2003-02-26 at 11:25, Scott Smith wrote:
> REALLY? there's a freeware program for generating menus and buttons?
>
> that's what I've been waiting on! I was going to talk to the Kino
> developers about maybe adding support... but it sounds like it already
> exists.
>
> ok Aaron, give us all a HOWTO on generating menus/buttons using
> Gimp... then I'll make sure dvdauthor can use it as input...
Trust me when I tell you *my* Gimp scripts are really low-tech. They all
start with a pre-made background image, I stole all these images from
the ULead Movie Factory program after I figured out that it sucked badly
(looses audio sync in your DVD). The program was awful, but all the menu
backgrounds they provide were pretty cool.
The backgrounds were in JPG format so the first thing my gimp script
does is create a new 720x540 image (the whole thing gets scaled to
720x480 later, 540 is so text looks correct on your TV). Then the gimp
script reads in the stolen ULead background of choice and adds it to the
layer as an image.
The title for the DVD is passed on the command line. This is written
across the top of the DVD menu in bold letters. The font is hardcoded in
the perl script itself, not too creative but can be made configurable of
course. All text written to the DVD menu is autofitted, so it doesn't
matter how long the title is, it will be scaled proportionally to fit.
The actual text for the buttons is taken from the MPG file names I pass
on the command line. My script is hardcoded to allow 14 "buttons" on
each menu, if you pass in 14 MPG files that will be burnt to DVD, it
will create a one page menu. If you pass in 28 files, a 2 page menu will
be made with next and home buttons at the button (the next and home
buttons must be linked manually in DVDSP, thats how I do it). If you
pass in 30 files it will create 2 full page menus and one menu with only
2 items on it. At the bottom will be buttons for next page, prev page
and home (home is page 1 menu). Once again the buttons for switching
menu pages are linked manually in DVDSP.
Also, the next, prev and home buttons were also stolen from ULead.
Now i'll show you a bit of just how low-tech this thing is (I don't
really care since it works for me and creates flawless menus for my DVDs
in seconds).
In my perl script is a hash describing the layout:
1 => {
file => "backgrounds/BG037.jpg",
diskTitle => [70, 40, 590, 70, 60, CENTER,
MIDDLE],
text1 => [70, 100, 590, 22, 24, LEFT, MIDDLE],
text2 => [70, 125, 590, 22, 24, LEFT, MIDDLE],
text3 => [70, 150, 590, 22, 24, LEFT, MIDDLE],
text4 => [70, 175, 590, 22, 24, LEFT, MIDDLE],
text5 => [70, 200, 590, 22, 24, LEFT, MIDDLE],
text6 => [70, 225, 590, 22, 24, LEFT, MIDDLE],
text7 => [70, 250, 590, 22, 24, LEFT, MIDDLE],
text8 => [70, 275, 590, 22, 24, LEFT, MIDDLE],
text9 => [70, 300, 590, 22, 24, LEFT, MIDDLE],
text10 => [70, 325, 590, 22, 24, LEFT, MIDDLE],
text11 => [70, 350, 590, 22, 24, LEFT, MIDDLE],
text12 => [70, 375, 590, 22, 24, LEFT, MIDDLE],
text13 => [70, 400, 590, 22, 24, LEFT, MIDDLE],
text14 => [70, 425, 590, 22, 24, LEFT, MIDDLE],
diskTitleColor => [0, 0, 0],
diskTitleHl => [227, 242, 242],
NRM => [0, 0, 0],
SEL => [0, 0, 0],
ACT => [127, 127, 127]
},
this has number 1. The particular background is hard tied to the hash.
There is a hash for each background I use. They are different because
depening on the background I may put the text in a different place. The
diskTitle through text14 params all contain layout information Gimp uses
when placing the text on the image. Data is
x, y, width, height, target font, hAlign, vAlign
Once again the text is autofitted, so if it's too big using target font
it will be scaled down automatically.
The remaining blocks are color specifications for disk title and normal,
selected and activated conditions for all buttons. I don't need 3
separate color specifiers for each button so they all use the same one.
This would be easy to change.
And now some more code. All text (title, all buttons) is placed on the
menu using a subroutine I created a REALLY long time ago called
placeText(). It is specifically made to fit arbitrary text into an area
of an image. I use it not just for making DVD menus but CD and DVD
labels, Web graphics, printing envelopes or whatever. It looks like
this:
sub placeText {
my ($field) = @_;
my $font =
"-*-avantgarde-demibold-r-*-*-$cardData->{$field}->[4]-*-*-*-*-*-*-*";
if ($rowRef{$field} ne '') { $string = "$rowRef{$field}"; } else {
undef $string; }
$string =~ s/\n\n/\n/g;
$string =~ s/ +/ /g;
my $align = $cardData->{$field}->[5];
my $vAlign = $cardData->{$field}->[6];
if ($field eq 'diskTitle') {
$textColor[0] = $cardData->{'diskTitleColor'}->[0];
$textColor[1] = $cardData->{'diskTitleColor'}->[1];
$textColor[2] = $cardData->{'diskTitleColor'}->[2];
} else {
$textColor[0] = $cardData->{'NRM'}->[0];
$textColor[1] = $cardData->{'NRM'}->[1];
$textColor[2] = $cardData->{'NRM'}->[2];
}
gimp_palette_set_foreground([@textColor]);
my $layer = plug_in_dynamic_text(RUN_NONINTERACTIVE, $img, -1, $string,
1, $align, 0, 5, [@textColor], 5, $font);
my $targetWidth = $cardData->{$field}->[2];
my $targetHeight = $cardData->{$field}->[3];
my $layerHeight = gimp_drawable_height($layer);
my $layerWidth = gimp_drawable_width($layer);
my $factor = $targetWidth/$layerWidth;
my $newHeight;
if ($layerWidth > $targetWidth) {
$newHeight = int($factor * $layerHeight);
gimp_layer_scale($layer, $targetWidth, $newHeight, 1);
}
$layerWidth = gimp_drawable_width($layer);
$layerHeight = gimp_drawable_height($layer);
$factor = $targetHeight/$layerHeight;
my $newWidth;
if ($layerHeight > $targetHeight) {
$newWidth = int($factor * $layerWidth);
gimp_layer_scale($layer, $newWidth, $targetHeight, 1);
}
my $scaledHeight = gimp_drawable_height($layer);
my $scaledWidth = gimp_drawable_width($layer);
my $x2 = $cardData->{"$field"}->[0] + $cardData->{$field}->[2];
my $x1;
if ($align == LEFT) {
$x1 = $cardData->{$field}->[0];
} elsif ($align == RIGHT) {
$x1 = $x2 - $scaledWidth;
} elsif ($align == CENTER) {
my $center = $scaledWidth / 2;
my $half = ($cardData->{"$field"}->[2] / 2) - $scaledWidth;
$x1 = $cardData->{"$field"}->[0] + $center + $half;
}
# Adjust vertical alignment
my $y2 = $cardData->{"$field"}->[1] + $cardData->{$field}->[3];
my $y1;
if ($vAlign == TOP) {
$y1 = $cardData->{$field}->[1];
} elsif ($vAlign == BOTTOM) {
$y1 = $y2 - $scaledHeight;
} elsif ($vAlign == MIDDLE) {
my $center = $scaledHeight / 2;
my $half = ($cardData->{"$field"}->[3] / 2) - $scaledHeight;
$y1 = $cardData->{"$field"}->[1] + $center + $half;
}
gimp_layer_set_offsets( $layer, $x1, $y1);
gimp_selection_none($img);
return;
}
Near the end of the whole thing, the image gets flattened and scaled to
720x480 and saved as TIFF. Photoshop converts it to PSD for me.
And that's how text gets placed on my DVD menus. Of course my menus look
very plain since each "button" is simply plain text on a fancy
background, with a pink overlay when the button is active. With gimp you
can make the buttons as fancy as you want though. You can have fancy
text effects like drop shadows and gradients, your "buttons" can be
raised with bevel effects or sunken or composites of other images or
whatever you feel like programming.
Also, the entire script is probably of use to only me, which is why I
didn't send the whole thing. To be really useful it would probably
benefit from a better format of describing the DVD menu, maybe an XML
file or maybe a whole bunch of command line options. Right now it's
useful for creating Aaron Newsome menu files to use in DVDSP (although
soon to be for dvdauthor too).
I've written a lot, can't really remember what I wrote. Rather than read
again I'll send it and wait for questions.
Oh one more thing, as for me helping with adding sophisticated menu
support to DVD author, I'd be glad to help wherever I can. although as
you can see from my code above I'm not much of a programmer. But I just
might be the resident expert in creating fully automated Gimp scripts,
as I have dozens of them for various purposes.
--Aaron
|