int main (int argc, char **argv) { GpImage *img; gunichar2 *unis; GpBitmap *bitmap; GpStatus status; int original_palette_size; int reloaded_palette_size; ColorPalette *original_palette; ColorPalette *reloaded_palette; GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; PixelFormat pixel_format; ARGB color; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // PNG resave should preserve the palette transparency. Let's test it // by loading a PNG file and its palette, then resaving it and loading // it again for comparison. unis = g_utf8_to_utf16 ("test-trns.png", -1, NULL, NULL, NULL); status = GdipLoadImageFromFile (unis, &img); CHECK_STATUS(1); g_free (unis); status = GdipGetImagePaletteSize (img, &original_palette_size); CHECK_STATUS(1); CHECK_ASSERT(original_palette_size > 0); original_palette = malloc (original_palette_size); GdipGetImagePalette (img, original_palette, original_palette_size); CHECK_STATUS(1); unis = g_utf8_to_utf16 ("test-trns-resave.png", -1, NULL, NULL, NULL); status = GdipSaveImageToFile (img, unis, &png_clsid, NULL); CHECK_STATUS(1); GdipDisposeImage (img); status = GdipLoadImageFromFile (unis, &img); CHECK_STATUS(1); g_free (unis); status = GdipGetImagePaletteSize (img, &reloaded_palette_size); CHECK_STATUS(1); CHECK_ASSERT(reloaded_palette_size > 0); CHECK_ASSERT(reloaded_palette_size == original_palette_size); reloaded_palette = malloc (reloaded_palette_size); GdipGetImagePalette (img, reloaded_palette, reloaded_palette_size); CHECK_STATUS(1); CHECK_ASSERT(memcmp (original_palette, reloaded_palette, original_palette_size) == 0); GdipDisposeImage (img); img = NULL; unlink ("test-trns-resave.png"); free (original_palette); free (reloaded_palette); // Test grayscale image with alpha channel. The image should be converted // into 32-bit ARGB format and the alpha channel should be preserved. unis = g_utf8_to_utf16 ("test-gsa.png", -1, NULL, NULL, NULL); status = GdipCreateBitmapFromFile (unis, &bitmap); CHECK_STATUS(1); g_free (unis); status = GdipGetImagePixelFormat (bitmap, &pixel_format); CHECK_STATUS(1); CHECK_ASSERT(pixel_format == PixelFormat32bppARGB); status = GdipBitmapGetPixel (bitmap, 0, 0, &color); CHECK_STATUS(1); CHECK_ASSERT(color == 0xffffff); status = GdipBitmapGetPixel (bitmap, 1, 7, &color); CHECK_STATUS(1); CHECK_ASSERT(color == 0xe8b3b3b3); GdipDisposeImage (bitmap); return 0; }
int ReadTextureFromFile( struct Texture * t, const char * filename ) { int i; HGLOBAL hMem; LPVOID pMemImage; IStream *pStm; struct GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GpBitmap *pImg; PixelFormat PixelFormat; //Read in data FILE * f = fopen( filename, "rb"); if( !f ) { fprintf( stderr, "Error: Could not open %s\n", filename ); return -1; } fseek(f,0,SEEK_END); int l = ftell( f ); unsigned char * buffer = malloc( l ); fseek(f,0,SEEK_SET); fread(buffer, l, 1, f ); fclose( f ); //Prepare GDI+ imaging hMem = GlobalAlloc( GMEM_MOVEABLE, l ); pMemImage = GlobalLock( hMem); memcpy( pMemImage, buffer, l ); GlobalUnlock( hMem ); //XXX: This requries OLE32, do we really want it? CreateStreamOnHGlobal( hMem, TRUE, &pStm ); gdiplusStartupInput.GdiplusVersion = 1; gdiplusStartupInput.DebugEventCallback = NULL; gdiplusStartupInput.SuppressBackgroundThread = FALSE; gdiplusStartupInput.SuppressExternalCodecs = FALSE; GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL ); if( GdipCreateBitmapFromStream( pStm, &pImg ) ) { fprintf( stderr, "Error: cannot decode: %s\n", filename ); return -2; } GdipGetImagePixelFormat( (GpImage *)pImg, &PixelFormat ); UINT width; UINT height; GdipGetImageHeight( (GpImage *)pImg, &height ); GdipGetImageWidth( (GpImage *)pImg, &width ); GpRect r; r.X = 0; r.Y = 0; r.Width = width; r.Height = height; BitmapData bd; enum TextureType format; GLenum type; //Almost always GL_TEXTURE_2D (Could be GL_TEXTURE_3D) GLuint texture; int slot; //which texture slot (For multi-texturing) uint8_t * rawdata; //May be other types, too! t->width = width; t->height = height; t->type = GL_TEXTURE_2D; //Detect if has alpha or not... int ps; if( PixelFormat & PixelFormatAlpha ) { GdipBitmapLockBits(pImg,&r,ImageLockModeRead,PixelFormat32bppARGB,&bd); ps = 4; t->format = TTRGBA; } else { GdipBitmapLockBits(pImg,&r,ImageLockModeRead,PixelFormat24bppRGB,&bd); ps = 3; t->format = TTRGB; } t->rawdata = malloc( ps * width * height ); int x, y; if( ps == 3 ) { for( y = 0; y < height; y++ ) for( x = 0; x < width; x++ ) { t->rawdata[(x+y*width)*3+0] = ((unsigned char*)bd.Scan0)[x*3+y*bd.Stride+2]; t->rawdata[(x+y*width)*3+1] = ((unsigned char*)bd.Scan0)[x*3+y*bd.Stride+1]; t->rawdata[(x+y*width)*3+2] = ((unsigned char*)bd.Scan0)[x*3+y*bd.Stride+0]; } } else //ps = 4 { for( y = 0; y < height; y++ ) for( x = 0; x < width; x++ ) { t->rawdata[(x+y*width)*4+0] = ((unsigned char*)bd.Scan0)[x*4+y*bd.Stride+2]; t->rawdata[(x+y*width)*4+1] = ((unsigned char*)bd.Scan0)[x*4+y*bd.Stride+1]; t->rawdata[(x+y*width)*4+2] = ((unsigned char*)bd.Scan0)[x*4+y*bd.Stride+0]; t->rawdata[(x+y*width)*4+3] = ((unsigned char*)bd.Scan0)[x*4+y*bd.Stride+3]; } } GdipBitmapUnlockBits(pImg, &bd ); GdipDisposeImage( (GpImage *)pImg ); GdiplusShutdown( gdiplusToken ); return 0; }