~ubuntu-branches/ubuntu/saucy/mapserver/saucy-security

« back to all changes in this revision

Viewing changes to mapdrawgdal.c

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2011-12-23 14:02:06 UTC
  • mfrom: (26.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20111223140206-n3h9t2hsa8hyslmu
Tags: 6.0.1-2
Added missed stuff for libmapscript-perl.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: mapdrawgdal.c 10012 2010-03-25 14:42:48Z warmerdam $
 
2
 * $Id: mapdrawgdal.c 11176 2011-03-16 19:01:00Z schpidi $
3
3
 *
4
4
 * Project:  MapServer
5
5
 * Purpose:  Code for drawing GDAL raster layers.  Called from 
33
33
#include "mapresample.h"
34
34
#include "mapthread.h"
35
35
 
36
 
MS_CVSID("$Id: mapdrawgdal.c 10012 2010-03-25 14:42:48Z warmerdam $")
 
36
MS_CVSID("$Id: mapdrawgdal.c 11176 2011-03-16 19:01:00Z schpidi $")
37
37
 
38
38
extern int InvGeoTransform( double *gt_in, double *gt_out );
39
39
 
58
58
                layerObj *layer, 
59
59
                int src_xoff, int src_yoff, int src_xsize, int src_ysize, 
60
60
                GByte *pabyBuffer,
61
 
                int dst_xsize, int dst_ysize );
 
61
                int dst_xsize, int dst_ysize,
 
62
                int *pbHaveRGBNoData, 
 
63
                int *pnNoData1, int *pnNoData2, int *pnNoData3 );
62
64
static int 
63
65
msDrawRasterLayerGDAL_RawMode(
64
66
    mapObj *map, layerObj *layer, imageObj *image, GDALDatasetH hDS, 
67
69
 
68
70
static int 
69
71
msDrawRasterLayerGDAL_16BitClassification(
70
 
    mapObj *map, layerObj *layer, imageObj *image, 
 
72
    mapObj *map, layerObj *layer, rasterBufferObj *rb,
71
73
    GDALDatasetH hDS, GDALRasterBandH hBand,
72
74
    int src_xoff, int src_yoff, int src_xsize, int src_ysize,
73
75
    int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize );
99
101
#define RGB_LEVEL_INDEX(r,g,b) ((r)*GREEN_LEVELS*BLUE_LEVELS + (g)*BLUE_LEVELS+(b))
100
102
#define RGB_INDEX(r,g,b) RGB_LEVEL_INDEX(((r)/RED_DIV),((g)/GREEN_DIV),((b)/BLUE_DIV))
101
103
 
 
104
/*
 
105
 * rasterBufferObj setting macros. 
 
106
 */
 
107
 
 
108
 
 
109
 
102
110
/************************************************************************/
103
111
/*                       msDrawRasterLayerGDAL()                        */
104
112
/************************************************************************/
105
113
 
106
114
int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, 
107
 
                          void *hDSVoid )
 
115
                          rasterBufferObj *rb, void *hDSVoid )
108
116
 
109
117
{
110
 
  int i,j, k; /* loop counters */
111
 
  int cmap[MAXCOLORS], cmap_set = FALSE;
112
 
  double adfGeoTransform[6], adfInvGeoTransform[6];
113
 
  int   dst_xoff, dst_yoff, dst_xsize, dst_ysize;
114
 
  int   src_xoff, src_yoff, src_xsize, src_ysize;
115
 
  int   anColorCube[256];
116
 
  double llx, lly, urx, ury;
117
 
  rectObj copyRect, mapRect;
118
 
  unsigned char *pabyRaw1=NULL, *pabyRaw2=NULL, *pabyRaw3=NULL, 
119
 
                *pabyRawAlpha = NULL;
120
 
  int truecolor = FALSE, classified = FALSE;
121
 
  int red_band=0, green_band=0, blue_band=0, alpha_band=0, cmt=0;
122
 
  int band_count, band_numbers[4];
123
 
  gdImagePtr gdImg = NULL;
124
 
  GDALDatasetH hDS = hDSVoid;
125
 
  GDALColorTableH hColorMap;
126
 
  GDALRasterBandH hBand1=NULL, hBand2=NULL, hBand3=NULL, hBandAlpha=NULL;
127
 
  memset( cmap, 0xff, MAXCOLORS * sizeof(int) );
 
118
    int i,j, k; /* loop counters */
 
119
    int cmap[MAXCOLORS], cmap_set = FALSE;
 
120
    unsigned char rb_cmap[4][MAXCOLORS];
 
121
    double adfGeoTransform[6], adfInvGeoTransform[6];
 
122
    int dst_xoff, dst_yoff, dst_xsize, dst_ysize;
 
123
    int src_xoff, src_yoff, src_xsize, src_ysize;
 
124
    int   anColorCube[256];
 
125
    double llx, lly, urx, ury;
 
126
    rectObj copyRect, mapRect;
 
127
    unsigned char *pabyRaw1=NULL, *pabyRaw2=NULL, *pabyRaw3=NULL, 
 
128
        *pabyRawAlpha = NULL;
 
129
    int classified = FALSE;
 
130
    int red_band=0, green_band=0, blue_band=0, alpha_band=0, cmt=0;
 
131
    int band_count, band_numbers[4];
 
132
    GDALDatasetH hDS = hDSVoid;
 
133
    GDALColorTableH hColorMap;
 
134
    GDALRasterBandH hBand1=NULL, hBand2=NULL, hBand3=NULL, hBandAlpha=NULL;
 
135
    int bHaveRGBNoData = FALSE;
 
136
    int nNoData1=-1,nNoData2=-1,nNoData3=-1;
 
137
    
 
138
    /*only support rawdata and pluggable renderers*/
 
139
    assert(MS_RENDERER_RAWDATA(image->format) || (MS_RENDERER_PLUGIN(image->format) && rb));
 
140
    
 
141
    /*make sure we don't have a truecolor gd image*/
 
142
    assert(!rb || rb->type != MS_BUFFER_GD || !gdImageTrueColor(rb->data.gd_img));
 
143
 
 
144
    memset( cmap, 0xff, MAXCOLORS * sizeof(int) );
 
145
    memset( rb_cmap, 0, sizeof(rb_cmap) );
128
146
 
129
147
/* -------------------------------------------------------------------- */
130
148
/*      Test the image format instead of the map format.                */
134
152
/*      and then dumped into the SWF or the PDF file.                   */
135
153
/* -------------------------------------------------------------------- */
136
154
  
137
 
  /* if( MS_RENDERER_GD(map->outputformat) ) */
138
 
  if( MS_RENDERER_GD(image->format) )
139
 
  {
140
 
      gdImg = image->img.gd;
141
 
 
142
 
      truecolor = gdImageTrueColor( gdImg );
143
 
      if( CSLFetchNameValue( layer->processing, 
144
 
                             "COLOR_MATCH_THRESHOLD" ) != NULL )
145
 
      {
146
 
          cmt = MAX(0,atoi(CSLFetchNameValue( layer->processing, 
147
 
                                              "COLOR_MATCH_THRESHOLD" )));
148
 
      }
149
 
  }
150
 
#ifdef USE_AGG
151
 
  else if( MS_RENDERER_AGG(image->format) )
152
 
  {
153
 
      gdImg = image->img.gd;
154
 
 
155
 
      truecolor = gdImageTrueColor( gdImg );
156
 
      if( CSLFetchNameValue( layer->processing, 
157
 
                             "COLOR_MATCH_THRESHOLD" ) != NULL )
158
 
      {
159
 
          cmt = MAX(0,atoi(CSLFetchNameValue( layer->processing, 
160
 
                                              "COLOR_MATCH_THRESHOLD" )));
161
 
      }
162
 
  }
163
 
#endif
164
 
  src_xsize = GDALGetRasterXSize( hDS );
165
 
  src_ysize = GDALGetRasterYSize( hDS );
166
 
 
167
 
  /*
168
 
   * If the RAW_WINDOW attribute is set, use that to establish what to
169
 
   * load.  This is normally just set by the mapresample.c module to avoid
170
 
   * problems with rotated maps.
171
 
   */
172
 
 
173
 
  if( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) != NULL )
174
 
  {
175
 
      char **papszTokens = 
176
 
          CSLTokenizeString( 
177
 
              CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) );
178
 
      
179
 
      if( layer->debug )
180
 
          msDebug( "msDrawGDAL(%s): using RAW_WINDOW=%s, dst=0,0,%d,%d\n",
181
 
                   layer->name,
182
 
                   CSLFetchNameValue( layer->processing, "RAW_WINDOW" ),
183
 
                   image->width, image->height );
184
 
 
185
 
      if( CSLCount(papszTokens) != 4 )
186
 
      {
187
 
          CSLDestroy( papszTokens );
188
 
          msSetError( MS_IMGERR, "RAW_WINDOW PROCESSING directive corrupt.",
189
 
                      "msDrawGDAL()" );
190
 
          return -1;
191
 
      }
192
 
 
193
 
      src_xoff = atoi(papszTokens[0]);
194
 
      src_yoff = atoi(papszTokens[1]);
195
 
      src_xsize = atoi(papszTokens[2]);
196
 
      src_ysize = atoi(papszTokens[3]);
197
 
 
198
 
      dst_xoff = 0;
199
 
      dst_yoff = 0;
200
 
      dst_xsize = image->width;
201
 
      dst_ysize = image->height;
202
 
 
203
 
      CSLDestroy( papszTokens );
204
 
  }
205
 
 
206
 
  /*
207
 
   * Compute the georeferenced window of overlap, and do nothing if there
208
 
   * is no overlap between the map extents, and the file we are operating on.
209
 
   */
210
 
  else if( layer->transform )
211
 
  {
212
 
      int dst_lrx, dst_lry;
213
 
 
214
 
      msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform );
215
 
      InvGeoTransform( adfGeoTransform, adfInvGeoTransform );
216
 
      
217
 
      mapRect = map->extent;
218
 
      
219
 
      mapRect.minx -= map->cellsize*0.5;
220
 
      mapRect.maxx += map->cellsize*0.5;
221
 
      mapRect.miny -= map->cellsize*0.5;
222
 
      mapRect.maxy += map->cellsize*0.5;
223
 
      
224
 
      copyRect = mapRect;
225
 
      
226
 
      if( copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize) )
227
 
          copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize);
228
 
      if( copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0) )
229
 
          copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0);
230
 
 
231
 
      if( copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize) )
232
 
          copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize);
233
 
      if( copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0) )
234
 
          copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0);
235
 
      
236
 
      if( copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy )
237
 
          return 0;
238
 
 
239
 
      /*
240
 
       * Copy the source and destination raster coordinates.
241
 
       */
242
 
      llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny);
243
 
      lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny);
244
 
      urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy);
245
 
      ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy);
246
 
      
247
 
      src_xoff = MAX(0,(int) floor(llx+0.5));
248
 
      src_yoff = MAX(0,(int) floor(ury+0.5));
249
 
      src_xsize = MIN(MAX(0,(int) (urx - llx + 0.5)),
250
 
                      GDALGetRasterXSize(hDS) - src_xoff);
251
 
      src_ysize = MIN(MAX(0,(int) (lly - ury + 0.5)),
252
 
                      GDALGetRasterYSize(hDS) - src_yoff);
253
 
 
254
 
      if( src_xsize == 0 || src_ysize == 0 )
255
 
      {
256
 
          if( layer->debug )
257
 
              msDebug( "msDrawGDAL(): no apparent overlap between map view and this window(1).\n" );
258
 
          return 0;
259
 
      }
260
 
 
261
 
      dst_xoff = (int) ((copyRect.minx - mapRect.minx) / map->cellsize);
262
 
      dst_yoff = (int) ((mapRect.maxy - copyRect.maxy) / map->cellsize);
263
 
 
264
 
      dst_lrx = (int) ((copyRect.maxx - mapRect.minx) / map->cellsize + 0.5);
265
 
      dst_lry = (int) ((mapRect.maxy - copyRect.miny) / map->cellsize + 0.5);
266
 
      dst_lrx = MAX(0,MIN(image->width,dst_lrx));
267
 
      dst_lry = MAX(0,MIN(image->height,dst_lry));
268
 
      
269
 
      dst_xsize = MAX(0,MIN(image->width,dst_lrx - dst_xoff));
270
 
      dst_ysize = MAX(0,MIN(image->height,dst_lry - dst_yoff));
271
 
 
272
 
      if( dst_xsize == 0 || dst_ysize == 0 )
273
 
      {
274
 
          if( layer->debug )
275
 
              msDebug( "msDrawGDAL(): no apparent overlap between map view and this window(2).\n" );
276
 
          return 0;
277
 
      }
278
 
 
279
 
      if( layer->debug )
