mapoutput.c
上传用户:renmgy007
上传日期:2013-06-15
资源大小:1526k
文件大小:35k
源码类别:

GPS编程

开发平台:

C/C++

  1. /******************************************************************************
  2.  *
  3.  * Project:  MapServer
  4.  * Purpose:  Various support code related to the outputFormatObj.
  5.  * Author:   Frank Warmerdam, warmerdam@pobox.com
  6.  *
  7.  ******************************************************************************
  8.  * Copyright (c) 2002, Frank Warmerdam
  9.  *
  10.  * Permission is hereby granted, free of charge, to any person obtaining a
  11.  * copy of this software and associated documentation files (the "Software"),
  12.  * to deal in the Software without restriction, including without limitation
  13.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14.  * and/or sell copies of the Software, and to permit persons to whom the
  15.  * Software is furnished to do so, subject to the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice shall be included
  18.  * in all copies or substantial portions of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  23.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26.  * DEALINGS IN THE SOFTWARE.
  27.  ******************************************************************************
  28.  *
  29.  * $Log: mapoutput.c,v $
  30.  * Revision 1.35  2005/11/10 15:41:16  frank
  31.  * Added missing function header.
  32.  *
  33.  * Revision 1.34  2005/04/07 17:23:16  assefa
  34.  * Remove #ifdef USE_SVG. It was added during development.
  35.  *
  36.  * Revision 1.33  2005/03/08 19:53:25  frank
  37.  * adjusted png24 mimetype per bug 1231
  38.  *
  39.  * Revision 1.32  2005/02/08 21:36:23  frank
  40.  * Return actual error code.
  41.  *
  42.  * Revision 1.31  2005/02/03 00:06:57  assefa
  43.  * Add SVG function prototypes and related calls.
  44.  *
  45.  * Revision 1.30  2004/11/18 20:55:38  frank
  46.  * In msOutputFormatValidate() we now ensure that GD/JPEG does not have
  47.  * alpha enabled, or transparent turned on.   Bug 1073.
  48.  *
  49.  * Revision 1.29  2004/11/18 19:27:16  frank
  50.  * Fixed formatting of debug message.
  51.  *
  52.  * Revision 1.28  2004/11/17 23:53:07  assefa
  53.  * Advertize only gd and gdal formats for wms capabilities (Bug 455).
  54.  *
  55.  * Revision 1.27  2004/11/05 23:04:50  assefa
  56.  * Change a bit test in function msGetOutputFormatMimeListGD.
  57.  *
  58.  * Revision 1.26  2004/11/05 16:29:40  assefa
  59.  * add function msGetOutputFormatMimeListGD.
  60.  *
  61.  * Revision 1.25  2004/10/21 04:30:54  frank
  62.  * Added standardized headers.  Added MS_CVSID().
  63.  *
  64.  * Revision 1.24  2004/10/20 20:46:51  frank
  65.  * msOutputFormatValidate() now also fixes stuff up including setting
  66.  * imagemode to MS_RENDER_WITH_RAWDATA if appropriate, and setting
  67.  * imagemode to MS_IMAGEMODE_RGBA from RGB if transparent enabled.
  68.  * See Bugs 724 and 425/977.
  69.  *
  70.  * Revision 1.23  2004/04/23 16:44:54  frank
  71.  * msRemoteOutputFormat() now frees output formats if refcount==0
  72.  *
  73.  * Revision 1.22  2004/03/08 04:28:46  sean
  74.  * New functions to support mapscript interface to outputformatlist
  75.  *
  76.  * Revision 1.21  2004/03/05 05:57:04  frank
  77.  * support multi-band rawmode output
  78.  *
  79.  * Revision 1.20  2003/07/08 12:36:11  frank
  80.  * don't crash if format==NULL
  81.  *
  82.  * Revision 1.19  2003/07/03 03:01:58  assefa
  83.  * Add support for saving the output formats.
  84.  *
  85.  * Revision 1.18  2003/03/14 13:12:11  attila
  86.  * Introduce MySQL generic support, enabled with --with-mygis when configuring
  87.  *
  88.  * Revision 1.17  2003/02/20 19:49:14  frank
  89.  * fixed implicit setting of JPEG quality from IMAGEQUALITY keyword
  90.  *
  91.  * Revision 1.16  2003/01/17 15:47:48  frank
  92.  * ensure that msApplyDefaultOutputFormats() does not modify map->imagetype
  93.  *
  94.  * Revision 1.15  2003/01/11 23:25:48  frank
  95.  * Bug 249: msApplyOutputFormat() will switch imagemode from RGB to RGBA if
  96.  * transparency is requested.
  97.  * Added msOutputFormatValidate() function.
  98.  *
  99.  * Revision 1.14  2003/01/11 17:32:27  frank
  100.  * When GD2 isn't available create a PC256 mode JPEG driver by default
  101.  *
  102.  * Revision 1.13  2002/12/21 22:04:54  frank
  103.  * I regressed the changes Julien made, and reimplemented the same effect
  104.  * with the logic in msApplyDefaultOutputFormats().  Should be much safer now.
  105.  *
  106.  * Revision 1.11  2002/12/17 23:02:19  dan
  107.  * I assigned the wrong value to map->imagetype.  Duh!
  108.  *
  109.  * Revision 1.10  2002/12/17 22:52:43  dan
  110.  * Update value of map->imagetype in msSelectOutputFormat()
  111.  *
  112.  * Revision 1.9  2002/12/17 22:04:58  dan
  113.  * Added PNG24 to the list of default output formats with GD2
  114.  *
  115.  * Revision 1.8  2002/11/19 14:38:39  frank
  116.  * fixed bug in msApplyOutputFormat with transparent override
  117.  *
  118.  * Revision 1.7  2002/11/19 05:47:37  frank
  119.  * cleanup memory leak
  120.  *
  121.  * Revision 1.6  2002/10/05 16:32:40  zak
  122.  * updated e-mail address
  123.  *
  124.  * Revision 1.5  2002/10/04 21:15:59  assefa
  125.  * Add PDF support using the new output architecture. Work done
  126.  * by Zak James (zak-ms@aiya.dhs.org).
  127.  *
  128.  * Revision 1.4  2002/06/21 18:29:45  frank
  129.  * Added support for GD/PC256 as a pseudo-driver
  130.  *
  131.  * Revision 1.3  2002/06/13 19:56:15  frank
  132.  * don't automatically emit Imagine format support
  133.  *
  134.  * Revision 1.2  2002/06/11 20:45:22  frank
  135.  * add renderer copy to output format clone function
  136.  *
  137.  * Revision 1.1  2002/06/11 13:49:52  frank
  138.  * New
  139.  *
  140.  */
  141. #include <assert.h>
  142. #include "map.h"
  143. MS_CVSID("$Id: mapoutput.c,v 1.35 2005/11/10 15:41:16 frank Exp $")
  144. static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, 
  145.                                              const char *driver );
  146. /*************************************************************************
  147. NOTES on outputFormatObj:
  148. typedef struct {
  149.   char *name;
  150.   char *mimetype;
  151.   char *driver;
  152.   int  imagemode; // MS_IMAGEMODE_* value.
  153.   int  transparent;
  154.   int  numformatoptions;
  155.   char **formatoptions;
  156. } outputFormatObj;
  157.  NAME - Associates an internal name with the declaration.  The value used
  158.         has not intrinsic meaning and is just used to associate with the
  159.         MAP level IMAGETYPE.  It is also the "name" used for the format
  160.         in WMS capabilities documents, and FORMAT= requests. (required)
  161.  MIMETYPE - The mime type to use for this format.  If omitted, the value
  162.             will be derived from the DRIVER or default to the value for
  163.             untyped binary data will be used.  (optional - may be NULL)
  164.  DRIVER - This indicates which internal driver mechanism is to be used. 
  165.           Anything prefixed by "GDAL/" will be handled by the GDAL driver, with
  166.           the remainder taken as the GDAL format name. (required)
  167.  IMAGEMODE - Has one of "PC256", "RGB", or "RGBA" indicating whether
  168.              the imaging should be done to a 256 pseudo-colored, 24bit RGB, or
  169.              32bit RGBA (A=alpha/transparency) result image.  Note that the 
  170.              IMAGEMODE actually affects how all the rendering for the map is 
  171.              done, long before it is output to a particular output format.  
  172.              The default value is the traditional "PC256".  Some output 
  173.              formats can only support some IMAGEMODE values. (optional)
  174.              Translate as MS_IMAGEMODE_PC256, MS_IMAGEMODE_RGB and 
  175.              MS_IMAGEMODE_RGBA. 
  176.              Not too sure what this should be set to for output formats like
  177.              flash and SVG.
  178.  TRANSPARENT - A value of "ON" or "OFF" indicating whether transparency 
  179.                support should be enabled.  Same as the old TRANSPARENT flag
  180.                at the MAP level.
  181.  FORMATOPTION - Contains an argument for the specific driver used.  There may 
  182.                 be any number of format options for a given OUTPUTFORMAT 
  183.                 declaration.  FORMATOPTION will be used to encode the older
  184.                 INTERLACE, and QUALITY values. 
  185.                 Handled as a MapServer style CharArray.
  186.  *************************************************************************/
  187. /************************************************************************/
  188. /*                  msPostMapParseOutputFormatSetup()                   */
  189. /************************************************************************/
  190. int msPostMapParseOutputFormatSetup( mapObj *map )
  191. {
  192.     outputFormatObj *format;
  193.     /* Provide default output formats. */
  194.     msApplyDefaultOutputFormats( map );
  195.     /* default to the first of these if IMAGETYPE not set. */
  196.     if( map->imagetype == NULL && map->numoutputformats > 0 )
  197.         map->imagetype = strdup(map->outputformatlist[0]->name);
  198.     /* select the current outputformat into map->outputformat */
  199.     format = msSelectOutputFormat( map, map->imagetype );
  200.     if( format == NULL ) 
  201.     {
  202.         msSetError(MS_MISCERR, 
  203.                    "Unable to select IMAGETYPE `%s'.", 
  204.                    "msPostMapParseOutputFormatSetup()",
  205.                    map->imagetype ? map->imagetype : "(null)" );
  206.         return MS_FAILURE;
  207.     }
  208.     msApplyOutputFormat( &(map->outputformat), format, 
  209.                          map->transparent, map->interlace, map->imagequality );
  210.     return MS_SUCCESS;
  211. }
  212. /************************************************************************/
  213. /*                    msCreateDefaultOutputFormat()                     */
  214. /************************************************************************/
  215. outputFormatObj *msCreateDefaultOutputFormat( mapObj *map, 
  216.                                               const char *driver )
  217. {
  218.     outputFormatObj *format = NULL;
  219.     if( strcasecmp(driver,"GD/PC256") == 0 )
  220.     {
  221. #ifdef USE_GD_GIF
  222.         return msCreateDefaultOutputFormat( map, "GD/GIF" );
  223. #elif defined(USE_GD_PNG)
  224.         return msCreateDefaultOutputFormat( map, "GD/PNG" );
  225. #else
  226.         return NULL;
  227. #endif
  228.     }
  229. #ifdef USE_GD_GIF
  230.     if( strcasecmp(driver,"GD/GIF") == 0 )
  231.     {
  232.         format = msAllocOutputFormat( map, "gif", driver );
  233.         format->mimetype = strdup("image/gif");
  234.         format->imagemode = MS_IMAGEMODE_PC256;
  235.         format->extension = strdup("gif");
  236.         format->renderer = MS_RENDER_WITH_GD;
  237.     }
  238. #endif
  239. #ifdef USE_GD_PNG
  240.     if( strcasecmp(driver,"GD/PNG") == 0 )
  241.     {
  242.         format = msAllocOutputFormat( map, "png", driver );
  243.         format->mimetype = strdup("image/png");
  244.         format->imagemode = MS_IMAGEMODE_PC256;
  245.         format->extension = strdup("png");
  246.         format->renderer = MS_RENDER_WITH_GD;
  247.     }
  248. #endif /* USE_GD_PNG */
  249. #if defined(USE_GD_PNG) && GD2_VERS > 1
  250.     if( strcasecmp(driver,"GD/PNG24") == 0 )
  251.     {
  252.         format = msAllocOutputFormat( map, "png24", "GD/PNG" );
  253.         format->mimetype = strdup("image/png; mode=24bit");
  254.         format->imagemode = MS_IMAGEMODE_RGB;
  255.         format->extension = strdup("png");
  256.         format->renderer = MS_RENDER_WITH_GD;
  257.     }
  258. #endif /* USE_GD_PNG */
  259. #ifdef USE_GD_JPEG
  260.     if( strcasecmp(driver,"GD/JPEG") == 0 )
  261.     {
  262.         format = msAllocOutputFormat( map, "jpeg", driver );
  263.         format->mimetype = strdup("image/jpeg");
  264. #if GD2_VERS > 1
  265.         format->imagemode = MS_IMAGEMODE_RGB;
  266. #else
  267.         format->imagemode = MS_IMAGEMODE_PC256;
  268. #endif
  269.         format->extension = strdup("jpg");
  270.         format->renderer = MS_RENDER_WITH_GD;
  271.     }
  272. #endif
  273. #ifdef USE_GD_WBMP
  274.     if( strcasecmp(driver,"GD/WBMP") == 0 )
  275.     {
  276.         format = msAllocOutputFormat( map, "wbmp", driver );
  277.         format->mimetype = strdup("image/wbmp");
  278.         format->imagemode = MS_IMAGEMODE_PC256;
  279.         format->extension = strdup("wbmp");
  280.         format->renderer = MS_RENDER_WITH_GD;
  281.     }
  282. #endif
  283. #ifdef USE_MING_FLASH
  284.     if( strcasecmp(driver,"swf") == 0 )
  285.     {
  286.         format = msAllocOutputFormat( map, "swf", driver );
  287.         format->mimetype = strdup("application/x-shockwave-flash");
  288.         format->imagemode = MS_IMAGEMODE_PC256;
  289.         format->extension = strdup("swf");
  290.         format->renderer = MS_RENDER_WITH_SWF;
  291.     }
  292. #endif
  293. #ifdef USE_PDF
  294.     if( strcasecmp(driver,"pdf") == 0 )
  295.     {
  296.         format = msAllocOutputFormat( map, "pdf", driver );
  297.         format->mimetype = strdup("application/x-pdf");
  298.         format->imagemode = MS_IMAGEMODE_PC256;
  299.         format->extension = strdup("pdf");
  300.         format->renderer = MS_RENDER_WITH_PDF;
  301.     }
  302. #endif
  303. #ifdef USE_GDAL
  304.     if( strncasecmp(driver,"gdal/",5) == 0 )
  305.     {
  306.         format = msAllocOutputFormat( map, driver+5, driver );
  307.         if( msInitDefaultGDALOutputFormat( format ) == MS_FAILURE )
  308.         {
  309.             if( map != NULL )
  310.             {
  311.                 map->numoutputformats--;
  312.                 map->outputformatlist[map->numoutputformats] = NULL;
  313.             }
  314.             msFreeOutputFormat( format );
  315.             format = NULL;
  316.         }
  317.     }
  318. #endif
  319.     if( strcasecmp(driver,"imagemap") == 0 )
  320.     {
  321.         format = msAllocOutputFormat( map, "imagemap", driver );
  322.         format->mimetype = strdup("text/html");
  323.         format->extension = strdup("html");
  324.         format->imagemode = 0;
  325.         format->renderer = MS_RENDER_WITH_IMAGEMAP;
  326.     }
  327.     if( strcasecmp(driver,"svg") == 0 )
  328.     {
  329.         format = msAllocOutputFormat( map, "svg", driver );
  330.         format->mimetype = strdup("image/svg+xml");
  331.         format->imagemode = 0;
  332.         format->extension = strdup("svg");
  333.         format->renderer = MS_RENDER_WITH_SVG;
  334.     }
  335.     if( format != NULL )
  336.         format->inmapfile = MS_FALSE;
  337.     return format;
  338. }
  339. /************************************************************************/
  340. /*                    msApplyDefaultOutputFormats()                     */
  341. /************************************************************************/
  342. void msApplyDefaultOutputFormats( mapObj *map )
  343. {
  344.     char *saved_imagetype;
  345.     if( map->imagetype == NULL )
  346.         saved_imagetype = NULL;
  347.     else
  348.         saved_imagetype = strdup(map->imagetype);
  349.     if( msSelectOutputFormat( map, "gif" ) == NULL )
  350.         msCreateDefaultOutputFormat( map, "GD/GIF" );
  351.     if( msSelectOutputFormat( map, "png" ) == NULL )
  352.         msCreateDefaultOutputFormat( map, "GD/PNG" );
  353.     if( msSelectOutputFormat( map, "png24" ) == NULL )
  354.         msCreateDefaultOutputFormat( map, "GD/PNG24" );
  355.     if( msSelectOutputFormat( map, "jpeg" ) == NULL )
  356.         msCreateDefaultOutputFormat( map, "GD/JPEG" );
  357.     if( msSelectOutputFormat( map, "wbmp" ) == NULL )
  358.         msCreateDefaultOutputFormat( map, "GD/WBMP" );
  359.     if( msSelectOutputFormat( map, "swf" ) == NULL )
  360.         msCreateDefaultOutputFormat( map, "swf" );
  361.     if( msSelectOutputFormat( map, "imagemap" ) == NULL )
  362.         msCreateDefaultOutputFormat( map, "imagemap" );
  363.     if( msSelectOutputFormat( map, "pdf" ) == NULL )
  364.         msCreateDefaultOutputFormat( map, "pdf" );
  365.     if( msSelectOutputFormat( map, "GTiff" ) == NULL )
  366.         msCreateDefaultOutputFormat( map, "GDAL/GTiff" );
  367.     if( msSelectOutputFormat( map, "svg" ) == NULL )
  368.         msCreateDefaultOutputFormat( map, "svg" );
  369.     if( map->imagetype != NULL )
  370.         free( map->imagetype );
  371.     map->imagetype = saved_imagetype;
  372. }
  373. /************************************************************************/
  374. /*                         msFreeOutputFormat()                         */
  375. /************************************************************************/
  376. void msFreeOutputFormat( outputFormatObj *format )
  377. {
  378.     if( format == NULL )
  379.         return;
  380.     msFree( format->name );
  381.     msFree( format->mimetype );
  382.     msFree( format->driver );
  383.     msFree( format->extension );
  384.     msFreeCharArray( format->formatoptions, format->numformatoptions );
  385.     msFree( format );
  386. }
  387. /************************************************************************/
  388. /*                        msAllocOutputFormat()                         */
  389. /************************************************************************/
  390. static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, 
  391.                                              const char *driver )
  392. {
  393.     outputFormatObj *format;
  394. /* -------------------------------------------------------------------- */
  395. /*      Allocate the format object.                                     */
  396. /* -------------------------------------------------------------------- */
  397.     format = (outputFormatObj *) calloc(1,sizeof(outputFormatObj));
  398.     if( format == NULL )
  399.     {
  400.         msSetError( MS_MEMERR, NULL, "msAllocOutputFormat()" );
  401.         return NULL;
  402.     }
  403. /* -------------------------------------------------------------------- */
  404. /*      Initialize various fields.                                      */
  405. /* -------------------------------------------------------------------- */
  406.     format->bands = 1;
  407.     format->name = strdup(name);
  408.     format->driver = strdup(driver);
  409.     format->refcount = 0;
  410.     format->imagemode = MS_IMAGEMODE_PC256;
  411. /* -------------------------------------------------------------------- */
  412. /*      Attach to map.                                                  */
  413. /* -------------------------------------------------------------------- */
  414.     if( map != NULL )
  415.     {
  416.         map->numoutputformats++;
  417.         if( map->outputformatlist == NULL )
  418.             map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*));
  419.         else
  420.             map->outputformatlist = (outputFormatObj **)
  421.                 realloc(map->outputformatlist,
  422.                         sizeof(void*) * map->numoutputformats );
  423.         map->outputformatlist[map->numoutputformats-1] = format;
  424.         format->refcount++;
  425.     }
  426.     
  427.     return format;
  428. }
  429. /************************************************************************/
  430. /*                        msAppendOutputFormat()                        */
  431. /*                                                                      */
  432. /*      Add an output format  .                                         */
  433. /*      http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511           */
  434. /************************************************************************/
  435. int msAppendOutputFormat(mapObj *map, outputFormatObj *format) 
  436. {
  437. /* -------------------------------------------------------------------- */
  438. /*      Attach to map.                                                  */
  439. /* -------------------------------------------------------------------- */
  440.     if (map != NULL)
  441.     {
  442.         map->numoutputformats++;
  443.         if (map->outputformatlist == NULL)
  444.             map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*));
  445.         else
  446.             map->outputformatlist = (outputFormatObj **)
  447.                 realloc(map->outputformatlist,
  448.                         sizeof(void*) * map->numoutputformats );
  449.         map->outputformatlist[map->numoutputformats-1] = format;
  450.         format->refcount++;
  451.     }
  452.     
  453.     return map->numoutputformats;
  454. }
  455. /************************************************************************/
  456. /*                        msRemoveOutputFormat()                        */
  457. /*                                                                      */
  458. /*      Remove an output format (by name).                              */
  459. /*      http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511           */
  460. /************************************************************************/
  461. int msRemoveOutputFormat(mapObj *map, const char *name)
  462. {
  463.     int i, j;
  464. /* -------------------------------------------------------------------- */
  465. /*      Detach from map.                                                */
  466. /* -------------------------------------------------------------------- */
  467.     if (map != NULL)
  468.     {
  469.         if (map->outputformatlist == NULL)
  470.         {
  471.             msSetError(MS_CHILDERR, "Can't remove format from empty outputformatlist", "msRemoveOutputFormat()");
  472.             return MS_FAILURE;
  473.         }
  474.         else
  475.         {
  476.             i = msGetOutputFormatIndex(map, name);
  477.             if (i >= 0) 
  478.             {
  479.                 map->numoutputformats--;
  480.                 if( map->outputformatlist[i]->refcount-- < 1 )
  481.                     msFreeOutputFormat( map->outputformatlist[i] );
  482.                 for (j=i; j<map->numoutputformats-1; j++)
  483.                 {
  484.                     map->outputformatlist[j] = map->outputformatlist[j+1];
  485.                 }
  486.             }
  487.             map->outputformatlist = (outputFormatObj **)
  488.                 realloc(map->outputformatlist,
  489.                     sizeof(void*) * (map->numoutputformats) );
  490.             return MS_SUCCESS;
  491.         }
  492.     }
  493.     return MS_FAILURE;
  494. }
  495. /************************************************************************/
  496. /*                       msGetOutputFormatIndex()                       */
  497. /*                                                                      */
  498. /*      Pulled this out of msSelectOutputFormat for use in other cases. */
  499. /************************************************************************/
  500. int msGetOutputFormatIndex(mapObj *map, const char *imagetype)
  501. {
  502.     int i;
  503. /* -------------------------------------------------------------------- */
  504. /*      Try to find the format in the maps list of formats, first by    */
  505. /*      mime type, and then by output format name.                      */
  506. /* -------------------------------------------------------------------- */
  507.     for (i = 0; i < map->numoutputformats; i++)
  508.     {
  509.         if (map->outputformatlist[i]->mimetype != NULL
  510.             && strcasecmp(imagetype,
  511.                           map->outputformatlist[i]->mimetype) == 0 )
  512.             return i;
  513.     }
  514.     
  515.     for( i = 0; i < map->numoutputformats; i++ )
  516.     {
  517.         if( strcasecmp(imagetype,map->outputformatlist[i]->name) == 0 )
  518.             return i;
  519.     }
  520.     return -1;
  521. }
  522. /************************************************************************/
  523. /*                        msSelectOutputFormat()                        */
  524. /************************************************************************/
  525. outputFormatObj *msSelectOutputFormat( mapObj *map, 
  526.                                        const char *imagetype )
  527. {
  528.     int i, index;
  529.     outputFormatObj *format = NULL;
  530.     if( map == NULL || imagetype == NULL || strlen(imagetype) == 0 )
  531.         return NULL;
  532.     
  533.     index = msGetOutputFormatIndex(map, imagetype);
  534.     if (index >= 0)
  535.         format = map->outputformatlist[index];
  536. /* -------------------------------------------------------------------- */
  537. /*      Try to find the format in the maps list of formats, first by    */
  538. /*      mime type, and then by output format name.                      */
  539. /* -------------------------------------------------------------------- */
  540.     for( i = 0; i < map->numoutputformats && format == NULL; i++ )
  541.     {
  542.         if( map->outputformatlist[i]->mimetype != NULL
  543.             && strcasecmp(imagetype,
  544.                           map->outputformatlist[i]->mimetype) == 0 )
  545.             format = map->outputformatlist[i];
  546.     }
  547.     
  548.     for( i = 0; i < map->numoutputformats && format == NULL; i++ )
  549.     {
  550.         if( strcasecmp(imagetype,map->outputformatlist[i]->name) == 0 )
  551.             format = map->outputformatlist[i];
  552.     }
  553.     
  554.     if (format)
  555.     {
  556.         if (map->imagetype)
  557.             free(map->imagetype);
  558.         map->imagetype = strdup(format->name);
  559.     }
  560.     if( format != NULL )
  561.         msOutputFormatValidate( format );
  562.     return format;
  563. }
  564. /************************************************************************/
  565. /*                        msApplyOutputFormat()                         */
  566. /************************************************************************/
  567. void msApplyOutputFormat( outputFormatObj **target, 
  568.                           outputFormatObj *format,
  569.                           int transparent, 
  570.                           int interlaced, 
  571.                           int imagequality )
  572. {
  573.     int       change_needed = MS_FALSE;
  574.     int       old_imagequality, old_interlaced;
  575.     outputFormatObj *formatToFree = NULL;
  576.     assert( target != NULL );
  577.     
  578.     if( *target != NULL && --((*target)->refcount) < 1 )
  579.     {
  580.         formatToFree = *target;
  581.         *target = NULL;
  582.     }
  583.     if( format == NULL )
  584.     {
  585.         if( formatToFree )
  586.             msFreeOutputFormat( formatToFree );
  587.         return;
  588.     }
  589.     msOutputFormatValidate( format );
  590. /* -------------------------------------------------------------------- */
  591. /*      Do we need to change any values?  If not, then just apply       */
  592. /*      and return.                                                     */
  593. /* -------------------------------------------------------------------- */
  594.     if( transparent != MS_NOOVERRIDE && !format->transparent != !transparent )
  595.         change_needed = MS_TRUE;
  596.     old_imagequality = atoi(msGetOutputFormatOption( format, "QUALITY", "75"));
  597.     if( imagequality != MS_NOOVERRIDE && old_imagequality != imagequality )
  598.         change_needed = MS_TRUE;
  599.     old_interlaced = 
  600.         strcasecmp(msGetOutputFormatOption( format, "INTERLACE", "ON"),
  601.                    "OFF") != 0;
  602.     if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced )
  603.         change_needed = MS_TRUE;
  604.     if( change_needed )
  605.     {
  606.         char new_value[128];
  607.         if( format->refcount > 0 )
  608.             format = msCloneOutputFormat( format );
  609.         if( transparent != MS_NOOVERRIDE )
  610.         {
  611.             format->transparent = transparent;
  612.             if( format->imagemode == MS_IMAGEMODE_RGB )
  613.                 format->imagemode = MS_IMAGEMODE_RGBA;
  614.         }
  615.         if( imagequality != MS_NOOVERRIDE && imagequality != old_imagequality )
  616.         {
  617.             sprintf( new_value, "%d", imagequality );
  618.             msSetOutputFormatOption( format, "QUALITY", new_value );
  619.         }
  620.         if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced )
  621.         {
  622.             if( interlaced )
  623.                 msSetOutputFormatOption( format, "INTERLACE", "ON" );
  624.             else
  625.                 msSetOutputFormatOption( format, "INTERLACE", "OFF" );
  626.         }
  627.     }
  628.     *target = format;
  629.     format->refcount++;
  630.     if( formatToFree )
  631.         msFreeOutputFormat( formatToFree );
  632. }
  633. /************************************************************************/
  634. /*                        msCloneOutputFormat()                         */
  635. /************************************************************************/
  636. outputFormatObj *msCloneOutputFormat( outputFormatObj *src )
  637. {
  638.     outputFormatObj *dst;
  639.     int             i;
  640.     dst = msAllocOutputFormat( NULL, src->name, src->driver );
  641.     msFree( dst->mimetype );
  642.     if( src->mimetype )
  643.         dst->mimetype = strdup( src->mimetype );
  644.     else
  645.         dst->mimetype = NULL;
  646.     msFree( dst->extension );
  647.     if( src->extension )
  648.         dst->extension = strdup( src->extension );
  649.     else
  650.         dst->extension = NULL;
  651.     dst->imagemode = src->imagemode;
  652.     dst->renderer = src->renderer;
  653.     dst->transparent = src->transparent;
  654.     dst->bands = src->bands;
  655.     dst->numformatoptions = src->numformatoptions;
  656.     dst->formatoptions = (char **) 
  657.         malloc(sizeof(char *) * src->numformatoptions );
  658.     for( i = 0; i < src->numformatoptions; i++ )
  659.         dst->formatoptions[i] = strdup(src->formatoptions[i]);
  660.     return dst;
  661. }
  662. /************************************************************************/
  663. /*                      msGetOutputFormatOption()                       */
  664. /*                                                                      */
  665. /*      Fetch the value of a particular option.  It is assumed the      */
  666. /*      options are in "KEY=VALUE" format.                              */
  667. /************************************************************************/
  668. const char *msGetOutputFormatOption( outputFormatObj *format, 
  669.                                      const char *optionkey, 
  670.                                      const char *defaultresult )
  671. {
  672.     int    i, len = strlen(optionkey);
  673.     for( i = 0; i < format->numformatoptions; i++ )
  674.     {
  675.         if( strncasecmp(format->formatoptions[i],optionkey,len) == 0
  676.             && format->formatoptions[i][len] == '=' )
  677.             return format->formatoptions[i] + len + 1;
  678.     }
  679.     return defaultresult;
  680. }
  681. /************************************************************************/
  682. /*                      msSetOutputFormatOption()                       */
  683. /************************************************************************/
  684. void msSetOutputFormatOption( outputFormatObj *format,
  685.                               const char *key, const char *value )
  686. {
  687.     char *newline;
  688.     int   i, len;
  689. /* -------------------------------------------------------------------- */
  690. /*      Format the name=value pair into a newly allocated string.       */
  691. /* -------------------------------------------------------------------- */
  692.     newline = (char *) malloc(strlen(key)+strlen(value)+2);
  693.     if( newline == NULL )
  694.     {
  695.         assert( newline != NULL );
  696.         return;
  697.     }
  698.     sprintf( newline, "%s=%s", key, value );
  699.     
  700. /* -------------------------------------------------------------------- */
  701. /*      Does this key already occur?  If so replace it.                 */
  702. /* -------------------------------------------------------------------- */
  703.     len = strlen(key);
  704.     for( i = 0; i < format->numformatoptions; i++ )
  705.     {
  706.         if( strncasecmp(format->formatoptions[i],key,len) == 0
  707.             && format->formatoptions[i][len] == '=' )
  708.         {
  709.             free( format->formatoptions[i] );
  710.             format->formatoptions[i] = newline;
  711.             return;
  712.         }
  713.     }
  714. /* -------------------------------------------------------------------- */
  715. /*      otherwise, we need to grow the list.                            */
  716. /* -------------------------------------------------------------------- */
  717.     format->numformatoptions++;
  718.     format->formatoptions = (char **) 
  719.         realloc( format->formatoptions, 
  720.                  sizeof(char*) * format->numformatoptions );
  721.     format->formatoptions[format->numformatoptions-1] = newline;
  722. /* -------------------------------------------------------------------- */
  723. /*      Capture generic value(s) we are interested in.                  */
  724. /* -------------------------------------------------------------------- */
  725.     if( strcasecmp(key,"BAND_COUNT") == 0 )
  726.         format->bands = atoi(value);
  727. }
  728. /************************************************************************/
  729. /*                     msGetOutputFormatMimeList()                      */
  730. /************************************************************************/
  731. void msGetOutputFormatMimeList( mapObj *map, char **mime_list, int max_mime )
  732. {
  733.     int mime_count = 0, i;
  734.     for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ )
  735.     {
  736.         int  j;
  737.         
  738.         if( map->outputformatlist[i]->mimetype == NULL )
  739.             continue;
  740.         for( j = 0; j < mime_count; j++ )
  741.         {
  742.             if( strcasecmp(mime_list[j],
  743.                            map->outputformatlist[i]->mimetype) == 0 )
  744.                 break;
  745.         }
  746.         if( j == mime_count )
  747.             mime_list[mime_count++] = map->outputformatlist[i]->mimetype;
  748.     }
  749.     if( mime_count < max_mime )
  750.         mime_list[mime_count] = NULL;
  751. }
  752. /************************************************************************/
  753. /*                     msGetOutputFormatMimeList()                      */
  754. /************************************************************************/
  755. void msGetOutputFormatMimeListGD( mapObj *map, char **mime_list, int max_mime )
  756. {
  757.     int mime_count = 0, i;
  758.     for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ )
  759.     {
  760.         int  j;
  761.         
  762.         if( map->outputformatlist[i]->mimetype == NULL )
  763.             continue;
  764.         for( j = 0; j < mime_count; j++ )
  765.         {
  766.             if( strcasecmp(mime_list[j],
  767.                            map->outputformatlist[i]->mimetype) == 0 )
  768.                 break;
  769.         }
  770.         if( j == mime_count && map->outputformatlist[i]->driver &&
  771.             strncasecmp(map->outputformatlist[i]->driver, "GD/", 3)==0)
  772.             mime_list[mime_count++] = map->outputformatlist[i]->mimetype;
  773.     }
  774.     if( mime_count < max_mime )
  775.         mime_list[mime_count] = NULL;
  776. }
  777. /************************************************************************/
  778. /*                  msGetOutputFormatMimeListRaster()                   */
  779. /************************************************************************/
  780. void msGetOutputFormatMimeListRaster( mapObj *map, char **mime_list, int max_mime )
  781. {
  782.     int mime_count = 0, i;
  783.     for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ )
  784.     {
  785.         int  j;
  786.         
  787.         if( map->outputformatlist[i]->mimetype == NULL )
  788.             continue;
  789.         for( j = 0; j < mime_count; j++ )
  790.         {
  791.             if( strcasecmp(mime_list[j],
  792.                            map->outputformatlist[i]->mimetype) == 0 )
  793.                 break;
  794.         }
  795.         if( j == mime_count && map->outputformatlist[i]->driver &&
  796.             (strncasecmp(map->outputformatlist[i]->driver, "GD/", 3)==0 ||
  797.              strncasecmp(map->outputformatlist[i]->driver, "GDAL/", 5)==0))
  798.             mime_list[mime_count++] = map->outputformatlist[i]->mimetype;
  799.     }
  800.     if( mime_count < max_mime )
  801.         mime_list[mime_count] = NULL;
  802. }
  803. /************************************************************************/
  804. /*                       msOutputFormatValidate()                       */
  805. /*                                                                      */
  806. /*      Do some validation of the output format, and report to debug    */
  807. /*      output if it doesn't seem valid.  Fixup in place as best as     */
  808. /*      possible.                                                       */
  809. /************************************************************************/
  810. int msOutputFormatValidate( outputFormatObj *format )
  811. {
  812.     int result = MS_TRUE;
  813.     format->bands = 
  814.             atoi(msGetOutputFormatOption( format, "BAND_COUNT", "1" ));
  815.     /* Enforce the requirement that GD/JPEG be RGB and TRANSPARENT=OFF */
  816.     if( strcasecmp(format->driver,"GD/JPEG") == 0 && format->transparent )
  817.     {
  818.         msDebug( "GD/JPEG OUTPUTFORMAT %s has TRANSPARENT set ON, but this is not supported.n"
  819.                  "It has been disabled.n", 
  820.                  format->name );
  821.         format->transparent = MS_FALSE;
  822.         result = MS_FALSE;
  823.     }
  824.     if( strcasecmp(format->driver,"GD/JPEG") == 0 
  825.         && format->imagemode == MS_IMAGEMODE_RGBA )
  826.     {
  827.         msDebug( "GD/JPEG OUTPUTFORMAT %s has IMAGEMODE RGBA, but this is not supported.n"
  828.                  "IMAGEMODE forced to RGB.n", 
  829.                  format->name );
  830.         format->imagemode = MS_IMAGEMODE_RGB;
  831.         result = MS_FALSE;
  832.     }
  833.     if( format->transparent && format->imagemode == MS_IMAGEMODE_RGB )
  834.     {
  835.         msDebug( "OUTPUTFORMAT %s has TRANSPARENT set ON, but an IMAGEMODEn"
  836.                  " of RGB instead of RGBA.  Changing imagemode to RGBA.n", 
  837.                  format->name );
  838.         format->imagemode = MS_IMAGEMODE_RGBA;
  839.         result = MS_FALSE;
  840.     }
  841.     /* see bug 724 */
  842.     if( ( format->imagemode == MS_IMAGEMODE_INT16 
  843.           || format->imagemode == MS_IMAGEMODE_FLOAT32 
  844.           || format->imagemode == MS_IMAGEMODE_BYTE )
  845.         && format->renderer != MS_RENDER_WITH_RAWDATA )
  846.         format->renderer = MS_RENDER_WITH_RAWDATA;
  847.     return result;
  848. }