diff options
Diffstat (limited to 'engines/sword25/gfx/image/pngloader.cpp')
-rw-r--r-- | engines/sword25/gfx/image/pngloader.cpp | 360 |
1 files changed, 155 insertions, 205 deletions
diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp index 1c896a7675..3f892c7af1 100644 --- a/engines/sword25/gfx/image/pngloader.cpp +++ b/engines/sword25/gfx/image/pngloader.cpp @@ -85,209 +85,170 @@ bool BS_PNGLoader::DoDecodeImage(const char *FileDataPtr, unsigned int FileSize, return false; } - try { - // PNG Signatur überprüfen - if (!png_check_sig(reinterpret_cast<png_bytep>(const_cast<char *>(FileDataPtr)), 8)) { - throw(0); - } - - // Die beiden PNG Strukturen erstellen - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - BS_LOG_ERRORLN("Could not create libpng read struct."); - throw(0); - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - BS_LOG_ERRORLN("Could not create libpng info struct."); - throw(0); - } + // PNG Signatur überprüfen + if (!png_check_sig(reinterpret_cast<png_bytep>(const_cast<char *>(FileDataPtr)), 8)) { + error("png_check_sig failed"); + } - // Rücksprungpunkt setzen. Wird im Falle eines Fehlers angesprungen. - if (setjmp(png_jmpbuf(png_ptr))) throw(0); + // Die beiden PNG Strukturen erstellen + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + error("Could not create libpng read struct."); + } - // Alternative Lesefunktion benutzen - png_set_read_fn(png_ptr, (void *)FileDataPtr, png_user_read_data); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + error("Could not create libpng info struct."); + } - // PNG Header einlesen - png_read_info(png_ptr, info_ptr); + // Alternative Lesefunktion benutzen + png_set_read_fn(png_ptr, (void *)FileDataPtr, png_user_read_data); - // PNG Informationen auslesen - png_get_IHDR(png_ptr, info_ptr, (unsigned long *)&Width, (unsigned long *)&Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL); + // PNG Header einlesen + png_read_info(png_ptr, info_ptr); - // Pitch des Ausgabebildes berechnen - Pitch = BS_GraphicEngine::CalcPitch(ColorFormat, Width); + // PNG Informationen auslesen + png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&Width, (png_uint_32 *)&Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL); - // Speicher für die endgültigen Bilddaten reservieren - // Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten - UncompressedDataPtr = new char[Pitch * Height]; - if (!UncompressedDataPtr) { - BS_LOG_ERRORLN("Could not allocate memory for output image."); - throw(0); - } + // Pitch des Ausgabebildes berechnen + Pitch = BS_GraphicEngine::CalcPitch(ColorFormat, Width); - // Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt - if (BitDepth == 16) - png_set_strip_16(png_ptr); - if (ColorType == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); - if (BitDepth < 8) - png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - if (ColorType == PNG_COLOR_TYPE_GRAY || - ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - - png_set_bgr(png_ptr); - - if (ColorType != PNG_COLOR_TYPE_RGB_ALPHA) - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - - // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen - png_read_update_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, (unsigned long *)&Width, (unsigned long *)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); - - // PNGs ohne Interlacing werden Zeilenweise eingelesen - if (InterlaceType == PNG_INTERLACE_NONE) { - // Speicher für eine Bildzeile reservieren - RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; - if (!RawDataBuffer) { - BS_LOG_ERRORLN("Could not allocate memory for row buffer."); - throw(0); - } + // Speicher für die endgültigen Bilddaten reservieren + // Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten + UncompressedDataPtr = new char[Pitch * Height]; + if (!UncompressedDataPtr) { + error("Could not allocate memory for output image."); + } - // Bilddaten zeilenweise einlesen und in das gewünschte Zielformat konvertieren - for (i = 0; i < Height; i++) { - // Zeile einlesen - png_read_row(png_ptr, RawDataBuffer, NULL); - - // Zeile konvertieren - switch (ColorFormat) { - case BS_GraphicEngine::CF_RGB16: - RowARGB32ToRGB16((unsigned char *)RawDataBuffer, - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); - break; - - case BS_GraphicEngine::CF_RGB15: - RowARGB32ToRGB15((unsigned char *)RawDataBuffer, - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); - break; - - case BS_GraphicEngine::CF_RGB16_INTERLEAVED: - RowARGB32ToRGB16_INTERLEAVED((unsigned char *)RawDataBuffer, - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); - break; - - case BS_GraphicEngine::CF_RGB15_INTERLEAVED: - RowARGB32ToRGB15_INTERLEAVED((unsigned char *)RawDataBuffer, - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); - break; - - case BS_GraphicEngine::CF_ARGB32: - memcpy(&UncompressedDataPtr[i * Pitch], - RawDataBuffer, - Pitch); - break; - - case BS_GraphicEngine::CF_ABGR32: - RowARGB32ToABGR32((unsigned char *)RawDataBuffer, - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); - break; - - default: - BS_ASSERT(false); - } - } + // Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt + if (BitDepth == 16) + png_set_strip_16(png_ptr); + if (ColorType == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (BitDepth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (ColorType == PNG_COLOR_TYPE_GRAY || + ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + png_set_bgr(png_ptr); + + if (ColorType != PNG_COLOR_TYPE_RGB_ALPHA) + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen + png_read_update_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&Width, (png_uint_32 *)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); + + // PNGs ohne Interlacing werden Zeilenweise eingelesen + if (InterlaceType == PNG_INTERLACE_NONE) { + // Speicher für eine Bildzeile reservieren + RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; + if (!RawDataBuffer) { + error("Could not allocate memory for row buffer."); } - // PNGs mit Interlacing werden an einem Stück eingelesen - else { - // Speicher für das komplette Bild reservieren - RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr) * Height]; - if (!RawDataBuffer) { - BS_LOG_ERRORLN("Could not allocate memory for raw image buffer."); - throw(0); - } - - // Speicher für die Rowpointer reservieren - pRowPtr = new png_bytep[Height]; - if (!pRowPtr) { - BS_LOG_ERRORLN("Could not allocate memory for row pointers."); - throw(0); - } - - // Alle Rowpointer mit den richtigen Offsets initialisieren - for (i = 0; i < Height; i++) - pRowPtr[i] = RawDataBuffer + i * png_get_rowbytes(png_ptr, info_ptr); - // Bild einlesen - png_read_image(png_ptr, pRowPtr); + // Bilddaten zeilenweise einlesen und in das gewünschte Zielformat konvertieren + for (i = 0; i < Height; i++) { + // Zeile einlesen + png_read_row(png_ptr, RawDataBuffer, NULL); - // Bilddaten zeilenweise in das gewünschte Ausgabeformat konvertieren + // Zeile konvertieren switch (ColorFormat) { case BS_GraphicEngine::CF_RGB16: - for (i = 0; i < Height; i++) - RowARGB32ToRGB16((unsigned char *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); + RowARGB32ToRGB16((byte *)RawDataBuffer, (byte *)&UncompressedDataPtr[i * Pitch], Width); break; case BS_GraphicEngine::CF_RGB15: - for (i = 0; i < Height; i++) - RowARGB32ToRGB15((unsigned char *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); + RowARGB32ToRGB15((byte *)RawDataBuffer, (byte *)&UncompressedDataPtr[i * Pitch], Width); break; case BS_GraphicEngine::CF_RGB16_INTERLEAVED: - for (i = 0; i < Height; i++) - RowARGB32ToRGB16_INTERLEAVED((unsigned char *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); + RowARGB32ToRGB16_INTERLEAVED((byte *)RawDataBuffer, (byte *)&UncompressedDataPtr[i * Pitch], Width); break; case BS_GraphicEngine::CF_RGB15_INTERLEAVED: - for (i = 0; i < Height; i++) - RowARGB32ToRGB15_INTERLEAVED((unsigned char *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), - (unsigned char *)&UncompressedDataPtr[i * Pitch], - Width); + RowARGB32ToRGB15_INTERLEAVED((byte *)RawDataBuffer, + (byte *)&UncompressedDataPtr[i * Pitch], Width); break; case BS_GraphicEngine::CF_ARGB32: - for (i = 0; i < Height; i++) - memcpy(&UncompressedDataPtr[i * Pitch], - &RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)], - Pitch); + memcpy(&UncompressedDataPtr[i * Pitch], RawDataBuffer, Pitch); + break; + + case BS_GraphicEngine::CF_ABGR32: + RowARGB32ToABGR32((byte *)RawDataBuffer, (byte *)&UncompressedDataPtr[i * Pitch], Width); break; + + default: + assert(0); } } + } else { + // PNGs mit Interlacing werden an einem Stück eingelesen + // Speicher für das komplette Bild reservieren + RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr) * Height]; + if (!RawDataBuffer) { + error("Could not allocate memory for raw image buffer."); + } - // Die zusätzlichen Daten am Ende des Bildes lesen - png_read_end(png_ptr, NULL); + // Speicher für die Rowpointer reservieren + pRowPtr = new png_bytep[Height]; + if (!pRowPtr) { + error("Could not allocate memory for row pointers."); + } - // Die Strukturen freigeben - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + // Alle Rowpointer mit den richtigen Offsets initialisieren + for (i = 0; i < Height; i++) + pRowPtr[i] = RawDataBuffer + i * png_get_rowbytes(png_ptr, info_ptr); - // Temporäre Buffer freigeben - delete[] pRowPtr; - delete[] RawDataBuffer; - } + // Bild einlesen + png_read_image(png_ptr, pRowPtr); + + // Bilddaten zeilenweise in das gewünschte Ausgabeformat konvertieren + switch (ColorFormat) { + case BS_GraphicEngine::CF_RGB16: + for (i = 0; i < Height; i++) + RowARGB32ToRGB16((byte *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), + (byte *)&UncompressedDataPtr[i * Pitch], Width); + break; - catch (int) { - delete[] pRowPtr; - delete[] RawDataBuffer; - if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); - if (info_ptr) png_destroy_read_struct(NULL, &info_ptr, NULL); + case BS_GraphicEngine::CF_RGB15: + for (i = 0; i < Height; i++) + RowARGB32ToRGB15((byte *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), + (byte *)&UncompressedDataPtr[i * Pitch], Width); + break; - // Der Funktionsaufruf war nicht erfolgreich - return false; + case BS_GraphicEngine::CF_RGB16_INTERLEAVED: + for (i = 0; i < Height; i++) + RowARGB32ToRGB16_INTERLEAVED((byte *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), + (byte *)&UncompressedDataPtr[i * Pitch], Width); + break; + + case BS_GraphicEngine::CF_RGB15_INTERLEAVED: + for (i = 0; i < Height; i++) + RowARGB32ToRGB15_INTERLEAVED((byte *)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]), + (byte *)&UncompressedDataPtr[i * Pitch], Width); + break; + + case BS_GraphicEngine::CF_ARGB32: + for (i = 0; i < Height; i++) + memcpy(&UncompressedDataPtr[i * Pitch], &RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)], Pitch); + break; + } } + + // Die zusätzlichen Daten am Ende des Bildes lesen + png_read_end(png_ptr, NULL); + + // Die Strukturen freigeben + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + // Temporäre Buffer freigeben + delete[] pRowPtr; + delete[] RawDataBuffer; // Der Funktionsaufruf war erfolgreich return true; @@ -308,48 +269,37 @@ bool BS_PNGLoader::DoImageProperties(const char *FileDataPtr, unsigned int FileS png_structp png_ptr = NULL; png_infop info_ptr = NULL; - try { - // Die beiden PNG Strukturen erstellen - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - BS_LOG_ERRORLN("Could not create libpng read struct."); - throw(0); - } - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - BS_LOG_ERRORLN("Could not create libpng info struct."); - throw(0); - } - - // Alternative Lesefunktion benutzen - png_set_read_fn(png_ptr, (void *)FileDataPtr, png_user_read_data); + // Die beiden PNG Strukturen erstellen + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + error("Could not create libpng read struct."); + } - // PNG Header einlesen - png_read_info(png_ptr, info_ptr); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + error("Could not create libpng info struct."); + } - // PNG Informationen auslesen - int BitDepth; - int ColorType; - png_get_IHDR(png_ptr, info_ptr, (unsigned long *)&Width, (unsigned long *)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); + // Alternative Lesefunktion benutzen + png_set_read_fn(png_ptr, (void *)FileDataPtr, png_user_read_data); - // PNG-ColorType in BS ColorFormat konvertieren. - if (ColorType & PNG_COLOR_MASK_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - ColorFormat = BS_GraphicEngine::CF_ARGB32; - else - ColorFormat = BS_GraphicEngine::CF_RGB24; + // PNG Header einlesen + png_read_info(png_ptr, info_ptr); - // Die Strukturen freigeben - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - } + // PNG Informationen auslesen + int BitDepth; + int ColorType; + png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&Width, (png_uint_32 *)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); - catch (int) { - if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); - if (info_ptr) png_destroy_read_struct(NULL, &info_ptr, NULL); + // PNG-ColorType in BS ColorFormat konvertieren. + if (ColorType & PNG_COLOR_MASK_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + ColorFormat = BS_GraphicEngine::CF_ARGB32; + else + ColorFormat = BS_GraphicEngine::CF_RGB24; - // Der Funktionsaufruf war nicht erfolgreich - return false; - } + // Die Strukturen freigeben + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return true; @@ -367,7 +317,7 @@ bool BS_PNGLoader::ImageProperties(const char *FileDataPtr, unsigned int FileSiz bool BS_PNGLoader::DoIsCorrectImageFormat(const char *FileDataPtr, unsigned int FileSize) { if (FileSize > 8) - return png_check_sig((unsigned char *)FileDataPtr, 8) ? true : false; + return png_check_sig((byte *)FileDataPtr, 8) ? true : false; else return false; } |