280
 
          msDebug( "msDrawGDAL(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", 
281
 
                   src_xoff, src_yoff, src_xsize, src_ysize, 
282
 
                   dst_xoff, dst_yoff, dst_xsize, dst_ysize );
 
155
 
 
156
    src_xsize = GDALGetRasterXSize( hDS );
 
157
    src_ysize = GDALGetRasterYSize( hDS );
 
158
 
 
159
    /*
 
160
     * If the RAW_WINDOW attribute is set, use that to establish what to
 
161
     * load.  This is normally just set by the mapresample.c module to avoid
 
162
     * problems with rotated maps.
 
163
     */
 
164
 
 
165
    if( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) != NULL )
 
166
    {
 
167
        char **papszTokens = 
 
168
            CSLTokenizeString( 
 
169
                CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) );
 
170
      
 
171
        if( layer->debug )
 
172
            msDebug( "msDrawGDAL(%s): using RAW_WINDOW=%s, dst=0,0,%d,%d\n",
 
173
                     layer->name,
 
174
                     CSLFetchNameValue( layer->processing, "RAW_WINDOW" ),
 
175
                     image->width, image->height );
 
176
 
 
177
        if( CSLCount(papszTokens) != 4 )
 
178
        {
 
179
            CSLDestroy( papszTokens );
 
180
            msSetError( MS_IMGERR, "RAW_WINDOW PROCESSING directive corrupt.",
 
181
                        "msDrawGDAL()" );
 
182
            return -1;
 
183
        }
 
184
 
 
185
        src_xoff = atoi(papszTokens[0]);
 
186
        src_yoff = atoi(papszTokens[1]);
 
187
        src_xsize = atoi(papszTokens[2]);
 
188
        src_ysize = atoi(papszTokens[3]);
 
189
 
 
190
        dst_xoff = 0;
 
191
        dst_yoff = 0;
 
192
        dst_xsize = image->width;
 
193
        dst_ysize = image->height;
 
194
 
 
195
        CSLDestroy( papszTokens );
 
196
    }
 
197
 
 
198
    /*
 
199
     * Compute the georeferenced window of overlap, and do nothing if there
 
200
     * is no overlap between the map extents, and the file we are operating on.
 
201
     */
 
202
    else if( layer->transform )
 
203
    {
 
204
        int dst_lrx, dst_lry;
 
205
        
 
206
        if( layer->debug )
 
207
            msDebug( "msDrawRasterLayerGDAL(): Entering transform.\n" );
 
208
 
 
209
        msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform );
 
210
        InvGeoTransform( adfGeoTransform, adfInvGeoTransform );
 
211
      
 
212
        mapRect = map->extent;
 
213
      
 
214
        mapRect.minx -= map->cellsize*0.5;
 
215
        mapRect.maxx += map->cellsize*0.5;
 
216
        mapRect.miny -= map->cellsize*0.5;
 
217
        mapRect.maxy += map->cellsize*0.5;
 
218
      
 
219
        copyRect = mapRect;
 
220
      
 
221
        if( copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize) )
 
222
            copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize);
 
223
        if( copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0) )
 
224
            copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0);
 
225
 
 
226
        if( copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize) )
 
227
            copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize);
 
228
        if( copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0) )
 
229
            copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0);
 
230
      
 
231
        if( copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy )
 
232
        {
 
233
            if( layer->debug )
 
234
                msDebug( "msDrawRasterLayerGDAL(): Error in overlap calculation.\n" );
 
235
            return 0;
 
236
        }
 
237
 
 
238
        /*
 
239
         * Copy the source and destination raster coordinates.
 
240
         */
 
241
        llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny);
 
242
        lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny);
 
243
        urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy);
 
244
        ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy);
 
245
      
 
246
        src_xoff = MAX(0,(int) floor(llx+0.5));
 
247
        src_yoff = MAX(0,(int) floor(ury+0.5));
 
248
        src_xsize = MIN(MAX(0,(int) (urx - llx + 0.5)),
 
249
                        GDALGetRasterXSize(hDS) - src_xoff);
 
250
        src_ysize = MIN(MAX(0,(int) (lly - ury + 0.5)),
 
251
                        GDALGetRasterYSize(hDS) - src_yoff);
 
252
 
 
253
        if( src_xsize == 0 || src_ysize == 0 )
 
254
        {
 
255
            if( layer->debug )
 
256
                msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(1).\n" );
 
257
            return 0;
 
258
        }
 
259
 
 
260
        if (map->cellsize == 0)
 
261
        {
 
262
            if( layer->debug )
 
263
                msDebug( "msDrawRasterLayerGDAL(): Cellsize can't be 0.\n" );
 
264
            return 0;
 
265
        }
 
266
 
 
267
        dst_xoff = (int) ((copyRect.minx - mapRect.minx) / map->cellsize);
 
268
        dst_yoff = (int) ((mapRect.maxy - copyRect.maxy) / map->cellsize);
 
269
 
 
270
        dst_lrx = (int) ((copyRect.maxx - mapRect.minx) / map->cellsize + 0.5);
 
271
        dst_lry = (int) ((mapRect.maxy - copyRect.miny) / map->cellsize + 0.5);
 
272
        dst_lrx = MAX(0,MIN(image->width,dst_lrx));
 
273
        dst_lry = MAX(0,MIN(image->height,dst_lry));
 
274
      
 
275
        dst_xsize = MAX(0,MIN(image->width,dst_lrx - dst_xoff));
 
276
        dst_ysize = MAX(0,MIN(image->height,dst_lry - dst_yoff));
 
277
 
 
278
        if( dst_xsize == 0 || dst_ysize == 0 )
 
279
        {
 
280
            if( layer->debug )
 
281
                msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(2).\n" );
 
282
            return 0;
 
283
        }
 
284
 
 
285
        if( layer->debug )
 
286
            msDebug( "msDrawRasterLayerGDAL(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", 
 
287
                     src_xoff, src_yoff, src_xsize, src_ysize, 
 
288
                     dst_xoff, dst_yoff, dst_xsize, dst_ysize );
283
289
#ifndef notdef
284
 
      if( layer->debug )
285
 
      {
286
 
          double d_src_xoff, d_src_yoff, geo_x, geo_y;
287
 
 
288
 
          geo_x = mapRect.minx + dst_xoff * map->cellsize;
289
 
          geo_y = mapRect.maxy - dst_yoff * map->cellsize;
290
 
 
291
 
          d_src_xoff = (geo_x - adfGeoTransform[0]) / adfGeoTransform[1];
292
 
          d_src_yoff = (geo_y - adfGeoTransform[3]) / adfGeoTransform[5];
 
290
        if( layer->debug )
 
291
        {
 
292
            double d_src_xoff, d_src_yoff, geo_x, geo_y;
 
293
 
 
294
            geo_x = mapRect.minx + dst_xoff * map->cellsize;
 
295
            geo_y = mapRect.maxy - dst_yoff * map->cellsize;
 
296
 
 
297
            d_src_xoff = (geo_x - adfGeoTransform[0]) / adfGeoTransform[1];
 
298
            d_src_yoff = (geo_y - adfGeoTransform[3]) / adfGeoTransform[5];
293
299
          
294
 
          msDebug( "source raster PL (%.3f,%.3f) for dst PL (%d,%d).\n",
295
 
                   d_src_xoff, d_src_yoff,
296
 
                   dst_xoff, dst_yoff );
297
 
      }
 
300
            msDebug( "msDrawRasterLayerGDAL(): source raster PL (%.3f,%.3f) for dst PL (%d,%d).\n",
 
301
                     d_src_xoff, d_src_yoff,
 
302
                     dst_xoff, dst_yoff );
 
303
        }
298
304
#endif
299
 
  }
300
 
 
301
 
  /*
302
 
   * If layer transforms are turned off, just map 1:1.
303
 
   */
304
 
  else
305
 
  {
306
 
      dst_xoff = src_xoff = 0;
307
 
      dst_yoff = src_yoff = 0;
308
 
      dst_xsize = src_xsize = MIN(image->width,src_xsize);
309
 
      dst_ysize = src_ysize = MIN(image->height,src_ysize);
310
 
  }
311
 
 
312
 
  /*
313
 
   * In RAWDATA mode we don't fool with colors.  Do the raw processing, 
314
 
   * and return from the function early.
315
 
   */
316
 
  if( !gdImg )
317
 
  {
318
 
      assert( MS_RENDERER_RAWDATA( image->format ) );
319
 
 
320
 
      return msDrawRasterLayerGDAL_RawMode( 
321
 
          map, layer, image, hDS, 
322
 
          src_xoff, src_yoff, src_xsize, src_ysize, 
323
 
          dst_xoff, dst_yoff, dst_xsize, dst_ysize );
324
 
  }
325
 
  
326
 
  /*
327
 
   * Is this image classified?  We consider it classified if there are
328
 
   * classes with an expression string *or* a color range.  We don't want
329
 
   * to treat the raster as classified if there is just a bogus class here
330
 
   * to force inclusion in the legend.
331
 
   */
332
 
  for( i = 0; i < layer->numclasses; i++ )
333
 
  {
334
 
      int s;
335
 
 
336
 
      /* change colour based on colour range? */
337
 
      for(s=0; s<layer->class[i]->numstyles; s++)
338
 
      {
339
 
          if( MS_VALID_COLOR(layer->class[i]->styles[s]->mincolor)
340
 
              && MS_VALID_COLOR(layer->class[i]->styles[s]->maxcolor) )
341
 
          {
342
 
              classified = TRUE;
343
 
              break;
344
 
          }
345
 
      }
346
 
      
347
 
      if( layer->class[i]->expression.string != NULL )
348
 
      {
349
 
          classified = TRUE;
350
 
          break;
351
 
      }
352
 
  }
353
 
 
354
 
  /*
355
 
   * Set up the band selection.  We look for a BANDS directive in the 
356
 
   * the PROCESSING options.  If not found we default to red=1 or
357
 
   * red=1,green=2,blue=3 or red=1,green=2,blue=3,alpha=4. 
358
 
   */
359
 
 
360
 
  if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL )
361
 
  {
362
 
      red_band = 1;
363
 
 
364
 
      if( GDALGetRasterCount( hDS ) >= 4 
365
 
          && GDALGetRasterColorInterpretation( 
366
 
              GDALGetRasterBand( hDS, 4 ) ) == GCI_AlphaBand )
367
 
          alpha_band = 4;
368
 
      
369
 
      if( GDALGetRasterCount( hDS ) >= 3 )
370
 
      {
371
 
          green_band = 2;
372
 
          blue_band = 3;
373
 
      }
374
 
 
375
 
      if( GDALGetRasterCount( hDS ) == 2 
376
 
          && GDALGetRasterColorInterpretation( 
377
 
              GDALGetRasterBand( hDS, 2 ) ) == GCI_AlphaBand )
378
 
          alpha_band = 2;
379
 
      
380
 
      hBand1 = GDALGetRasterBand( hDS, red_band );
381
 
      if( classified 
382
 
          || GDALGetRasterColorTable( hBand1 ) != NULL )
383
 
      {
384
 
          alpha_band = 0;
385
 
          green_band = 0;
386
 
          blue_band = 0;
387
 
      }
388
 
  }
389
 
  else
390
 
  {
391
 
      int *band_list;
392
 
 
393
 
      band_list = msGetGDALBandList( layer, hDS, 4, &band_count );
394
 
      if( band_list == NULL )
395
 
          return -1;
396
 
      
397
 
      if( band_count > 0 )
398
 
          red_band = band_list[0];
399
 
      else
400
 
          red_band = 0;
401
 
      if( band_count > 2 )
402
 
      {
403
 
          green_band = band_list[1];
404
 
          blue_band = band_list[2];
405
 
      }
406
 
      else      
407
 
      {
408
 
          green_band = 0;
409
 
          blue_band = 0;
410
 
      }
411
 
 
412
 
      if( band_count > 3 )
413
 
          alpha_band = band_list[3];
414
 
      else
415
 
          alpha_band = 0;
416
 
 
417
 
      free( band_list );
418
 
  }
419
 
 
420
 
  band_numbers[0] = red_band;
421
 
  band_numbers[1] = green_band;
422
 
  band_numbers[2] = blue_band;
423
 
  band_numbers[3] = 0;
424
 
  
425
 
  if( blue_band != 0 && alpha_band != 0 )
426
 
  {
427
 
      band_numbers[3] = alpha_band;
428
 
      band_count = 4;
429
 
  }
430
 
  else if( blue_band != 0 && alpha_band == 0 )
431
 
      band_count = 3;
432
 
  else if( alpha_band != 0 )
433
 
  {
434
 
      band_numbers[1] = alpha_band;
435
 
      band_count = 2;
436
 
  }
