Opened 21 years ago

Closed 21 years ago

#267 closed defect (fixed)

Lines of SIZE > 1 not displayed with 24-bit output (nor with 8-bit with layer transparency set)

Reported by: keon@… Owned by: warmerdam
Priority: high Milestone:
Component: GDAL Support Version: 4.0
Severity: normal Keywords:
Cc:

Description

When using 24-bit output, lines with thickness > 1 are not displayed.  This also
happens with 8-bit output if TRANSPARENCY is set for any of the layers.  By
"thickness" I mean using the circle symbol and giving it a size value (see roads
layer definition below).  Any SIZE definition > 1 will result in that class not 
being displayed.  In the example below, the "Paved" class is not displayed.  It
*is* displayed if I change SIZE from 2 to 1.

Figured I should submit this as a new bug since the description of the problem
is buried within bug 231.

LAYER
  NAME roads
  GROUP "BASE DATA"
  TYPE LINE
  STATUS DEFAULT
  DATA road83
  CLASSITEM "LEGEND"
  CLASS
    NAME "Paved"
    EXPRESSION /Paved/ #contains "Paved"
    COLOR 0 0 0
    SYMBOL 'circle'
    SIZE 2
  END
  CLASS
    NAME "Gravel"
    EXPRESSION /Gravel/ #contains "Gravel"
    COLOR 100 100 100
    SYMBOL 'circle'
    SIZE 1
  END
  CLASS
    NAME "Closed"
    EXPRESSION /Closed/ #contains "Closed"
    COLOR 190 190 190
    SYMBOL 'circle'
    SIZE 1
  END
END

LAYER
  NAME ONP_boundary
  TYPE POLYGON
  STATUS DEFAULT
  DATA onp_bnd_83
  TRANSPARENCY 60  #if set, lines of SIZE > 1 not displayed
  CLASS 
    NAME "ONP boundary"
    OUTLINECOLOR 0 0 0
    COLOR 243 248 245
  END
END

Change History (7)

comment:1 by fwarmerdam, 21 years ago

Status: newassigned
I haven't been able to reproduce this exactly as stated, but I do see a problem
of the background being drawn in black/transparent when drawing symbols in 24bit.
This results in badly messed up drawing of SIZE>1 circles for instance.  

I will fix this, and then bounce things back Dylan to try and reproduce his
bug.  They may be related.

comment:2 by fwarmerdam, 21 years ago

OK, I have looked into the problem and found a few things.

First, please use at least GD 2.0.11, old versions of GD 2.0.x have 
significant bugs some of which are fixed in 2.0.11. 

Second, the gdImageBrushApply() function has a bug laying 8bit 
brushes on true color images ... in particular, the transparent values
are generally not recognised properly.

