Re: Creating JPEG images with gdal
Frank Warmerdam <[email protected]>
| Newsgroups | gmane.comp.gis.freegis |
|---|---|
| Message-ID | <[email protected]> |
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, [email protected] 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; }