437
 
  else
438
 
      band_count = 1;
439
 
  
440
 
  if( layer->debug > 1 || (layer->debug > 0 && green_band != 0) )
441
 
  {
442
 
      msDebug( "msDrawGDAL(): red,green,blue,alpha bands = %d,%d,%d,%d\n", 
443
 
               red_band, green_band, blue_band, alpha_band );
444
 
  }
445
 
 
446
 
  /*
447
 
   * Get band handles for PC256, RGB or RGBA cases.
448
 
   */
449
 
  hBand1 = GDALGetRasterBand( hDS, red_band );
450
 
  if( hBand1 == NULL )
451
 
      return -1;
452
 
 
453
 
  hBand2 = hBand3 = hBandAlpha = NULL;
454
 
 
455
 
  if( green_band != 0 )
456
 
  {
457
 
      hBand1 = GDALGetRasterBand( hDS, red_band );
458
 
      hBand2 = GDALGetRasterBand( hDS, green_band );
459
 
      hBand3 = GDALGetRasterBand( hDS, blue_band );
460
 
      if( hBand1 == NULL || hBand2 == NULL || hBand3 == NULL )
461
 
          return -1;
462
 
  }
463
 
 
464
 
  if( alpha_band != 0 )
465
 
      hBandAlpha = GDALGetRasterBand( hDS, alpha_band );
466
 
 
467
 
  /*
468
 
   * Wipe pen indicators for all our layer class colors if they exist.  
469
 
   * Sometimes temporary gdImg'es are used in which case previously allocated
470
 
   * pens won't generally apply.  See Bug 504.
471
 
   */
472
 
  if( gdImg && !truecolor )
473
 
  {
474
 
      int iClass;
475
 
      int iStyle;
476
 
      for( iClass = 0; iClass < layer->numclasses; iClass++ )
477
 
      {
478
 
          for (iStyle=0; iStyle<layer->class[iClass]->numstyles; iStyle++)
479
 
            layer->class[iClass]->styles[iStyle]->color.pen = MS_PEN_UNSET;
480
 
      }
481
 
  }
482
 
 
483
 
  /*
484
 
   * The logic for a classification rendering of non-8bit raster bands
485
 
   * is sufficiently different than the normal mechanism of loading
486
 
   * into an 8bit buffer, that we isolate it into it's own subfunction.
487
 
   */
488
 
  if( classified && gdImg 
489
 
     && hBand1 != NULL && GDALGetRasterDataType( hBand1 ) != GDT_Byte ) 
490
 
  {
491
 
      return msDrawRasterLayerGDAL_16BitClassification( 
492
 
          map, layer, image, hDS, hBand1,
493
 
          src_xoff, src_yoff, src_xsize, src_ysize, 
494
 
          dst_xoff, dst_yoff, dst_xsize, dst_ysize );
495
 
  }
496
 
 
497
 
  /*
498
 
   * Get colormap for this image.  If there isn't one, and we have only
499
 
   * one band create a greyscale colormap. 
500
 
   */
501
 
  if( hBand2 != NULL )
502
 
      hColorMap = NULL;
503
 
  else
504
 
  {
505
 
      hColorMap = GDALGetRasterColorTable( hBand1 );
506
 
      if( hColorMap != NULL )
507
 
          hColorMap = GDALCloneColorTable( hColorMap );
508
 
      else if( hBand2 == NULL )
509
 
      {
510
 
          hColorMap = GDALCreateColorTable( GPI_RGB );
 
305
    }
 
306
 
 
307
    /*
 
308
     * If layer transforms are turned off, just map 1:1.
 
309
     */
 
310
    else
 
311
    {
 
312
        dst_xoff = src_xoff = 0;
 
313
        dst_yoff = src_yoff = 0;
 
314
        dst_xsize = src_xsize = MIN(image->width,src_xsize);
 
315
        dst_ysize = src_ysize = MIN(image->height,src_ysize);
 
316
    }
 
317
 
 
318
    /*
 
319
     * In RAWDATA mode we don't fool with colors.  Do the raw processing, 
 
320
     * and return from the function early.
 
321
     */
 
322
    if( MS_RENDERER_RAWDATA( image->format ) )
 
323
    {
 
324
        return msDrawRasterLayerGDAL_RawMode( 
 
325
            map, layer, image, hDS, 
 
326
            src_xoff, src_yoff, src_xsize, src_ysize, 
 
327
            dst_xoff, dst_yoff, dst_xsize, dst_ysize );
 
328
    }
 
329
  
 
330
    /*
 
331
     * Is this image classified?  We consider it classified if there are
 
332
     * classes with an expression string *or* a color range.  We don't want
 
333
     * to treat the raster as classified if there is just a bogus class here
 
334
     * to force inclusion in the legend.
 
335
     */
 
336
    for( i = 0; i < layer->numclasses; i++ )
 
337
    {
 
338
        int s;
 
339
 
 
340
        /* change colour based on colour range? */
 
341
        for(s=0; s<layer->class[i]->numstyles; s++)
 
342
        {
 
343
            if( MS_VALID_COLOR(layer->class[i]->styles[s]->mincolor)
 
344
                && MS_VALID_COLOR(layer->class[i]->styles[s]->maxcolor) )
 
345
            {
 
346
                classified = TRUE;
 
347
                break;
 
348
            }
 
349
        }
 
350
      
 
351
        if( layer->class[i]->expression.string != NULL )
 
352
        {
 
353
            classified = TRUE;
 
354
            break;
 
355
        }
 
356
    }
 
357
 
 
358
    /*
 
359
     * Set up the band selection.  We look for a BANDS directive in the 
 
360
     * the PROCESSING options.  If not found we default to red=1 or
 
361
     * red=1,green=2,blue=3 or red=1,green=2,blue=3,alpha=4. 
 
362
     */
 
363
 
 
364
    if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL )
 
365
    {
 
366
        red_band = 1;
 
367
 
 
368
        if( GDALGetRasterCount( hDS ) >= 4 
 
369
            && GDALGetRasterColorInterpretation( 
 
370
                GDALGetRasterBand( hDS, 4 ) ) == GCI_AlphaBand )
 
371
            alpha_band = 4;
 
372
      
 
373
        if( GDALGetRasterCount( hDS ) >= 3 )
 
374
        {
 
375
            green_band = 2;
 
376
            blue_band = 3;
 
377
        }
 
378
 
 
379
        if( GDALGetRasterCount( hDS ) == 2 
 
380
            && GDALGetRasterColorInterpretation( 
 
381
                GDALGetRasterBand( hDS, 2 ) ) == GCI_AlphaBand )
 
382
            alpha_band = 2;
 
383
      
 
384
        hBand1 = GDALGetRasterBand( hDS, red_band );
 
385
        if( classified 
 
386
            || GDALGetRasterColorTable( hBand1 ) != NULL )
 
387
        {
 
388
            alpha_band = 0;
 
389
            green_band = 0;
 
390
            blue_band = 0;
 
391
        }
 
392
    }
 
393
    else
 
394
    {
 
395
        int *band_list;
 
396
 
 
397
        band_list = msGetGDALBandList( layer, hDS, 4, &band_count );
 
398
        if( band_list == NULL )
 
399
            return -1;
 
400
      
 
401
        if( band_count > 0 )
 
402
            red_band = band_list[0];
 
403
        else
 
404
            red_band = 0;
 
405
        if( band_count > 2 )
 
406
        {
 
407
            green_band = band_list[1];
 
408
            blue_band = band_list[2];
 
409
        }
 
410
        else    
 
411
        {
 
412
            green_band = 0;
 
413
            blue_band = 0;
 
414
        }
 
415
 
 
416
        if( band_count > 3 )
 
417
            alpha_band = band_list[3];
 
418
        else
 
419
            alpha_band = 0;
 
420
 
 
421
        free( band_list );
 
422
    }
 
423
 
 
424
    band_numbers[0] = red_band;
 
425
    band_numbers[1] = green_band;
 
426
    band_numbers[2] = blue_band;
 
427
    band_numbers[3] = 0;
 
428
  
 
429
    if( blue_band != 0 && alpha_band != 0 )
 
430
    {
 
431
        band_numbers[3] = alpha_band;
 
432
        band_count = 4;
 
433
    }
 
434
    else if( blue_band != 0 && alpha_band == 0 )
 
435
        band_count = 3;
 
436
    else if( alpha_band != 0 )
 
437
    {
 
438
        band_numbers[1] = alpha_band;
 
439
        band_count = 2;
 
440
    }
 
441
    else
 
442
        band_count = 1;
 
443
  
 
444
    if( layer->debug > 1 || (layer->debug > 0 && green_band != 0) )
 
445
    {
 
446
        msDebug( "msDrawRasterLayerGDAL(): red,green,blue,alpha bands = %d,%d,%d,%d\n", 
 
447
                 red_band, green_band, blue_band, alpha_band );
 
448
    }
 
449
 
 
450
    /*
 
451
     * Get band handles for PC256, RGB or RGBA cases.
 
452
     */
 
453
    hBand1 = GDALGetRasterBand( hDS, red_band );
 
454
    if( hBand1 == NULL )
 
455
        return -1;
 
456
 
 
457
    hBand2 = hBand3 = hBandAlpha = NULL;
 
458
 
 
459
    if( green_band != 0 )
 
460
    {
 
461
        hBand1 = GDALGetRasterBand( hDS, red_band );
 
462
        hBand2 = GDALGetRasterBand( hDS, green_band );
 
463
        hBand3 = GDALGetRasterBand( hDS, blue_band );
 
464
        if( hBand1 == NULL || hBand2 == NULL || hBand3 == NULL )
 
465
            return -1;
 
466
    }
 
467
 
 
468
    if( alpha_band != 0 )
 
469
        hBandAlpha = GDALGetRasterBand( hDS, alpha_band );
 
470
 
 
471
    /*
 
472
     * Wipe pen indicators for all our layer class colors if they exist.  
 
473
     * Sometimes temporary gdImg'es are used in which case previously allocated
 
474
     * pens won't generally apply.  See Bug 504.
 
475
     */
 
476
    if( rb->type == MS_BUFFER_GD )
 
477
    {
 
478
        int iClass;
 
479
        int iStyle;
 
480
        for( iClass = 0; iClass < layer->numclasses; iClass++ )
 
481
        {
 
482
            for (iStyle=0; iStyle<layer->class[iClass]->numstyles; iStyle++)
 
483
                layer->class[iClass]->styles[iStyle]->color.pen = MS_PEN_UNSET;
 
484
        }
 
485
    }
 
486
 
 
487
    /*
 
488
     * The logic for a classification rendering of non-8bit raster bands
 
489
     * is sufficiently different than the normal mechanism of loading
 
490
     * into an 8bit buffer, that we isolate it into it's own subfunction.
 
491
     */
 
492
    if( classified 
 
493
        && hBand1 != NULL && GDALGetRasterDataType( hBand1 ) != GDT_Byte ) 
 
494
    {
 
495
        return msDrawRasterLayerGDAL_16BitClassification( 
 
496
            map, layer, rb, hDS, hBand1,
 
497
            src_xoff, src_yoff, src_xsize, src_ysize, 
 
498
            dst_xoff, dst_yoff, dst_xsize, dst_ysize );
 
499
    }
 
500
 
 
501
    /*
 
502
     * Get colormap for this image.  If there isn't one, and we have only
 
503
     * one band create a greyscale colormap. 
 
504
     */
 
505
    if( hBand2 != NULL )
 
506
        hColorMap = NULL;
 
507
    else
 
