[Bioperl-l] bioperl graphics

Jonathan Crabtree crabtree at tigr.org
Mon Mar 1 10:02:10 EST 2004

Hi Lincoln-

Thanks for the quick response.  I thought there must have been a good 
reason for using colorAllocate(), but now I'm not sure that this is 
true.  I've been able to generate valid SVG documents using GD::SVG and 
a copy of Bio::Graphics::Panel modified in the way that I described to 
Haibo, so I don't think that my proposed change breaks SVG output 
outright.  I've been using GD-SVG-0.25, which already supports 
colorResolve().  Here are lines 292-297 of SVG.pm:

sub GD::SVG::Image::colorResolve {
  my ($self,$r,$g,$b) = @_;
  ###GD###my $index = $self->{gd}->colorResolve($r,$g,$b);
  my $index = $self->colorAllocate($r,$g,$b);
  return $index;

I haven't looked at any past versions of GD::SVG, however, so perhaps 
this is a recent change.

I do like your suggestion about using multiple GD::Image objects and 
then copying the various Panel GD::Images into a single target 
GD::Image.  However, this approach definitely won't work with GD::SVG, 
which does not yet support any of the GD image copying methods (AFAIK, 
again based on the GD-SVG-0.25 code that I grabbed from CPAN.)  I'm not 
crazy about my current method, which involves manipulating pad_left, 
pad_top, etc., to arrange the various Bio::Graphics::Panels in their 
appropriate locations.  On the other hand, the API for 
Bio::Graphics::Panel does explicitly support the use of an 
externally-supplied GD::Image object when calling gd(), so I don't feel 
as though I'm abusing the module too much.  Using a single GD::Image (or 
SVG::GD::Image) also makes for a (marginally!) faster and more 
space-efficient solution.  Regards,


Lincoln Stein wrote:

>Hash: SHA1
>Sorry, but if you change colorAllocate() to colorResolve(), you will 
>break the ability to generate publication-quality images with 
>GD::SVG.  Perhaps Todd Harris will add colorResolve() to a future 
>version of GD::SVG, in which case I will make the suggested change to 
>I would recommend instead making two Bio::Graphics::Panel objects, and 
>generating a pair of GD objects (using the Panel->gd() method).  Then 
>you can combine them onto a third GD object in whatever geometry you 
>want by using GD->copy()
>On Wednesday 25 February 2004 06:46 pm, Jonathan Crabtree wrote:
>>hz5 at njit.edu wrote:
>>>Is there any way to render 2 Bio::Graphics::Panel into one png
>>>image? because I want 2 different arrows with different labeled
>>>coordinates on the same image and align to the left, but one
>>>Panel can only have one coordinates system.
>>The answer is yes, with a couple of caveats.  The first is that you
>>will have to take care of the layout of the individual
>>Panel-generated images.  If you're left-justifying everything then
>>this should be easy enough.  The second is that I would recommend
>>making a one-line change to Bio/Graphics/Panel.pm, to prevent the
>>package from trying to allocate the same set of colors twice (when
>>you reuse the same GD object to draw the two different parts of the
>>image.)  Search for the following piece of code in Panel.pm (at
>>line 411 in bioperl-1.4, I think):
>>  for my $name ('white','black',keys %COLORS) {
>>    my $idx = $gd->colorAllocate(@{$COLORS{$name}});
>>    $translation_table{$name} = $idx;
>>  }
>>Change "colorAllocate" to "colorResolve"; this should have no
>>effect on any existing Bio::Graphics code (AFAIK) and will allow
>>you to do your two (or three or four)-Panel trick.  (As an aside,
>>I'd like to lobby for this one-line change to be made in a future
>>version of
>>Bio::Graphics::Panel, for precisely this reason.)  In any case,
>>once you've made that change and reinstalled your copy of Bioperl,
>>here is a rough outline of what you need to do:
>>1. Set up your individual Bio::Graphics::Panel objects (e.g. $p1,
>>$p2, $p3, etc.) as desired to draw your images, but do *not* call
>>the gd method on any of them yet.
>>2. Create a GD::Image object big enough to hold the images that
>>will be drawn by $p1, $p2, $p3, etc.:
>>    my $gdImg = GD::Image->new($fullWidth, $fullHeight);
>>(Note: use $p1->width(), $p1->height(), etc., to determine what
>>$fullWidth and $fullHeight should be, based on your desired Panel
>>layout algorithm.)
>>4. Use a "dummy" Bio::Graphics::Panel object to allocate all your
>>colors (this is an optional step; I do this because my code does
>>some drawing that isn't handled by Bio::Graphics::Panel, and want
>>to make sure that the palette has been allocated before I start):
>>    my $dummyPanel = Bio::Graphics::Panel->new(-length => 100,
>>-offset => 0, -width => $fullWidth);
>>    $dummyPanel->gd($gdImg); # forces color allocation
>>5. Draw the individual panels and generate your png image:
>>    $p1->gd($gdImg);
>>    $p2->gd($gdImg);
>>    my $pngData = $gdImg->png();
>>I've glossed over some of the details here, for example the fact
>>that you may need to know the value of $p1->height() before you can
>>initialize $p2, but that's the basic idea.  I've been using this
>>method to generate some comparative sequence displays and while
>>it's definitely a bit of a hack, it works well in practice.  You
>>can also do the same thing with a GD::SVG::Image if you'd like to
>>generate SVG output.  Good luck,
>>Bioperl-l mailing list
>>Bioperl-l at portal.open-bio.org
>- -- 
>Lincoln D. Stein
>Cold Spring Harbor Laboratory
>1 Bungtown Road
>Cold Spring Harbor, NY 11724
>Version: GnuPG v1.2.1 (GNU/Linux)

More information about the Bioperl-l mailing list