While I have emailed Thomas Boutell about this, I don't know if or when a fix
will make it into GD.  In the meantime, I have tested a change to 
msDrawLineSymbolGD() to create 24bit brushes instead of 8bit brushes.  It 
looks like this and does solve the problem. 


    if((brush = searchImageCache(symbolset->imagecache, style->symbol, fc,
size)) == NULL) { // not in cache, create
      if( !gdImageTrueColor(img) )
      {
          brush = gdImageCreate(x, y);
          brush_bc = gdImageColorAllocate(brush,gdImageRed(img,0),
gdImageGreen(img, 0), gdImageBlue(img, 0));    
          
          gdImageColorTransparent(brush,0);
          brush_fc = gdImageColorAllocate(brush, style->color.red, 
                                        style->color.green, style->color.blue);
      }
#if GD2_VERS > 1
      else
      {
          brush = gdImageCreateTrueColor(x,y);
          gdImageAlphaBlending( brush, 0 );
          gdImageFilledRectangle( brush, 0, 0, x, y, -1 );
          brush_bc = -1;
          brush_fc = gdTrueColor( style->color.red, style->color.green, 
                                  style->color.blue );
      }
#endif

I have not yet committed this change mainly because it seems there are 
roughly 10 other places in mapgd.c where similar sorts of changes might be
required.  The question then is, should I go ahead and try to make these 
changes everywhere?   It will be pretty hard for me to test!
It is possible that only the brushes will require the fix ... not too sure,
in which case it might only be five or six places to fix. 

PS.  Whatever the solution, I would like to add more tests to the msautotest
for these cases when we are finished.

comment:3 by keon@…, 21 years ago

I was using GD 2.0.9.  Apparently my line thickness problem was related to the
recent fixes that went into GD, because upgrading to 2.0.11 solved the problem.

Thanks.

comment:4 by sdlime, 21 years ago

This is a killer for both GD and us. Can't release 3.7 with the issue seeing as
24-bit output is of great interest. Aside from the pain in the ass factor, I'm
wondering if there might be some other benefits to explicitly creating a brush
in the matching color depth. Might there be a performance gain in not having the
GD code have to do color lookups? What about a brush creation function? Just
pass a size, a color depth and a color to make transparent and return a
gdImagePtr. At least the code would remain semi-readable and might make moving
to something other than GD easier in the future. I assume populating the brush
would be unchanged then. We might also need to convert PIXMAP symbols to the
appropriate color depth for line and polygon rendering.

I like the thought of a createBrush(...) function. What do you guys think?

comment:5 by sdlime, 21 years ago

I've got a potential brush function. I've tested with polygon fills, both with
ellipse and vector symbols, and with/without a background color and it seems to
work fine. It's based on Frank's code looks like:

static gdImagePtr createBrush(gdImagePtr img, int width, int height, styleObj
*style, int *fgcolor, int *bgcolor)
{
  gdImagePtr brush;

#if GD2_VERS > 1
  if(!gdImageTrueColor(img)) {
    brush = gdImageCreate(width, height);
    if(style->backgroundcolor.pen >= 0)
      *bgcolor = gdImageColorAllocate(brush, style->backgroundcolor.red,
style->backgroundcolor.green, style->backgroundcolor.blue);
    else {
      *bgcolor = gdImageColorAllocate(brush, gdImageRed(img,0),
gdImageGreen(img, 0), gdImageBlue(img, 0));          
      gdImageColorTransparent(brush,0);
    }
    *fgcolor = gdImageColorAllocate(brush, style->color.red, style->color.green,
style->color.blue);
  } else {
    brush = gdImageCreateTrueColor(width, height);
    gdImageAlphaBlending(brush, 0);
    if(style->backgroundcolor.pen >= 0)
      *bgcolor = gdTrueColor(style->backgroundcolor.red,
style->backgroundcolor.green, style->backgroundcolor.blue);      
    else
      *bgcolor = -1;      
    gdImageFilledRectangle(brush, 0, 0, width, height, *bgcolor);
    *fgcolor = gdTrueColor(style->color.red, style->color.green, style->color.blue);
  }
#else
  brush = gdImageCreate(width, height);
  if(style->backgroundcolor.pen >= 0)
    *bgcolor = gdImageColorAllocate(brush, style->backgroundcolor.red,
style->backgroundcolor.green, style->backgroundcolor.blue);
  else {
    *bgcolor = gdImageColorAllocate(brush, gdImageRed(img,0), gdImageGreen(img,
0), gdImageBlue(img, 0));          
    gdImageColorTransparent(brush,0);
  }
  *fgcolor = gdImageColorAllocate(brush, style->color.red, style->color.green,
style->color.blue);
#endif

  return(brush);
}

I'll continue testing with lines and if all is well will commit if everyone is
cool with the change. Please let me know.

comment:6 by fwarmerdam, 21 years ago

Steve, 

This looks cool to me. 

comment:7 by sdlime, 21 years ago

Resolution: fixed
Status: assignedclosed
I committed the changes to mapgd.c so that all brushing and tiling uses the
createBrush function. That means the circle (shade/line), and shape (shade/line)
functions *should* work fine now. Marking as fixed for the moment...

Note I didn't change anything with markers. Sounded as if Boutell's changes for
GD 2.0.10 fixed image copying.

Steve
Note: See TracTickets for help on using tickets.