508
    {
 
509
        hColorMap = GDALGetRasterColorTable( hBand1 );
 
510
        if( hColorMap != NULL )
 
511
            hColorMap = GDALCloneColorTable( hColorMap );
 
512
        else if( hBand2 == NULL )
 
513
        {
 
514
            hColorMap = GDALCreateColorTable( GPI_RGB );
511
515
          
512
 
          for( i = 0; i < 256; i++ )
513
 
          {
514
 
              colorObj pixel;
515
 
              GDALColorEntry sEntry;
 
516
            for( i = 0; i < 256; i++ )
 
517
            {
 
518
                colorObj pixel;
 
519
                GDALColorEntry sEntry;
516
520
 
517
 
              pixel.red = i;
518
 
              pixel.green = i;
519
 
              pixel.blue = i;
520
 
              pixel.pen = i;
 
521
                pixel.red = i;
 
522
                pixel.green = i;
 
523
                pixel.blue = i;
 
524
                pixel.pen = i;
521
525
              
522
 
              if(MS_COMPARE_COLORS(pixel, layer->offsite))
523
 
              {
524
 
                  sEntry.c1 = 0;
525
 
                  sEntry.c2 = 0;
526
 
                  sEntry.c3 = 0;
527
 
                  sEntry.c4 = 0; /* alpha set to zero */
528
 
              }
529
 
              else if( truecolor )
530
 
              {
531
 
                  sEntry.c1 = i;
532
 
                  sEntry.c2 = i;
533
 
                  sEntry.c3 = i;
534
 
                  sEntry.c4 = 255;
535
 
              }
536
 
              else
537
 
              {
538
 
                  /*
539
 
                  ** This special calculation is intended to use only 128
540
 
                  ** unique colors for greyscale in non-truecolor mode.
541
 
                  */
 
526
                if(MS_COMPARE_COLORS(pixel, layer->offsite))
 
527
                {
 
528
                    sEntry.c1 = 0;
 
529
                    sEntry.c2 = 0;
 
530
                    sEntry.c3 = 0;
 
531
                    sEntry.c4 = 0; /* alpha set to zero */
 
532
                }
 
533
                else if( rb->type != MS_BUFFER_GD )
 
534
                {
 
535
                    sEntry.c1 = i;
 
536
                    sEntry.c2 = i;
 
537
                    sEntry.c3 = i;
 
538
                    sEntry.c4 = 255;
 
539
                }
 
540
                else
 
541
                {
 
542
                    /*
 
543
                    ** This special calculation is intended to use only 128
 
544
                    ** unique colors for greyscale in non-truecolor mode.
 
545
                    */
542
546
 
543
 
                  sEntry.c1 = i - i%2;
544
 
                  sEntry.c2 = i - i%2;
545
 
                  sEntry.c3 = i - i%2;
546
 
                  sEntry.c4 = 255;
547
 
              }
 
547
                    sEntry.c1 = i - i%2;
 
548
                    sEntry.c2 = i - i%2;
 
549
                    sEntry.c3 = i - i%2;
 
550
                    sEntry.c4 = 255;
 
551
                }
548
552
                  
549
 
              GDALSetColorEntry( hColorMap, i, &sEntry );
550
 
          }
551
 
      }
552
 
 
553
 
      /* 
554
 
      ** If we have a known NODATA value, mark it now as transparent. 
555
 
      */
556
 
      {
557
 
          int    bGotNoData;
558
 
          double dfNoDataValue = msGetGDALNoDataValue( layer, hBand1, 
559
 
                                                       &bGotNoData);
560
 
 
561
 
          if( bGotNoData && dfNoDataValue >= 0 
562
 
              && dfNoDataValue < GDALGetColorEntryCount( hColorMap ) )
563
 
          {
564
 
              GDALColorEntry sEntry;
 
553
                GDALSetColorEntry( hColorMap, i, &sEntry );
 
554
            }
 
555
        }
 
556
 
 
557
        /* 
 
558
        ** If we have a known NODATA value, mark it now as transparent. 
 
559
        */
 
560
        {
 
561
            int    bGotNoData;
 
562
            double dfNoDataValue = msGetGDALNoDataValue( layer, hBand1, 
 
563
                                                         &bGotNoData);
 
564
 
 
565
            if( bGotNoData && dfNoDataValue >= 0 
 
566
                && dfNoDataValue < GDALGetColorEntryCount( hColorMap ) )
 
567
            {
 
568
                GDALColorEntry sEntry;
565
569
              
566
 
              memcpy( &sEntry, 
567
 
                      GDALGetColorEntry( hColorMap, (int) dfNoDataValue ),
568
 
                      sizeof(GDALColorEntry) );
569
 
 
570
 
              sEntry.c4 = 0;
571
 
              GDALSetColorEntry( hColorMap, (int) dfNoDataValue, &sEntry );
572
 
          }
573
 
      }
574
 
  }
575
 
 
576
 
  /*
577
 
   * Setup the mapping between source eightbit pixel values, and the
578
 
   * output images color table.  There are two general cases, where the
579
 
   * class colors are provided by the MAP file, or where we use the native
580
 
   * color table.
581
 
   */
582
 
  if( classified && gdImg ) {
583
 
    int c, color_count;
584
 
 
585
 
    cmap_set = TRUE;
586
 
 
587
 
    if( hColorMap == NULL )
588
 
    {
589
 
        msSetError(MS_IOERR, 
590
 
                   "Attempt to classify 24bit image, this is unsupported.",
591
 
                   "drawGDAL()");
592
 
        return -1;
 
570
                memcpy( &sEntry, 
 
571
                        GDALGetColorEntry( hColorMap, (int) dfNoDataValue ),
 
572
                        sizeof(GDALColorEntry) );
 
573
 
 
574
                sEntry.c4 = 0;
 
575
                GDALSetColorEntry( hColorMap, (int) dfNoDataValue, &sEntry );
 
576
            }
 
577
        }
593
578
    }
594
579
 
595
 
    color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
596
 
    for(i=0; i < color_count; i++) {
597
 
        colorObj pixel;
598
 
        GDALColorEntry sEntry;
599
 
 
600
 
        GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
 
580
    /*
 
581
     * Setup the mapping between source eight bit pixel values, and the
 
582
     * output images color table.  There are two general cases, where the
 
583
     * class colors are provided by the MAP file, or where we use the native
 
584
     * color table.
 
585
     */
 
586
    if( classified ) {
 
587
        int c, color_count;
 
588
 
 
589
        cmap_set = TRUE;
 
590
 
 
591
        if( hColorMap == NULL )
 
592
        {
 
593
            msSetError(MS_IOERR, 
 
594
                       "Attempt to classify 24bit image, this is unsupported.",
 
595
                       "drawGDAL()");
 
596
            return -1;
 
597
        }
 
598
 
 
599
        color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
 
600
        for(i=0; i < color_count; i++) {
 
601
            colorObj pixel;
 
602
            GDALColorEntry sEntry;
 
603
 
 
604
            GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
601
605
            
602
 
        pixel.red = sEntry.c1;
603
 
        pixel.green = sEntry.c2;
604
 
        pixel.blue = sEntry.c3;
605
 
        pixel.pen = i;
 
606
            pixel.red = sEntry.c1;
 
607
            pixel.green = sEntry.c2;
 
608
            pixel.blue = sEntry.c3;
 
609
            pixel.pen = i;
606
610
        
607
 
        if(!MS_COMPARE_COLORS(pixel, layer->offsite))
608
 
        {
609
 
            c = msGetClass(layer, &pixel);
 
611
            if(!MS_COMPARE_COLORS(pixel, layer->offsite))
 
612
            {
 
613
                c = msGetClass(layer, &pixel);
610
614
            
611
 
            if(c == -1)/* doesn't belong to any class, so handle like offsite*/
612
 
                cmap[i] = -1;
613
 
            else
614
 
            {
615
 
                int s;
 
615
                if(c == -1)/* doesn't belong to any class, so handle like offsite*/
 
616
                {
 
617
                    if( rb->type == MS_BUFFER_GD )
 
618
                        cmap[i] = -1;
 
619
                }
 
620
                else
 
621
                {
 
622
                    int s;
616
623
                
617
 
                /* change colour based on colour range?  Currently we 
618
 
                   only address the greyscale case properly. */
619
 
 
620
 
                for(s=0; s<layer->class[c]->numstyles; s++)
621
 
                {
622
 
                    if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor)
623
 
                        && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) )
624
 
                        msValueToRange(layer->class[c]->styles[s],
625
 
                                       sEntry.c1 );
 
624
                    /* change colour based on colour range?  Currently we 
 
625
                       only address the greyscale case properly. */
 
626
 
 
627
                    for(s=0; s<layer->class[c]->numstyles; s++)
 
628
                    {
 
629
                        if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor)
 
630
                            && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) )
 
631
                            msValueToRange(layer->class[c]->styles[s],
 
632
                                           sEntry.c1 );
 
633
                    }
 
634
 
 
635
                    if( rb->type == MS_BUFFER_GD )
 
636
                    {
 
637
                        RESOLVE_PEN_GD(rb->data.gd_img, layer->class[c]->styles[0]->color);
 
638
                        if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) )
 
639
                            cmap[i] = -1;
 
640
                        else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
 
641
                        {
 
642
                            /* use class color */
 
643
                            cmap[i] = layer->class[c]->styles[0]->color.pen;
 
644
                        }
 
645
                        else /* Use raster color */
 
646
                            cmap[i] = msAddColorGD(map, rb->data.gd_img, cmt,
 
647
                                                   pixel.red, pixel.green, pixel.blue);
 
648
                    }
 
649
                    else if( rb->type == MS_BUFFER_BYTE_RGBA )
 
650
                    {
 
651
                        if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color))
 
652
                            /* leave it transparent */;
 
653
 
 
654
                        else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
 
655
                        {
 
656
                            rb_cmap[0][i] = layer->class[c]->styles[0]->color.red;
 
657
                            rb_cmap[1][i] = layer->class[c]->styles[0]->color.green;
 
658
                            rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue;
 
659
                            rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100);
 
660
                        }
 
661
 
 
662
                        else /* Use raster color */
 
663
                        {
 
664
                            rb_cmap[0][i] = pixel.red;
 
665
                            rb_cmap[1][i] = pixel.green;
 
666
                            rb_cmap[2][i] = pixel.blue;
 
667
                            rb_cmap[3][i] = 255;
 
668
                        }
 
669
                    }
626
670
                }
627
 
 
628
 
                RESOLVE_PEN_GD(gdImg, layer->class[c]->styles[0]->color);
629
 
                if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) )
 
671
            } else {
 
672
                if( rb->type == MS_BUFFER_GD )
630
673
                    cmap[i] = -1;
631
 
                else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
632
 
                {
633
 
                    /* use class color */
634
 
                    cmap[i] = layer->class[c]->styles[0]->color.pen;
635
 
                }
636
 
                else /* Use raster color */
637
 
                    cmap[i] = msAddColorGD(map, gdImg, cmt,
638
 
                                           pixel.red, pixel.green, pixel.blue);
639
 
            }
640
 
        } else
641
 
            cmap[i] = -1;
642
 
    }
643
 
  } else if( hColorMap != NULL && !truecolor && gdImg ) {
644
 
    int color_count;
645
 
    cmap_set = TRUE;
646
 
 
647
 
    color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
648
 
 
649
 
    for(i=0; i < color_count; i++) {
650
 
        GDALColorEntry sEntry;
651
 
 
652
 
        GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
653
 
 
654
 
        if( sEntry.c4 != 0 
655
 
            && (!MS_VALID_COLOR( layer->offsite )
656
 
                || layer->offsite.red != sEntry.c1
657
 
                || layer->offsite.green != sEntry.c2
658
 
                || layer->offsite.blue != sEntry.c3 ) )
659
 
            cmap[i] = msAddColorGD(map, gdImg, cmt, 
660
 
                                   sEntry.c1, sEntry.c2, sEntry.c3);
 
674
            }
 
675
        }
 
676
    } else if( hColorMap != NULL && rb->type == MS_BUFFER_GD ) {
 
677
        int color_count;
 
678
        cmap_set = TRUE;
 
679
 
 
680
        color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
 
681
 
 
682
        for(i=0; i < color_count; i++) {
 
683
            GDALColorEntry sEntry;
 
684
 
 
685
            GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
 
686
 
 
687
            if( sEntry.c4 != 0 
 
688
                && (!MS_VALID_COLOR( layer->offsite )
 
689
                    || layer->offsite.red != sEntry.c1
 
690
                    || layer->offsite.green != sEntry.c2
 
691
                    || layer->offsite.blue != sEntry.c3 ) )
 
692
                cmap[i] = msAddColorGD(map, rb->data.gd_img, cmt, 
 
693
                                       sEntry.c1, sEntry.c2, sEntry.c3);
 
694
            else
 
695
                cmap[i] = -1;
 
696
        }
 
697
    }
 
698
    else if( hBand2 == NULL && hColorMap != NULL && rb->type == MS_BUFFER_BYTE_RGBA )
 
699
    {
 
700
        int color_count;
 
701
        cmap_set = TRUE;
 
702
 
 
703
        color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
 
704
 
 
705
        for(i=0; i < color_count; i++) {
 
706
            GDALColorEntry sEntry;
 
707
          
 
708
            GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
 
709
 
 
710
            if( sEntry.c4 != 0 
 
711
                && (!MS_VALID_COLOR( layer->offsite )
 
712
                    || layer->offsite.red != sEntry.c1
 
713
                    || layer->offsite.green != sEntry.c2
 
714
                    || layer->offsite.blue != sEntry.c3 ) )
 
715
            {
 
716
                rb_cmap[0][i] = sEntry.c1;
 
717
                rb_cmap[1][i] = sEntry.c2;
 
718
                rb_cmap[2][i] = sEntry.c3;
 
719
                rb_cmap[3][i] = sEntry.c4;
 
720
            }
 
721
        }
 
722
    }
 
723
    else if( rb->type == MS_BUFFER_GD )
 
