[Freegis-list] Creating JPEG images with gdal

Frank Warmerdam warmerdam at pobox.com
Tue Oct 31 22:10:52 CET 2006


Tomas Zajc wrote:
> Correctme if I'm wrong. I can't use gdal to export an image I have on memory 
> (ie. on an array). I want to open an existin file usin gda or reading a raw 
> data (manualy) make some modifications (filtering, resampling, etc) and 
> export as JPEG. Maybe I should just use the plain jpg library to dump my 
> array on a file.

Tomas,

First, I should likely have mentioned last time that the gdal-dev mailing
list would be a more appropriate place for this discussion.

It is possible to use CreateCopy() with a memory array as the input,
though it is somewhat involved since you need to create a "virtual dataset"
wrapper for your memory array.  I have included an example of how this is
accomplished in mapserver below if you would like an example.

Of course it may well be easier to just write it using the jpeg library
if that is all you want to do.

Best regards,
-- 
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam at pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | President OSGeo, http://osgeo.org



/************************************************************************/
/*                          msSaveImageGDAL()                           */
/************************************************************************/

int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename )

{
     int  bFileIsTemporary = MS_FALSE;
     GDALDatasetH hMemDS, hOutputDS;
     GDALDriverH  hMemDriver, hOutputDriver;
     int          nBands = 1;
     int          iLine;
     GByte       *pabyAlphaLine = NULL;
     char        **papszOptions = NULL;
     outputFormatObj *format = image->format;
     GDALDataType eDataType = GDT_Byte;

     msGDALInitialize();

/* -------------------------------------------------------------------- */
/*      We will need to write the output to a temporary file and        */
/*      then stream to stdout if no filename is passed.                 */
/* -------------------------------------------------------------------- */
     if( filename == NULL )
     {
         const char *pszExtension = format->extension;
         if( pszExtension == NULL )
             pszExtension = "img.tmp";

         if( map != NULL && map->web.imagepath != NULL )
             filename = msTmpFile(map->mappath,map->web.imagepath,pszExtension);
         else
         {
#ifndef _WIN32
             filename = msTmpFile(NULL, "/tmp/", pszExtension );
#else
             filename = msTmpFile(NULL, "C:\\", pszExtension );
#endif
         }

         bFileIsTemporary = MS_TRUE;
     }

/* -------------------------------------------------------------------- */
/*      Establish the characteristics of our memory, and final          */
/*      dataset.                                                        */
/* -------------------------------------------------------------------- */
     if( format->imagemode == MS_IMAGEMODE_RGB )
     {
         nBands = 3;
         assert( gdImageTrueColor( image->img.gd ) );
     }
     else if( format->imagemode == MS_IMAGEMODE_RGBA )
     {
         pabyAlphaLine = (GByte *) calloc(image->width,1);
         nBands = 4;
         assert( gdImageTrueColor( image->img.gd ) );
     }
     else if( format->imagemode == MS_IMAGEMODE_INT16 )
     {
         nBands = format->bands;
         eDataType = GDT_Int16;
     }
     else if( format->imagemode == MS_IMAGEMODE_FLOAT32 )
     {
         nBands = format->bands;
         eDataType = GDT_Float32;
     }
     else if( format->imagemode == MS_IMAGEMODE_BYTE )
     {
         nBands = format->bands;
         eDataType = GDT_Byte;
     }
     else
     {
         assert( format->imagemode == MS_IMAGEMODE_PC256
                 && !gdImageTrueColor( image->img.gd ) );
     }

/* -------------------------------------------------------------------- */
/*      Create a memory dataset which we can use as a source for a      */
/*      CreateCopy().                                                   */
/* -------------------------------------------------------------------- */
     msAcquireLock( TLOCK_GDAL );
     hMemDriver = GDALGetDriverByName( "MEM" );
     if( hMemDriver == NULL )
     {
         msReleaseLock( TLOCK_GDAL );
         msSetError( MS_MISCERR, "Failed to find MEM driver.",
                     "msSaveImageGDAL()" );
         return MS_FAILURE;
     }

     hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp",
                          image->width, image->height, nBands,
                          eDataType, NULL );
     if( hMemDS == NULL )
     {
         msReleaseLock( TLOCK_GDAL );
         msSetError( MS_MISCERR, "Failed to create MEM dataset.",
                     "msSaveImageGDAL()" );
         return MS_FAILURE;
     }

/* -------------------------------------------------------------------- */
/*      Copy the gd image into the memory dataset.                      */
/* -------------------------------------------------------------------- */
     for( iLine = 0; iLine < image->height; iLine++ )
     {
         int iBand;

         for( iBand = 0; iBand < nBands; iBand++ )
         {
             GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 );

             if( format->imagemode == MS_IMAGEMODE_INT16 )
             {
                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               image->img.raw_16bit + iLine * image->width
                               + iBand * image->width * image->height,
                               image->width, 1, GDT_Int16, 2, 0 );

             }
             else if( format->imagemode == MS_IMAGEMODE_FLOAT32 )
             {
                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               image->img.raw_float + iLine * image->width
                               + iBand * image->width * image->height,
                               image->width, 1, GDT_Float32, 4, 0 );
             }
             else if( format->imagemode == MS_IMAGEMODE_BYTE )
             {
                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               image->img.raw_byte + iLine * image->width
                               + iBand * image->width * image->height,
                               image->width, 1, GDT_Byte, 1, 0 );
             }