724
    {
 
725
        allocColorCube( map, rb->data.gd_img, anColorCube );
 
726
    }
 
727
 
 
728
    /*
 
729
     * Allocate imagery buffers.
 
730
     */
 
731
    pabyRaw1 = (unsigned char *) malloc(dst_xsize * dst_ysize * band_count);
 
732
    if( pabyRaw1 == NULL )
 
733
    {
 
734
        msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.",
 
735
                   "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count );
 
736
        return -1;
 
737
    }
 
738
 
 
739
    if( hBand2 != NULL && hBand3 != NULL )
 
740
    {
 
741
        pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1;
 
742
        pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2;
 
743
    }
 
744
 
 
745
    if( hBandAlpha != NULL )
 
746
    {
 
747
        if( hBand2 != NULL )
 
748
            pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3;
661
749
        else
662
 
            cmap[i] = -1;
663
 
    }
664
 
  }
665
 
  else if( hBand2 == NULL && hColorMap != NULL )
666
 
  {
667
 
      int color_count;
668
 
      cmap_set = TRUE;
669
 
 
670
 
      color_count = MIN(256,GDALGetColorEntryCount(hColorMap));
671
 
 
672
 
      for(i=0; i < color_count; i++) {
673
 
          GDALColorEntry sEntry;
674
 
          
675
 
          GDALGetColorEntryAsRGB( hColorMap, i, &sEntry );
676
 
 
677
 
          if( sEntry.c4 != 0 
678
 
              && (!MS_VALID_COLOR( layer->offsite )
679
 
                  || layer->offsite.red != sEntry.c1
680
 
                  || layer->offsite.green != sEntry.c2
681
 
                  || layer->offsite.blue != sEntry.c3 ) )
682
 
              cmap[i] = gdTrueColorAlpha(sEntry.c1, sEntry.c2, sEntry.c3, 
683
 
                                         127 - (sEntry.c4 >> 1) );
684
 
          else
685
 
              cmap[i] = -1;
686
 
      }
687
 
  }
688
 
  else if( !truecolor && gdImg )
689
 
  {
690
 
      allocColorCube( map, gdImg, anColorCube );
691
 
  }
692
 
  else if( !truecolor )
693
 
  {
694
 
      msSetError(MS_IOERR, 
695
 
                 "Unsupported configuration for raster layer read via GDAL.",
696
 
                 "drawGDAL()");
697
 
      return -1;
698
 
  }
699
 
 
700
 
  /*
701
 
   * Allocate imagery buffers.
702
 
   */
703
 
  pabyRaw1 = (unsigned char *) malloc(dst_xsize * dst_ysize * band_count);
704
 
  if( pabyRaw1 == NULL )
705
 
  {
706
 
      msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.",
707
 
                 "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count );
708
 
      return -1;
709
 
  }
710
 
 
711
 
  if( hBand2 != NULL && hBand3 != NULL )
712
 
  {
713
 
      pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1;
714
 
      pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2;
715
 
  }
716
 
 
717
 
  if( hBandAlpha != NULL )
718
 
  {
719
 
      if( hBand2 != NULL )
720
 
          pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3;
721
 
      else
722
 
          pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1;
723
 
  }
724
 
 
725
 
  /*
726
 
   * Load image data into buffers with scaling, etc.
727
 
   */
728
 
  if( LoadGDALImages( hDS, band_numbers, band_count, layer, 
729
 
                      src_xoff, src_yoff, src_xsize, src_ysize, 
730
 
                      pabyRaw1, dst_xsize, dst_ysize ) == -1 )
731
 
  {
732
 
      free( pabyRaw1 );
733
 
      return -1;
734
 
  }
 
750
            pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1;
 
751
    }
 
752
 
 
753
    /*
 
754
     * Load image data into buffers with scaling, etc.
 
755
     */
 
756
    if( LoadGDALImages( hDS, band_numbers, band_count, layer, 
 
757
                        src_xoff, src_yoff, src_xsize, src_ysize, 
 
758
                        pabyRaw1, dst_xsize, dst_ysize,
 
759
                        &bHaveRGBNoData, 
 
760
                        &nNoData1, &nNoData2, &nNoData3 ) == -1 )
 
761
    {
 
762
        free( pabyRaw1 );
 
763
        return -1;
 
764
    }
 
765
 
 
766
    if( bHaveRGBNoData && layer->debug )
 
767
        msDebug( "msDrawGDAL(): using RGB nodata values from GDAL dataset.\n" );
 
768
 
 
769
/* -------------------------------------------------------------------- */
 
770
/*      If there was no alpha band, but we have a dataset level mask    */
 
771
/*      load it as massage it so it will function as our alpha for      */
 
772
/*      transparency purposes.                                          */
 
773
/* -------------------------------------------------------------------- */
 
774
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1500 
 
775
    if( hBandAlpha == NULL )
 
776
    {
 
777
        int nMaskFlags = GDALGetMaskFlags(hBand1); 
 
778
   
 
779
        if( (CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) && 
 
780
            (nMaskFlags & GMF_PER_DATASET) != 0 && 
 
781
            (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 ) 
 
782
        { 
 
783
            CPLErr eErr; 
 
784
 
 
785
            if( layer->debug )
 
786
                msDebug( "msDrawGDAL(): using GDAL mask band for alpha.\n" );
 
787
                 
 
788
            band_count++;
 
789
 
 
790
            pabyRaw1 = (unsigned char *) 
 
791
                realloc(pabyRaw1,dst_xsize * dst_ysize * band_count);
 
792
            
 
793
            if( pabyRaw1 == NULL ) 
 
794
            { 
 
795
                msSetError(MS_MEMERR, 
 
796
                           "Allocating work image of size %dx%dx%d failed.", 
 
797
                           "msDrawRasterLayerGDAL()", 
 
798
                           dst_xsize, dst_ysize, band_count ); 
 
799
                return -1; 
 
800
            } 
 
801
 
 
802
            if( hBand2 != NULL )
 
803
            {
 
804
                pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1;
 
805
                pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2;
 
806
                pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3;
 
807
            }
 
808
            else
 
809
            {
 
810
                pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1;
 
811
            }
 
812
 
 
813
            hBandAlpha = GDALGetMaskBand(hBand1); 
 
814
                 
 
815
            eErr = GDALRasterIO( hBandAlpha, GF_Read,  
 
816
                                 src_xoff, src_yoff, src_xsize, src_ysize,  
 
817
                                 pabyRawAlpha, dst_xsize, dst_ysize, GDT_Byte, 0,0); 
 
818
                 
 
819
            if( eErr != CE_None ) 
 
820
            { 
 
821
                msSetError( MS_IOERR, "GDALRasterIO() failed: %s",  
 
822
                            "drawGDAL()", CPLGetLastErrorMsg() ); 
 
823
                free( pabyRaw1 ); 
 
824
                return -1; 
 
825
            } 
 
826
                 
 
827
            /* In case the mask is not an alpha channel, expand values of 1 to 255, */ 
 
828
            /* so we can deal as it was an alpha band afterwards */ 
 
829
            if ((nMaskFlags & GMF_ALPHA) == 0) 
 
830
            { 
 
831
                for(i=0;i<dst_xsize * dst_ysize;i++) 
 
832
                    if (pabyRawAlpha[i]) 
 
833
                        pabyRawAlpha[i] = 255; 
 
834
            } 
 
835
        } 
 
836
    }
 
837
#endif /* defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1500 */
735
838
 
736
839
/* -------------------------------------------------------------------- */
737
840
/*      Single band plus colormap with alpha blending to 8bit.          */
738
841
/* -------------------------------------------------------------------- */
739
 
  if( hBand2 == NULL && !truecolor && gdImg && hBandAlpha != NULL )
740
 
  {
741
 
      assert( cmap_set );
742
 
      k = 0;
 
842
    if( hBand2 == NULL && rb->type == MS_BUFFER_GD && hBandAlpha != NULL )
 
843
    {
 
844
        assert( cmap_set );
 
845
        k = 0;
743
846
 
744
 
      for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
745
 
      {
746
 
          int   result, alpha;
 
847
        for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
848
        {
 
849
            int result, alpha;
747
850
          
748
 
          for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
749
 
          {
750
 
              alpha = pabyRawAlpha[k];
751
 
 
752
 
              result = cmap[pabyRaw1[k++]];
753
 
 
754
 
              /* 
755
 
              ** We don't do alpha blending in non-truecolor mode, just
756
 
              ** threshold the point on/off at alpha=128.
757
 
              */
758
 
 
759
 
              if( result != -1 && alpha >= 128 )
760
 
                  gdImg->pixels[i][j] = result;
761
 
          }
762
 
      }
763
 
 
764
 
      assert( k == dst_xsize * dst_ysize );
765
 
  }
 
851
            for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
 
852
            {
 
853
                alpha = pabyRawAlpha[k];
 
854
 
 
855
                result = cmap[pabyRaw1[k++]];
 
856
 
 
857
                /* 
 
858
                ** We don't do alpha blending in non-truecolor mode, just
 
859
                ** threshold the point on/off at alpha=128.
 
860
                */
 
861
 
 
862
                if( result != -1 && alpha >= 128 )
 
863
                    rb->data.gd_img->pixels[i][j] = result;
 
864
            }
 
865
        }
 
866
 
 
867
        assert( k == dst_xsize * dst_ysize );
 
868
    }
766
869
 
767
870
/* -------------------------------------------------------------------- */
768
871
/*      Single band plus colormap (no alpha) to 8bit.                   */
769
872
/* -------------------------------------------------------------------- */
770
 
  else if( hBand2 == NULL && !truecolor && gdImg )
771
 
  {
772
 
      assert( cmap_set );
773
 
      k = 0;
774
 
 
775
 
      for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
776
 
      {
777
 
          int   result;
778
 
          
779
 
          for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
780
 
          {
781
 
              result = cmap[pabyRaw1[k++]];
782
 
              if( result != -1 )
783
 
              {
784
 
                  gdImg->pixels[i][j] = result;
785
 
              }
786
 
          }
787
 
      }
788
 
 
789
 
      assert( k == dst_xsize * dst_ysize );
790
 
  }
791
 
 
792
 
/* -------------------------------------------------------------------- */
793
 
/*      Single band plus colormap and alpha to truecolor.               */
794
 
/* -------------------------------------------------------------------- */
795
 
  else if( hBand2 == NULL && truecolor && gdImg && hBandAlpha != NULL )
796
 
  {
797
 
      assert( cmap_set );
798
 
 
799
 
      k = 0;
800
 
      for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
801
 
      {
802
 
          int   result, alpha;
803
 
          
804
 
          for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
805
 
          {
806
 
              alpha = pabyRawAlpha[k];
807
 
              result = cmap[pabyRaw1[k++]];
808
 
 
809
 
              if( result == -1 || alpha < 2 )
810
 
                  /* do nothing - transparent */;
811
 
              else if( alpha > 253 )
812
 
                  gdImg->tpixels[i][j] = result;
813
 
              else
814
 
              {
815
 
                  /* mix alpha into "result" */
816
 
                  result += (127 - (alpha >> 1)) << 24;
817
 
                  gdImg->tpixels[i][j] = 
818
 
                      msAlphaBlend( gdImg->tpixels[i][j], result );
819
 
              }
820
 
          }
821
 
      }
822
 
  }
823
 
 
824
 
/* -------------------------------------------------------------------- */
825
 
/*      Single band plus colormap (no alpha) to truecolor               */
826
 
/* -------------------------------------------------------------------- */
827
 
  else if( hBand2 == NULL && truecolor && gdImg )
828
 
  {
829
 
      assert( cmap_set );
830
 
 
831
 
      k = 0;
832
 
      for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
833
 
      {
834
 
          int   result;
835
 
          
836
 
          for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
837
 
          {
838
 
              result = cmap[pabyRaw1[k++]];
839
 
              if( result != -1 )
840
 
                  gdImg->tpixels[i][j] = result;
841
 
          }
842
 
      }
843
 
  }
844
 
 
845
 
/* -------------------------------------------------------------------- */
846
 
/*      Input is 3 band RGB.  Alpha blending is mixed into the loop     */
847
 
/*      since this case is less commonly used and has lots of other     */
848
 
/*      overhead.                                                       */
849
 
/* -------------------------------------------------------------------- */
850
 
  else if( hBand3 != NULL && gdImg )
851
 
  {
852
 
      /* Dithered 24bit to 8bit conversion */
853
 
      if( !truecolor && CSLFetchBoolean( layer->processing, "DITHER", FALSE ) )
854
 
      {
 
873
    else if( hBand2 == NULL  && rb->type == MS_BUFFER_GD )
 
874
    {
 
875
        assert( cmap_set );
 
876
        k = 0;
 
877
 
 
878
        for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
879
        {
 
880
            int result;
 
881
          
 
882
            for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
 
883
            {
 
884
                result = cmap[pabyRaw1[k++]];
 
885
                if( result != -1 )
 
886
                {
 
887
                    rb->data.gd_img->pixels[i][j] = result;
 
888
                }
 
889
            }
 
890
        }
 
891
 
 
892
        assert( k == dst_xsize * dst_ysize );
 
893
    }
 
894
 
 
895
/* -------------------------------------------------------------------- */
 
896
/*      Single band plus colormap and alpha to truecolor. (RB)          */
 
897
/* -------------------------------------------------------------------- */
 
898
    else if( hBand2 == NULL && rb->type == MS_BUFFER_BYTE_RGBA && hBandAlpha != NULL )
 
899
    {
 
900
        assert( cmap_set );
 
901
 
 
902
        k = 0;
 
903
        for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
904
        {
 
905
            for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
 
906
            {
 
907
                int     src_pixel, src_alpha, cmap_alpha, merged_alpha;
 
908
 
 
909
                src_pixel = pabyRaw1[k];
 
910
                src_alpha = pabyRawAlpha[k];
 
911
                cmap_alpha = rb_cmap[3][src_pixel];
 
912
 
 
913
                merged_alpha = (src_alpha * cmap_alpha) / 255;
 
914
 
 
915
                if( merged_alpha < 2 )
 
916
                    /* do nothing - transparent */;
 
917
                else if( merged_alpha > 253 )
 
918
                {
 
919
                    RB_SET_PIXEL( rb, j, i, 
 
920
                                  rb_cmap[0][src_pixel], 
 
921
                                  rb_cmap[1][src_pixel], 
 
922
                                  rb_cmap[2][src_pixel], 
 
923
                                  cmap_alpha );
 
924
                }
 
925
                else
 
926
                {
 
927
                    RB_MIX_PIXEL( rb, j, i, 
 
928
                                  rb_cmap[0][src_pixel], 
 
929
                                  rb_cmap[1][src_pixel], 
 
930
                                  rb_cmap[2][src_pixel], 
 
931
                                  merged_alpha );
 
932
                }
 
933
                k++;
 
934
            }
 
935
        }
 
936
    }
 
937
 
 
938
/* -------------------------------------------------------------------- */
 
939
/*      Single band plus colormap (no alpha) to truecolor (RB)          */
 
940
/* -------------------------------------------------------------------- */
 
941
    else if( hBand2 == NULL && rb->type == MS_BUFFER_BYTE_RGBA )
 
942
    {
 
943
        assert( cmap_set );
 
944
 
 
945
        k = 0;
 
946
        for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
947
        {
 
948
            for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
 
949
            {
 
950
                int src_pixel = pabyRaw1[k++];
 
951
 
 
952
                if( rb_cmap[3][src_pixel] > 253 )
 
953
                {
 
954
                    RB_SET_PIXEL( rb, j, i, 
 
955
                                  rb_cmap[0][src_pixel], 
 
956
                                  rb_cmap[1][src_pixel], 
 
957
                                  rb_cmap[2][src_pixel], 
 
958
                                  rb_cmap[3][src_pixel] );
 
959
                }                  
 
960
                else if( rb_cmap[3][src_pixel] > 1 )
 
961
                {
 
962
                    RB_MIX_PIXEL( rb, j, i, 
 
963
                                  rb_cmap[0][src_pixel], 
 
964
                                  rb_cmap[1][src_pixel], 
 
965
                                  rb_cmap[2][src_pixel], 
 
966
                                  rb_cmap[3][src_pixel] );
 
967
                }                  
 
968
            }
 
969
        }
 
970
    }
 
971
 
 
972
/* -------------------------------------------------------------------- */
 
973
/*      Input is 3 band RGB.  Alpha blending is mixed into the loop     */
 
974
/*      since this case is less commonly used and has lots of other     */
 
975
/*      overhead. (RB)                                                  */
 
976
/* -------------------------------------------------------------------- */
 
977
    else if( hBand3 != NULL && rb->type == MS_BUFFER_BYTE_RGBA )
 
978
    {
 
979
        k = 0;
 
980
        for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
981
        {
 
982
            for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
 
983
            {
 
984
                if( MS_VALID_COLOR( layer->offsite )
 
985
                    && pabyRaw1[k] == layer->offsite.red
 
986
                    && pabyRaw2[k] == layer->offsite.green
 
987
                    && pabyRaw3[k] == layer->offsite.blue )
 
988
                    continue;
 
989
 
 
990
                if( bHaveRGBNoData 
 
991
                    && pabyRaw1[k] == nNoData1 
 
992
                    && pabyRaw2[k] == nNoData2 
 
993
                    && pabyRaw3[k] == nNoData3 )
 
994
                    continue;
 
995
 
 
996
                if( pabyRawAlpha == NULL || pabyRawAlpha[k] == 255 )
 
997
                {
 
998
                    RB_SET_PIXEL( rb, j, i, 
 
999
                                  pabyRaw1[k],
 
1000
                                  pabyRaw2[k],
 
1001
                                  pabyRaw3[k],
 
1002
                                  255 );
 
1003
                }
 
1004
                else if( pabyRawAlpha[k] != 0 )
 
1005
                {
 
1006
                    RB_MIX_PIXEL( rb, j, i, 
 
1007
                                  pabyRaw1[k],
 
1008
                                  pabyRaw2[k],
 
1009
                                  pabyRaw3[k],
 
1010
                                  pabyRawAlpha[k] );
 
1011
                }
 
1012
            }
 
1013
        }
 
1014
    }
 
1015
 
 
1016
/* -------------------------------------------------------------------- */
 
1017
/*      Input is 3 band RGB.  Alpha blending is mixed into the loop     */
 
1018
/*      since this case is less commonly used and has lots of other     */
 
1019
/*      overhead. (GD)                                                  */
 
1020
/* -------------------------------------------------------------------- */
 
1021
    else if( hBand3 != NULL && rb->type == MS_BUFFER_GD )
 
1022
    {
 
1023
        /* Dithered 24bit to 8bit conversion */
 
1024
        if( CSLFetchBoolean( layer->processing, "DITHER", FALSE ) )
 
1025
        {
855
1026
#ifdef ENABLE_DITHER
856
 
          unsigned char *pabyDithered;
857
 
 
858
 
          pabyDithered = (unsigned char *) malloc(dst_xsize * dst_ysize);
859
 
          if( pabyDithered == NULL )
860
 
          {
861
 
              msSetError(MS_MEMERR, "Allocating work image of size %dx%d failed.",
862
 
                         "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize );
863
 
              return -1;
864
 
          }
865
 
          
866
 
          Dither24to8( pabyRaw1, pabyRaw2, pabyRaw3, pabyDithered,
867
 
                       dst_xsize, dst_ysize, image->format->transparent, 
868
 
                       map->imagecolor, gdImg );
869
 
 
870
 
          k = 0;
871
 
          for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
872
 
          {
873
 
              for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
874
 
              {
875
 
                  if( MS_VALID_COLOR( layer->offsite )
876
 
                      && pabyRaw1[k] == layer->offsite.red
877
 
                      && pabyRaw2[k] == layer->offsite.green
878
 
                      && pabyRaw3[k] == layer->offsite.blue )
879
 
                      continue;
880
 
 
881
 
                  if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 )
882
 
                      continue;
883
 
 
884
 
                  gdImg->pixels[i][j] = pabyDithered[k];
885
 
              }
886
 
          }
887
 
          
888
 
          free( pabyDithered );
 
1027
            unsigned char *pabyDithered;
 
1028
 
 
1029
            pabyDithered = (unsigned char *) malloc(dst_xsize * dst_ysize);
 
1030
            if( pabyDithered == NULL )
 
1031
            {
 
1032
                msSetError(MS_MEMERR, "Allocating work image of size %dx%d failed.",
 
1033
                           "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize );
 
1034
                return -1;
 
1035
            }
 
1036
          
 
1037
            Dither24to8( pabyRaw1, pabyRaw2, pabyRaw3, pabyDithered,
 
1038
                         dst_xsize, dst_ysize, image->format->transparent, 
 
1039
                         map->imagecolor, rb->data.gd_img );
 
1040
 
 
1041
            k = 0;
 
1042
            for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
1043
            {
 
1044
                for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
 
1045
                {
 
1046
                    if( MS_VALID_COLOR( layer->offsite )
 
1047
                        && pabyRaw1[k] == layer->offsite.red
 
1048
                        && pabyRaw2[k] == layer->offsite.green
 
1049
                        && pabyRaw3[k] == layer->offsite.blue )
 
1050
                        continue;
 
1051
 
 
1052
                    if( bHaveRGBNoData 
 
1053
                        && pabyRaw1[k] == nNoData1 
 
1054
                        && pabyRaw2[k] == nNoData2 
 
1055
                        && pabyRaw3[k] == nNoData3 )
 
1056
                        continue;
 
1057
 
 
1058
                    if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 )
 
1059
                        continue;
 
1060
 
 
1061
                    rb->data.gd_img->pixels[i][j] = pabyDithered[k];
 
1062
                }
 
1063
            }
 
1064
          
 
1065
            free( pabyDithered );
889
1066
#else
890
 
          msSetError( MS_IMGERR, 
891
 
                      "DITHER not supported in this build.  Update to latest GDAL, and define the ENABLE_DITHER macro.", "drawGDAL()" );
892
 
          return -1;
 
1067
            msSetError( MS_IMGERR, 
 
1068
                        "DITHER not supported in this build.  Update to latest GDAL, and define the ENABLE_DITHER macro.", "drawGDAL()" );
 
1069
            return -1;
893
1070
#endif 
894
 
      }
895
 
 
896
 
      /* Color cubed 24bit to 8bit conversion. */
897
 
      else if( !truecolor )
898
 
      {
899
 
          k = 0;
900
 
          for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
901
 
          {
902
 
              for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
903
 
              {
904
 
                  int   cc_index;
905
 
                  
906
 
                  if( MS_VALID_COLOR( layer->offsite )
907
 
                      && pabyRaw1[k] == layer->offsite.red
908
 
                      && pabyRaw2[k] == layer->offsite.green
909
 
                      && pabyRaw3[k] == layer->offsite.blue )
910
 
                      continue;
911
 
                  
912
 
                  if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 )
913
 
                      continue;
914
 
 
915
 
                  cc_index= RGB_INDEX(pabyRaw1[k],pabyRaw2[k],pabyRaw3[k]);
916
 
                  gdImg->pixels[i][j] = anColorCube[cc_index];
917
 
              }
918
 
          }
919
 
      }
920
 
      else if( truecolor )
921
 
      {
922
 
          k = 0;
923
 
          for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
924
 
          {
925
 
              for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
926
 
              {
927
 
                  if( MS_VALID_COLOR( layer->offsite )
928
 
                      && pabyRaw1[k] == layer->offsite.red
929
 
                      && pabyRaw2[k] == layer->offsite.green
930
 
                      && pabyRaw3[k] == layer->offsite.blue )
931
 
                      continue;
932
 
                  
933
 
                  if( pabyRawAlpha == NULL || pabyRawAlpha[k] == 255 )
934
 
                  {
935
 
                      gdImg->tpixels[i][j] = 
936
 
                          gdTrueColor(pabyRaw1[k], pabyRaw2[k], pabyRaw3[k]);
937
 
                  }
938
 
                  else if( pabyRawAlpha[k] != 0 )
939
 
                  {
940
 
                      int gd_color;
941
 
                      int gd_alpha = 127 - (pabyRawAlpha[k] >> 1);
942
 
 
943
 
                      gd_color = gdTrueColorAlpha(
944
 
                          pabyRaw1[k], pabyRaw2[k], pabyRaw3[k], gd_alpha );
945
 
 
946
 
                      /* NOTE: GD versions prior to 2.0.12 didn't take
947
 
                         the source alpha into account at all */
948
 
 
949
 
                      gdImg->tpixels[i][j] = 
950
 
                          msAlphaBlend( gdImg->tpixels[i][j], gd_color );
951
 
                  }
952
 
              }
953
 
          }
954
 
      }
955
 
  }
956
 
 
957
 
  /*
958
 
  ** Cleanup
959
 
  */
960
 
 
961
 
  free( pabyRaw1 );
962
 
 
963
 
  if( hColorMap != NULL )
964
 
      GDALDestroyColorTable( hColorMap );
965
 
 
966
 
  return 0;
 
1071
        }
 
1072
 
 
1073
        /* Color cubed 24bit to 8bit conversion. */
 
1074
        else if( rb->type == MS_BUFFER_GD )
 
1075
        {
 
1076
            k = 0;
 
1077
            for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ )
 
1078
            {
 
1079
                for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ )
 
1080
                {
 
1081
                    int cc_index;
 
1082
                  
 
1083
                    if( MS_VALID_COLOR( layer->offsite )
 
1084
                        && pabyRaw1[k] == layer->offsite.red
 
1085
                        && pabyRaw2[k] == layer->offsite.green
 
1086
                        && pabyRaw3[k] == layer->offsite.blue )
 
1087
                        continue;
 
1088
                  
 
1089
                    if( bHaveRGBNoData 
 
1090
                        && pabyRaw1[k] == nNoData1 
 
1091
                        && pabyRaw2[k] == nNoData2 
 
1092
                        && pabyRaw3[k] == nNoData3 )
 
1093
                        continue;
 
1094
 
 
1095
                    if( pabyRawAlpha != NULL && pabyRawAlpha[k] == 0 )
 
1096
                        continue;
 
1097
 
 
1098
                    cc_index= RGB_INDEX(pabyRaw1[k],pabyRaw2[k],pabyRaw3[k]);
 
1099
                    rb->data.gd_img->pixels[i][j] = anColorCube[cc_index];
 
1100
                }
 
1101
            }
 