#if GD2_VERS > 1
             else if( nBands > 1 && iBand < 3 )
             {
                 GByte *pabyData;
#ifdef CPL_MSB

                 pabyData = ((GByte *) image->img.gd->tpixels[iLine])+iBand+1;
#else
                 pabyData = ((GByte *) image->img.gd->tpixels[iLine])+(2-iBand);
#endif
                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               pabyData, image->width, 1, GDT_Byte, 4, 0 );
             }
             else if( nBands > 1 && iBand == 3 ) /* Alpha band */
             {
                 int x;
#ifdef CPL_MSB
                 GByte *pabySrc = ((GByte *) image->img.gd->tpixels[iLine]);
#else
                 GByte *pabySrc = ((GByte *) image->img.gd->tpixels[iLine])+3;
#endif

                 for( x = 0; x < image->width; x++ )
                 {
                     if( *pabySrc == 127 )
                         pabyAlphaLine[x] = 0;
                     else
                         pabyAlphaLine[x] = 255 - 2 * *pabySrc;

                     pabySrc += 4;
                 }

                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               pabyAlphaLine, image->width, 1, GDT_Byte, 1, 0 );
             }
#endif
             else
             {
                 GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                               image->img.gd->pixels[iLine],
                               image->width, 1, GDT_Byte, 0, 0 );
             }
         }
     }

     if( pabyAlphaLine != NULL )
         free( pabyAlphaLine );

/* -------------------------------------------------------------------- */
/*      Attach the palette if appropriate.                              */
/* -------------------------------------------------------------------- */
     if( format->imagemode == MS_IMAGEMODE_PC256 )
     {
         GDALColorEntry sEntry;
         int  iColor;
         GDALColorTableH hCT;

         hCT = GDALCreateColorTable( GPI_RGB );

         for( iColor = 0; iColor < image->img.gd->colorsTotal; iColor++ )
         {
             sEntry.c1 = image->img.gd->red[iColor];
             sEntry.c2 = image->img.gd->green[iColor];
             sEntry.c3 = image->img.gd->blue[iColor];

             if( iColor == gdImageGetTransparent( image->img.gd ) )
                 sEntry.c4 = 0;
             else if( iColor == 0
                      && gdImageGetTransparent( image->img.gd ) == -1
                      && format->transparent )
                 sEntry.c4 = 0;
             else
                 sEntry.c4 = 255;

             GDALSetColorEntry( hCT, iColor, &sEntry );
         }

         GDALSetRasterColorTable( GDALGetRasterBand( hMemDS, 1 ), hCT );

         GDALDestroyColorTable( hCT );
     }

#if GDAL_VERSION_NUM > 1170
     else if( format->imagemode == MS_IMAGEMODE_RGB )
     {
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand );
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand );
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand );
     }
     else if( format->imagemode == MS_IMAGEMODE_RGBA )
     {
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand );
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand );
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand );
         GDALSetRasterColorInterpretation(
             GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand );
     }
#endif

/* -------------------------------------------------------------------- */
/*      Assign the projection and coordinate system to the memory       */
/*      dataset.                                                        */
/* -------------------------------------------------------------------- */

     if( map != NULL )
     {
         char *pszWKT;

         GDALSetGeoTransform( hMemDS, map->gt.geotransform );

         pszWKT = msProjectionObjToWKT( &(map->projection) );
         if( pszWKT != NULL )
         {
             GDALSetProjection( hMemDS, pszWKT );
             CPLFree( pszWKT );
         }
     }

/* -------------------------------------------------------------------- */
/*      Create a disk image in the selected output format from the      */
/*      memory image.                                                   */
/* -------------------------------------------------------------------- */
     hOutputDriver = GDALGetDriverByName( format->driver+5 );
     if( hOutputDriver == NULL )
     {
         GDALClose( hMemDS );
         msReleaseLock( TLOCK_GDAL );
         msSetError( MS_MISCERR, "Failed to find %s driver.",
                     "msSaveImageGDAL()", format->driver+5 );
         return MS_FAILURE;
     }

     papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1));
     memcpy( papszOptions, format->formatoptions,
             sizeof(char *) * format->numformatoptions );

     hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE,
                                 papszOptions, NULL, NULL );

     free( papszOptions );

     if( hOutputDS == NULL )
     {
         GDALClose( hMemDS );
         msReleaseLock( TLOCK_GDAL );
         msSetError( MS_MISCERR, "Failed to create output %s file.\n%s",
                     "msSaveImageGDAL()", format->driver+5,
                     CPLGetLastErrorMsg() );
         return MS_FAILURE;
     }

     /* closing the memory DS also frees all associated resources. */
     GDALClose( hMemDS );

     GDALClose( hOutputDS );

     msReleaseLock( TLOCK_GDAL );

/* -------------------------------------------------------------------- */
/*      Is this supposed to be a temporary file?  If so, stream to      */
/*      stdout and delete the file.                                     */
/* -------------------------------------------------------------------- */
     if( bFileIsTemporary )
     {
         FILE *fp;
         unsigned char block[4000];
         int bytes_read;

         if( msIO_needBinaryStdout() == MS_FAILURE )
             return MS_FAILURE;

         fp = fopen( filename, "rb" );
         if( fp == NULL )
         {
             msSetError( MS_MISCERR,
                         "Failed to open %s for streaming to stdout.",
                         "msSaveImageGDAL()", filename );
             return MS_FAILURE;
         }

         while( (bytes_read = fread(block, 1, sizeof(block), fp)) > 0 )
             msIO_fwrite( block, 1, bytes_read, stdout );

         fclose( fp );

         unlink( filename );
         free( filename );
     }

     return MS_SUCCESS;
}




More information about the Freegis-list mailing list

This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)