1102
        }
 
1103
        else {
 
1104
            msSetError(MS_MISCERR,"Unsupported raster configuration","msDrawRasterLayerGDAL()");
 
1105
            return MS_FAILURE;
 
1106
        }
 
1107
    }
 
1108
 
 
1109
    /*
 
1110
    ** Cleanup
 
1111
    */
 
1112
 
 
1113
    free( pabyRaw1 );
 
1114
 
 
1115
    if( hColorMap != NULL )
 
1116
        GDALDestroyColorTable( hColorMap );
 
1117
 
 
1118
    return 0;
967
1119
}
968
1120
 
969
1121
/************************************************************************/
1078
1230
        if( atoi(tokens[i*2]) >= 0 )
1079
1231
        {
1080
1232
            if( count++ > 0 )
1081
 
                strcat( wrkLUTDef, "," );
 
1233
                strlcat( wrkLUTDef, ",", sizeof(wrkLUTDef));
1082
1234
 
1083
 
            sprintf( wrkLUTDef + strlen(wrkLUTDef), "%s:%s",
1084
 
                     tokens[i*2], tokens[i*2+1] );
 
1235
            snprintf( wrkLUTDef + strlen(wrkLUTDef), sizeof(wrkLUTDef)-strlen(wrkLUTDef), 
 
1236
                      "%s:%s", tokens[i*2], tokens[i*2+1] );
1085
1237
        }
1086
1238
    }
1087
1239
 
1179
1331
        {
1180
1332
            msSetError(MS_IOERR, 
1181
1333
                       "Failed to open LUT file '%s'.",
1182
 
                       path,
1183
 
                       "drawGDAL()");
 
1334
                       "drawGDAL()", path );
1184
1335
            return -1;
1185
1336
        }
1186
1337
        
1191
1342
        {
1192
1343
            msSetError(MS_IOERR, 
1193
1344
                       "LUT definition from file %s longer than maximum buffer size (%d bytes).",
1194
 
                       path, sizeof(lut_def_fromfile),
1195
 
                       "drawGDAL()");
 
1345
                       "drawGDAL()", 
 
1346
                       path, sizeof(lut_def_fromfile) );
1196
1347
            return -1;
1197
1348
        }
1198
1349
        
1238
1389
                layerObj *layer, 
1239
1390
                int src_xoff, int src_yoff, int src_xsize, int src_ysize, 
1240
1391
                GByte *pabyWholeBuffer,
1241
 
                int dst_xsize, int dst_ysize )
 
1392
                int dst_xsize, int dst_ysize,
 
1393
                int *pbHaveRGBNoData, 
 
1394
                int *pnNoData1, int *pnNoData2, int *pnNoData3 )
1242
1395
    
1243
1396
{
1244
1397
    int    iColorIndex, result_code=0;
1246
1399
    float *pafWholeRawData;
1247
1400
 
1248
1401
/* -------------------------------------------------------------------- */
 
1402
/*      If we have no alpha band, but we do have three input            */
 
1403
/*      bands, then check for nodata values.  If we only have one       */
 
1404
/*      input band, then nodata will already have been adderssed as     */
 
1405
/*      part of the real or manufactured color table.                   */
 
1406
/* -------------------------------------------------------------------- */
 
1407
    if( band_count == 3 )
 
1408
    {
 
1409
        *pnNoData1 = (int) 
 
1410
            msGetGDALNoDataValue( layer, 
 
1411
                                  GDALGetRasterBand(hDS,band_numbers[0]), 
 
1412
                                  pbHaveRGBNoData);
 
1413
 
 
1414
        if( *pbHaveRGBNoData )
 
1415
            *pnNoData2 = (int) 
 
1416
                msGetGDALNoDataValue( layer, 
 
1417
                                  GDALGetRasterBand(hDS,band_numbers[1]), 
 
1418
                                  pbHaveRGBNoData);
 
1419
        if( *pbHaveRGBNoData )
 
1420
            *pnNoData3 = (int) 
 
1421
                msGetGDALNoDataValue( layer, 
 
1422
                                  GDALGetRasterBand(hDS,band_numbers[2]), 
 
1423
                                  pbHaveRGBNoData);
 
1424
    }
 
1425
 
 
1426
/* -------------------------------------------------------------------- */
1249
1427
/*      Are we doing a simple, non-scaling case?  If so, read directly  */
1250
1428
/*      and return.                                                     */
1251
1429
/* -------------------------------------------------------------------- */
1264
1442
 
1265
1443
        if( eErr != CE_None )
1266
1444
        {
1267
 
            msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", 
1268
 
                        CPLGetLastErrorMsg(), "drawGDAL()" );
 
1445
            msSetError( MS_IOERR, 
 
1446
                        "GDALDatasetRasterIO() failed: %s", 
 
1447
                        "drawGDAL()",
 
1448
                        CPLGetLastErrorMsg() );
1269
1449
            return -1;
1270
1450
        }
1271
1451
 
1282
1462
    }
1283
1463
 
1284
1464
/* -------------------------------------------------------------------- */
 
1465
/*      Disable use of nodata if we are doing scaling.                  */
 
1466
/* -------------------------------------------------------------------- */
 
1467
    *pbHaveRGBNoData = FALSE;
 
1468
 
 
1469
/* -------------------------------------------------------------------- */
1285
1470
/*      We need to do some scaling.  Will load into either a 16bit      */
1286
1471
/*      unsigned or a floating point buffer depending on the source     */
1287
1472
/*      data.  We offer a special case for 16U data because it is       */
1316
1501
    if( eErr != CE_None )
1317
1502
    {
1318
1503
        msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", 
1319
 
                    CPLGetLastErrorMsg(), "drawGDAL()" );
 
1504
                    "drawGDAL()",
 
1505
                    CPLGetLastErrorMsg() );
1320
1506
        
1321
1507
        free( pafWholeRawData );
1322
1508
        return -1;
1359
1545
                free( pafWholeRawData );
1360
1546
                msSetError( MS_MISCERR, 
1361
1547
                            "SCALE PROCESSING option unparsable for layer %s.",
1362
 
                            layer->name, 
1363
 
                            "msDrawGDAL()" );
 
1548
                            "msDrawGDAL()",
 
1549
                            layer->name );
1364
1550
                return -1;
1365
1551
            }
1366
1552
            else
1378
1564
/* -------------------------------------------------------------------- */
1379
1565
        pafRawData = pafWholeRawData + iColorIndex * dst_xsize * dst_ysize;
1380
1566
 
 
1567
        dfNoDataValue = msGetGDALNoDataValue( layer, hBand, &bGotNoData );
 
1568
 
1381
1569
        if( dfScaleMin == dfScaleMax )
1382
1570
        {
1383
 
            dfScaleMin = dfScaleMax = pafRawData[0];
1384
 
            
1385
 
            for( i = 1; i < nPixelCount; i++ )
 
1571
            int bMinMaxSet = 0;
 
1572
            
 
1573
            /* we force assignment to a float rather than letting pafRawData[i]
 
1574
               get promoted to double later to avoid float precision issues. */
 
1575
            float fNoDataValue = (float) dfNoDataValue; 
 
1576
 
 
1577
            for( i = 0; i < nPixelCount; i++ )
1386
1578
            {
 
1579
                if( bGotNoData && pafRawData[i] == fNoDataValue )
 
1580
                    continue;
 
1581
 
 
1582
                if( !bMinMaxSet )
 
1583
                {
 
1584
                    dfScaleMin = dfScaleMax = pafRawData[i];
 
1585
                    bMinMaxSet = TRUE;
 
1586
                }
 
1587
 
1387
1588
                dfScaleMin = MIN(dfScaleMin,pafRawData[i]);
1388
1589
                dfScaleMax = MAX(dfScaleMax,pafRawData[i]);
1389
1590
            }
 
1591
 
1390
1592
            if( dfScaleMin == dfScaleMax )
1391
1593
                dfScaleMax = dfScaleMin + 1.0;
1392
1594
        }
1418
1620
/*      unable to utilize it since we can't return any pixels marked    */
1419
1621
/*      as nodata from this function.  Need to fix someday.             */
1420
1622
/* -------------------------------------------------------------------- */
1421
 
        dfNoDataValue = msGetGDALNoDataValue( layer, hBand, &bGotNoData );
1422
1623
        if( bGotNoData )
1423
1624
            msDebug( "LoadGDALImage(%s): NODATA value %g in GDAL\n"
1424
 
                     "file or PROCESSING directive ignored.  Not yet supported for\n"
1425
 
                     "unclassified scaled data.\n",
 
1625
                     "file or PROCESSING directive largely ignored.  Not yet fully supported for\n"
 
1626
                     "unclassified scaled data.  The NODATA value is excluded from auto-scaling\n"
 
1627
                     "min/max computation, but will not be transparent.\n",
1426
1628
                     layer->name, dfNoDataValue );
1427
1629
        
1428
1630
/* -------------------------------------------------------------------- */
1771
1973
    int *band_list, band_count;
1772
1974
    int  i, j, k, band;
1773
1975
    CPLErr eErr;
 
1976
    float *f_nodatas = NULL;
 
1977
    unsigned char *b_nodatas = NULL;
 
1978
    GInt16 *i_nodatas = NULL;
 
1979
    int got_nodata=FALSE;
1774
1980
 
1775
1981
    if( image->format->bands > 256 )
1776
1982
    {
1780
1986
    }
1781
1987
 
1782
1988
/* -------------------------------------------------------------------- */
 
1989
/*      We need at least GDAL 1.2.0 for the DatasetRasterIO             */
 
1990
/*      function.                                                       */
 
1991
/* -------------------------------------------------------------------- */
 
1992
#if !defined(GDAL_VERSION_NUM) || GDAL_VERSION_NUM < 1200
 
1993
    msSetError(MS_IMGERR, 
 
1994
               "RAWMODE raster support requires GDAL 1.2.0 or newer.", 
 
1995
               "msDrawRasterLayerGDAL_RawMode()" );
 
1996
    free( pBuffer );
 
1997
    return -1;
 
1998
#endif
 
1999
 
 
2000
/* -------------------------------------------------------------------- */
1783
2001
/*      What data type do we need?                                      */
1784
2002
/* -------------------------------------------------------------------- */
1785
2003
    if( image->format->imagemode == MS_IMAGEMODE_INT16 )
1809
2027
    }
1810
2028
 
1811
2029
/* -------------------------------------------------------------------- */
 
2030
/*      Do we have nodata values?                                       */
 
2031
/* -------------------------------------------------------------------- */
 
2032
    f_nodatas = (float *) calloc(sizeof(float),band_count);
 
2033
    if (f_nodatas == NULL) 
 
2034
    {
 
2035
        msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawRasterLayerGDAL_RawMode()",
 
2036
                   __FILE__, __LINE__, sizeof(float)*band_count); 
 
2037
        free( band_list );
 
2038
        return -1;
 
2039
    }
 
2040
 
 
2041
    if( band_count <= 3
 
2042
        && (layer->offsite.red != -1
 
2043
            || layer->offsite.green != -1
 
2044
            || layer->offsite.blue != -1) )
 
2045
    {
 
2046
        if( band_count > 0 )
 
2047
            f_nodatas[0] = layer->offsite.red;
 
2048
        if( band_count > 1 )
 
2049
            f_nodatas[1] = layer->offsite.green;
 
2050
        if( band_count > 2 )
 
2051
            f_nodatas[2] = layer->offsite.blue;
 
2052
        got_nodata = TRUE;
 
2053
    }
 
2054
 
 
2055
    if( !got_nodata )
 
2056
    {
 
2057
        got_nodata = TRUE;
 
2058
        for( band = 0; band < band_count && got_nodata; band++ )
 
2059
        {
 
2060
            f_nodatas[band] = msGetGDALNoDataValue( 
 
2061
                layer, GDALGetRasterBand(hDS,band_list[band]), &got_nodata );
 
2062
        }
 
2063
    }
 
2064
    
 
2065
    if( !got_nodata )
 
2066
    {
 
2067
        msFree( f_nodatas );
 
2068
        f_nodatas = NULL;
 
2069
    }
 
2070
    else if( eDataType == GDT_Byte )
 
2071
    {
 
2072
        b_nodatas = (unsigned char *) f_nodatas;
 
2073
        for( band = 0; band < band_count; band++ )
 
2074
            b_nodatas[band] = (unsigned char) f_nodatas[band];
 
2075
    }
 
2076
    else if( eDataType == GDT_Int16 )
 
2077
    {
 
2078
        i_nodatas = (GInt16 *) f_nodatas;
 
2079
        for( band = 0; band < band_count; band++ )
 
2080
            i_nodatas[band] = (GInt16) f_nodatas[band];
 
2081
    }
 
2082
 
 
2083
/* -------------------------------------------------------------------- */
1812
2084
/*      Allocate buffer, and read data into it.                         */
1813
2085
/* -------------------------------------------------------------------- */
1814
2086
    pBuffer = malloc(dst_xsize * dst_ysize * image->format->bands
1821
2093
        return -1;
1822
2094
    }
1823
2095
 
1824
 
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1199
1825
2096
    eErr = GDALDatasetRasterIO( hDS, GF_Read,  
1826
2097
                                src_xoff, src_yoff, src_xsize, src_ysize, 
1827
2098
                                pBuffer, dst_xsize, dst_ysize, eDataType, 
1832
2103
    if( eErr != CE_None )
1833
2104
    {
1834
2105
        msSetError( MS_IOERR, "GDALRasterIO() failed: %s", 
1835
 
                    CPLGetLastErrorMsg(), 
1836
 
                    "msDrawRasterLayerGDAL_RawMode()" );
 
2106
                    "msDrawRasterLayerGDAL_RawMode()", CPLGetLastErrorMsg() );
1837
2107
        free( pBuffer );
 
2108
        free( f_nodatas );
1838
2109
        return -1;
1839
2110
    }
1840
 
#else
1841
 
    /*
1842
 
     * The above could actually be implemented for pre-1.2.0 GDALs
1843
 
     * reading band by band, but it would be hard to do and test and would
1844
 
     * be very rarely useful so we skip it.
1845
 
     */
1846
 
    msSetError(MS_IMGERR, 
1847
 
               "RAWMODE raster support requires GDAL 1.2.0 or newer.", 
1848
 
               "msDrawRasterLayerGDAL_RawMode()" );
1849
 
    free( pBuffer );
1850
 
    return -1;
1851
 
#endif
1852
2111
 
1853
2112
/* -------------------------------------------------------------------- */
1854
2113
/*      Transfer the data to the imageObj.                              */
1862
2121
            {
1863
2122
                for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
1864
2123
                {
1865
 
                    image->img.raw_16bit[j + i * image->width
1866
 
                                         + band*image->width*image->height] = 
1867
 
                        ((GInt16 *) pBuffer)[k++];
 
2124
                    int off = j + i * image->width
 
2125
                        + band*image->width*image->height;
 
2126
                    int off_mask = j + i * image->width;
 
2127
 
 
2128
                    if( i_nodatas 
 
2129
                        && ((GInt16 *) pBuffer)[k] == i_nodatas[band] )
 
2130
                    {
 
2131
                        k++;
 
2132
                        continue;
 
2133
                    }
 
2134
 
 
2135
                    image->img.raw_16bit[off] = ((GInt16 *) pBuffer)[k++];
 
2136
                    MS_SET_BIT(image->img_mask,off_mask);
1868
2137
                }
1869
2138
            }
1870
2139
            else if( image->format->imagemode == MS_IMAGEMODE_FLOAT32 )
1871
2140
            {
1872
2141
                for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
1873
2142
                {
1874
 
                    image->img.raw_float[j + i * image->width
1875
 
                                         + band*image->width*image->height] = 
1876
 
                        ((float *) pBuffer)[k++];
 
2143
                    int off = j + i * image->width
 
2144
                        + band*image->width*image->height;
 
2145
                    int off_mask = j + i * image->width;
 
2146
 
 
2147
                    if( f_nodatas 
 
2148
                        && ((float *) pBuffer)[k] == f_nodatas[band] )
 
2149
                    {
 
2150
                        k++;
 
2151
                        continue;
 
2152
                    }
 
2153
 
 
2154
                    image->img.raw_float[off] = ((float *) pBuffer)[k++];
 
2155
                    MS_SET_BIT(image->img_mask,off_mask);
1877
2156
                }
1878
2157
            }
1879
2158
            else if( image->format->imagemode == MS_IMAGEMODE_BYTE )
1880
2159
            {
1881
2160
                for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ )
1882
2161
                {
1883
 
                    image->img.raw_byte[j + i * image->width
1884
 
                                        + band*image->width*image->height] = 
1885
 
                        ((unsigned char *) pBuffer)[k++];
 
2162
                    int off = j + i * image->width
 
2163
                        + band*image->width*image->height;
 
2164
                    int off_mask = j + i * image->width;
 
2165
 
 
2166
                    if( b_nodatas 
 
2167
                        && ((unsigned char *) pBuffer)[k] == b_nodatas[band] )
 
2168
                    {
 
2169
                        k++;
 
2170
                        continue;
 
2171
                    }
 
2172
 
 
2173
                    image->img.raw_byte[off] = ((unsigned char *) pBuffer)[k++];
 
2174
                    MS_SET_BIT(image->img_mask,off_mask);
1886
2175
                }
1887
2176
            }
1888
2177
        }
1907
2196
 
1908
2197
static int 
1909
2198
msDrawRasterLayerGDAL_16BitClassification(
1910
 
    mapObj *map, layerObj *layer, imageObj *image, 
 
2199
    mapObj *map, layerObj *layer, rasterBufferObj *rb,
1911
2200
    GDALDatasetH hDS, GDALRasterBandH hBand,
1912
2201
    int src_xoff, int src_yoff, int src_xsize, int src_ysize,
1913
2202
    int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize )
1922
2211
    const char *pszBuckets;
1923
2212
    int  bUseIntegers = FALSE;
1924
2213
    int  *cmap, c, j, k, bGotNoData = FALSE, bGotFirstValue;
1925
 
    gdImagePtr gdImg = image->img.gd;
 
2214
    unsigned char *rb_cmap[4];
1926
2215
    CPLErr eErr;
1927
2216
 
1928
 
    assert( gdImg != NULL );
 
2217
    assert( rb->type == MS_BUFFER_GD || rb->type == MS_BUFFER_BYTE_RGBA );
1929
2218
 
1930
2219
/* ==================================================================== */
1931
2220
/*      Read the requested data in one gulp into a floating point       */
2003
2292
            free( pafRawData );
2004
2293
            msSetError( MS_MISCERR, 
2005
2294
                        "SCALE PROCESSING option unparsable for layer %s.",
2006
 
                        layer->name, 
2007
 
                        "msDrawGDAL()" );
 
2295
                        "msDrawGDAL()",
 
2296
                        layer->name );
2008
2297
            return -1;
2009
2298
        }
2010
2299
        else
2063
2352
            free( pafRawData );
2064
2353
            msSetError( MS_MISCERR, 
2065
2354
                        "SCALE_BUCKETS PROCESSING option is not a value of 2 or more: %s.",
2066
 
                        pszBuckets, 
2067
 
                        "msDrawRasterLayerGDAL_16BitClassification()" );
 
2355
                        "msDrawRasterLayerGDAL_16BitClassification()",
 
2356
                        pszBuckets );
2068
2357
            return -1;
2069
2358
        }
2070
2359
    }
2086
2375
/*      Compute classification lookup table.                            */
2087
2376
/* ==================================================================== */
2088
2377
 
2089
 
    cmap = (int *) calloc(sizeof(int),nBucketCount);
 
2378
    cmap = (int *) msSmallCalloc(sizeof(int),nBucketCount);
 
2379
    rb_cmap[0] = (unsigned char *) msSmallCalloc(1,nBucketCount);
 
2380
    rb_cmap[1] = (unsigned char *) msSmallCalloc(1,nBucketCount);
 
2381
    rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount);
 
2382
    rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount);
2090
2383
 
2091
2384
    for(i=0; i < nBucketCount; i++) 
2092
2385
    {
2096
2389
 
2097
2390
        dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin;
2098
2391
            
2099
 
        c = msGetClass_Float(layer, (float) dfOriginalValue);
 
2392
        c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1);
2100
2393
        if( c != -1 )
2101
2394
        {
2102
2395
            int s;
2108
2401
                    && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) )
2109
2402
                    msValueToRange(layer->class[c]->styles[s],dfOriginalValue);
2110
2403
            }
2111
 
 
2112
 
            RESOLVE_PEN_GD(gdImg, layer->class[c]->styles[0]->color);
2113
 
            if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) )
2114
 
                cmap[i] = -1;
2115
 
            else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
 
2404
            if(rb->type == MS_BUFFER_GD) {
 
2405
                RESOLVE_PEN_GD(rb->data.gd_img, layer->class[c]->styles[0]->color);
 
2406
                if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) )
 
2407
                    cmap[i] = -1;
 
2408
                else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
 
2409
                {
 
2410
                    /* use class color */
 
2411
                    cmap[i] = layer->class[c]->styles[0]->color.pen;
 
2412
                }
 
2413
            }
 
2414
            else if( rb->type == MS_BUFFER_BYTE_RGBA )
2116
2415
            {
2117
 
                /* use class color */
2118
 
                cmap[i] = layer->class[c]->styles[0]->color.pen;
 
2416
                if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) )
 
2417
                {
 
2418
                    /* leave it transparent */
 
2419
                }
 
2420
                else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color))
 
2421
                {
 
2422
                    /* use class color */
 
2423
                    rb_cmap[0][i] = layer->class[c]->styles[0]->color.red;
 
2424
                    rb_cmap[1][i] = layer->class[c]->styles[0]->color.green;
 
2425
                    rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue;
 
2426
                    rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100);
 
2427
                }
2119
2428
            }
2120
2429
        }
2121
2430
    }
2153
2462
                continue;
2154
2463
            }
2155
2464
 
2156
 
            result = cmap[iMapIndex];
2157
 
            if( result == -1 )
2158
 
                continue;
 
2465
            if( rb->type == MS_BUFFER_GD )
 
2466
            {
 
2467
                result = cmap[iMapIndex];
 
2468
                if( result == -1 )
 
2469
                    continue;
2159
2470
 
2160
 
            if( gdImageTrueColor( gdImg ) )
2161
 
                gdImg->tpixels[i][j] = result;
2162
 
            else
2163
 
                gdImg->pixels[i][j] = result;
 
2471
                rb->data.gd_img->pixels[i][j] = result;
 
2472
            }
 
2473
            else if( rb->type == MS_BUFFER_BYTE_RGBA )
 
2474
            {
 
2475
                /* currently we never have partial alpha so keep simple */
 
2476
                if( rb_cmap[3][iMapIndex] > 0 )
 
2477
                    RB_SET_PIXEL( rb, j, i, 
 
2478
                                  rb_cmap[0][iMapIndex], 
 
2479
                                  rb_cmap[1][iMapIndex], 
 
2480
                                  rb_cmap[2][iMapIndex], 
 
2481
                                  rb_cmap[3][iMapIndex] );
 
2482
            }
2164
2483
        }
2165
2484
    }
2166
2485
 
 
2486
/* -------------------------------------------------------------------- */
 
2487
/*      Cleanup                                                         */
 
2488
/* -------------------------------------------------------------------- */
2167
2489
    free( pafRawData );
2168
2490
    free( cmap );
 
2491
    free( rb_cmap[0] );
 
2492
    free( rb_cmap[1] );
 
2493
    free( rb_cmap[2] );
 
2494
    free( rb_cmap[3] );
2169
2495
 
2170
2496
    assert( k == dst_xsize * dst_ysize );
2171
2497
 
2246
2572
            *band_count = file_bands;
2247
2573
 
2248
2574
        band_list = (int *) malloc(sizeof(int) * *band_count );
 
2575
        MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL);
 
2576
 
2249
2577
        for( i = 0; i < *band_count; i++ )
2250
2578
            band_list[i] = i+1;
2251
2579
        return band_list;
2277
2605
 
2278
2606
        *band_count = CSLCount(papszItems);
2279
2607
        band_list = (int *) malloc(sizeof(int) * *band_count);
 
2608
        MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL);
2280
2609
 
2281
2610
        for( i = 0; i < *band_count; i++ )
2282
2611
        {