[Scummvm-git-logs] scummvm master -> f23cfec2eb9332791fbee3e732ffba19eda9757d

dreammaster noreply at scummvm.org
Sat Dec 23 09:19:58 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f23cfec2eb ULTIMA4: Refactor the image loaders to inherit from Image::ImageDecoder


Commit: f23cfec2eb9332791fbee3e732ffba19eda9757d
    https://github.com/scummvm/scummvm/commit/f23cfec2eb9332791fbee3e732ffba19eda9757d
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-12-22T23:19:54-10:00

Commit Message:
ULTIMA4: Refactor the image loaders to inherit from Image::ImageDecoder

This also fixes the colours in the FM-TOWNS image decoder.

Changed paths:
  R engines/ultima/ultima4/gfx/imageloader_png.cpp
  R engines/ultima/ultima4/gfx/imageloader_png.h
    engines/ultima/module.mk
    engines/ultima/ultima4/gfx/image.cpp
    engines/ultima/ultima4/gfx/image.h
    engines/ultima/ultima4/gfx/imageloader.cpp
    engines/ultima/ultima4/gfx/imageloader.h
    engines/ultima/ultima4/gfx/imageloader_fmtowns.cpp
    engines/ultima/ultima4/gfx/imageloader_fmtowns.h
    engines/ultima/ultima4/gfx/imageloader_u4.cpp
    engines/ultima/ultima4/gfx/imageloader_u4.h
    engines/ultima/ultima4/gfx/imagemgr.cpp
    engines/ultima/ultima4/gfx/imagemgr.h
    engines/ultima/ultima4/ultima4.cpp
    engines/ultima/ultima4/ultima4.h


diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index a94959421b9..aed24caed1c 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -195,7 +195,6 @@ MODULE_OBJS += \
 	ultima4/gfx/image.o \
 	ultima4/gfx/imageloader.o \
 	ultima4/gfx/imageloader_fmtowns.o \
-	ultima4/gfx/imageloader_png.o \
 	ultima4/gfx/imageloader_u4.o \
 	ultima4/gfx/imagemgr.o \
 	ultima4/gfx/scale.o \
diff --git a/engines/ultima/ultima4/gfx/image.cpp b/engines/ultima/ultima4/gfx/image.cpp
index f299d5a9575..a6b9670f2d2 100644
--- a/engines/ultima/ultima4/gfx/image.cpp
+++ b/engines/ultima/ultima4/gfx/image.cpp
@@ -90,19 +90,9 @@ Image::~Image() {
 		delete _surface;
 }
 
-void Image::setPalette(const RGBA *colors, unsigned n_colors) {
+void Image::setPalette(const byte *colors, unsigned n_colors) {
 	assertMsg(_paletted, "imageSetPalette called on non-paletted image");
-
-	byte *pal = new byte[n_colors * 3];
-	byte *palP = pal;
-	for (unsigned i = 0; i < n_colors; i++, palP += 3) {
-		palP[0] = colors[i].r;
-		palP[1] = colors[i].g;
-		palP[2] = colors[i].b;
-	}
-
-	_surface->setPalette(pal, 0, n_colors);
-	delete[] pal;
+	_surface->setPalette(colors, 0, n_colors);
 }
 
 void Image::setPaletteFromImage(const Image *src) {
diff --git a/engines/ultima/ultima4/gfx/image.h b/engines/ultima/ultima4/gfx/image.h
index ad382a99300..f68a12981b7 100644
--- a/engines/ultima/ultima4/gfx/image.h
+++ b/engines/ultima/ultima4/gfx/image.h
@@ -113,7 +113,7 @@ public:
 	/**
 	 * Sets the palette
 	 */
-	void setPalette(const RGBA *colors, unsigned n_colors);
+	void setPalette(const byte *colors, unsigned n_colors);
 
 	/**
 	 * Copies the palette from another image.
diff --git a/engines/ultima/ultima4/gfx/imageloader.cpp b/engines/ultima/ultima4/gfx/imageloader.cpp
index ea41d6244e6..c5d477e4a2c 100644
--- a/engines/ultima/ultima4/gfx/imageloader.cpp
+++ b/engines/ultima/ultima4/gfx/imageloader.cpp
@@ -19,104 +19,99 @@
  *
  */
 
-#include "ultima/ultima4/gfx/image.h"
 #include "ultima/ultima4/gfx/imageloader.h"
-#include "ultima/ultima4/gfx/imageloader_u4.h"
-#include "ultima/ultima4/gfx/imageloader_png.h"
-#include "ultima/ultima4/gfx/imageloader_fmtowns.h"
-#include "ultima/ultima4/core/utils.h"
+
+#include "common/textconsole.h"
+#include "graphics/surface.h"
 
 namespace Ultima {
 namespace Ultima4 {
 
-ImageLoaders::ImageLoaders() {
-	_loaderMap["image/png"] = new PngImageLoader();
-	_loaderMap["image/x-u4raw"] = new U4RawImageLoader();
-	_loaderMap["image/x-u4rle"] = new U4RleImageLoader();
-	_loaderMap["image/x-u4lzw"] = new U4LzwImageLoader();
-	_loaderMap["image/fmtowns-tif"] = new FMTOWNSImageLoader(510);
+/*-------------------------------------------------------------------*/
+U4ImageDecoder::U4ImageDecoder(int width, int height, int bpp) {
+	_width = width;
+	_height = height;
+	_bpp = bpp;
+	_surface = nullptr;
+	_palette = nullptr;
+	_paletteColorCount = 0;
 }
 
-ImageLoaders::~ImageLoaders() {
-	for (Common::HashMap<Common::String, ImageLoader *>::iterator it = _loaderMap.begin();
-	        it != _loaderMap.end(); ++it) {
-		delete(*it)._value;
-	}
+U4ImageDecoder::~U4ImageDecoder() {
+	destroy();
 }
 
-ImageLoader *ImageLoaders::getLoader(const Common::String &fileType) {
-	if (!_loaderMap.contains(fileType))
-		return nullptr;
+void U4ImageDecoder::destroy() {
+	if (_surface) {
+		_surface->free();
+		delete _surface;
+		_surface = nullptr;
+	}
 
-	return _loaderMap[fileType];
+	// _palette is owned by U4PaletteLoader
+	_palette = nullptr;
+	_paletteColorCount = 0;
 }
 
-/*-------------------------------------------------------------------*/
-
-void ImageLoader::setFromRawData(Image *image, int width, int height, int bpp, const byte *rawData) {
+void U4ImageDecoder::setFromRawData(const byte *rawData) {
 	int x, y;
 
-	switch (bpp) {
+	switch (_bpp) {
 	case 32:
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x++)
-				image->putPixel(x, y,
-				                rawData[(y * width + x) * 4],
-				                rawData[(y * width + x) * 4 + 1],
-				                rawData[(y * width + x) * 4 + 2],
-				                rawData[(y * width + x) * 4 + 3]);
-		}
-		break;
-
 	case 24:
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x++)
-				image->putPixel(x, y,
-				                rawData[(y * width + x) * 3],
-				                rawData[(y * width + x) * 3 + 1],
-				                rawData[(y * width + x) * 3 + 2],
-				                IM_OPAQUE);
-		}
-		break;
-
 	case 8:
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x++)
-				image->putPixelIndex(x, y, rawData[y * width + x]);
-		}
+		_surface->copyRectToSurface(rawData, (_width * _bpp) / 8, 0, 0, _width, _height);
 		break;
 
 	case 4:
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x += 2) {
-				image->putPixelIndex(x, y, rawData[(y * width + x) / 2] >> 4);
-				image->putPixelIndex(x + 1, y, rawData[(y * width + x) / 2] & 0x0f);
+		for (y = 0; y < _height; y++) {
+			for (x = 0; x < _width; x += 2) {
+				_surface->setPixel(x, y, rawData[(y * _width + x) / 2] >> 4);
+				_surface->setPixel(x + 1, y, rawData[(y * _width + x) / 2] & 0x0f);
 			}
 		}
 		break;
 
 	case 1:
-		for (y = 0; y < height; y++) {
-			for (x = 0; x < width; x += 8) {
-				image->putPixelIndex(x + 0, y, (rawData[(y * width + x) / 8] >> 7) & 0x01);
-				image->putPixelIndex(x + 1, y, (rawData[(y * width + x) / 8] >> 6) & 0x01);
-				image->putPixelIndex(x + 2, y, (rawData[(y * width + x) / 8] >> 5) & 0x01);
-				image->putPixelIndex(x + 3, y, (rawData[(y * width + x) / 8] >> 4) & 0x01);
-				image->putPixelIndex(x + 4, y, (rawData[(y * width + x) / 8] >> 3) & 0x01);
-				image->putPixelIndex(x + 5, y, (rawData[(y * width + x) / 8] >> 2) & 0x01);
-				image->putPixelIndex(x + 6, y, (rawData[(y * width + x) / 8] >> 1) & 0x01);
-				image->putPixelIndex(x + 7, y, (rawData[(y * width + x) / 8] >> 0) & 0x01);
+		for (y = 0; y < _height; y++) {
+			for (x = 0; x < _width; x += 8) {
+				_surface->setPixel(x + 0, y, (rawData[(y * _width + x) / 8] >> 7) & 0x01);
+				_surface->setPixel(x + 1, y, (rawData[(y * _width + x) / 8] >> 6) & 0x01);
+				_surface->setPixel(x + 2, y, (rawData[(y * _width + x) / 8] >> 5) & 0x01);
+				_surface->setPixel(x + 3, y, (rawData[(y * _width + x) / 8] >> 4) & 0x01);
+				_surface->setPixel(x + 4, y, (rawData[(y * _width + x) / 8] >> 3) & 0x01);
+				_surface->setPixel(x + 5, y, (rawData[(y * _width + x) / 8] >> 2) & 0x01);
+				_surface->setPixel(x + 6, y, (rawData[(y * _width + x) / 8] >> 1) & 0x01);
+				_surface->setPixel(x + 7, y, (rawData[(y * _width + x) / 8] >> 0) & 0x01);
 			}
 		}
 		break;
 
 	default:
-		error("invalid bits-per-pixel (bpp): %d", bpp);
+		error("invalid bits-per-pixel (bpp): %d", _bpp);
 	}
 }
 
-void ImageLoader::setFromSurface(Image *image, const Graphics::ManagedSurface &src) {
-	image->blitFrom(src);
+Graphics::PixelFormat U4ImageDecoder::getPixelFormatForBpp() const {
+	switch (_bpp) {
+	case 1:
+	case 4:
+	case 8:
+		return Graphics::PixelFormat::createFormatCLUT8();
+#ifdef SCUMM_LITTLE_ENDIAN
+	case 24:
+		return Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0);
+	case 32:
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
+#else
+	case 24:
+		return Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
+	case 32:
+		return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+#endif
+	default:
+		error("invalid bits-per-pixel (bpp): %d", _bpp);
+	}
 }
 
 } // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/gfx/imageloader.h b/engines/ultima/ultima4/gfx/imageloader.h
index 0b379037fa3..26cf12c95a4 100644
--- a/engines/ultima/ultima4/gfx/imageloader.h
+++ b/engines/ultima/ultima4/gfx/imageloader.h
@@ -22,8 +22,8 @@
 #ifndef ULTIMA4_GFX_IMAGELOADER_H
 #define ULTIMA4_GFX_IMAGELOADER_H
 
-#include "ultima/shared/std/containers.h"
-#include "common/str.h"
+#include "graphics/pixelformat.h"
+#include "image/image_decoder.h"
 
 namespace Common {
 class SeekableReadStream;
@@ -32,47 +32,35 @@ class SeekableReadStream;
 namespace Ultima {
 namespace Ultima4 {
 
-class Image;
-class ImageLoader;
-class U4FILE;
-
-class ImageLoaders {
-private:
-	Common::HashMap<Common::String, ImageLoader *> _loaderMap;
+/**
+ * A common base for all Ultima 4 image loaders.
+ */
+class U4ImageDecoder : public ::Image::ImageDecoder {
 public:
-	ImageLoaders();
-	~ImageLoaders();
+	U4ImageDecoder(int width, int height, int bpp);
+	virtual ~U4ImageDecoder();
 
-	/**
-	 * This class method returns the registered concrete subclass
-	 * appropriate for loading images of a type given by fileType.
-	 */
-	ImageLoader *getLoader(const Common::String &fileType);
-};
+	// ImageDecoder API
+	void destroy() override;
+	const Graphics::Surface *getSurface() const override { return _surface; }
+	const byte *getPalette() const override { return _palette; }
+	uint16 getPaletteColorCount() const override { return _paletteColorCount; }
 
-/**
- * The generic image loader interface.  Image loaders should override
- * the load method to load an image from a U4FILE and register
- * themselves with registerLoader.  By convention, the type parameter
- * of load and registerLoader is the standard mime type of the image
- * file (e.g. image/png) or an xu4 specific mime type
- * (e.g. image/x-u4...).
- */
-class ImageLoader {
 protected:
+	Graphics::Surface *_surface;
+	const byte *_palette;
+	uint16 _paletteColorCount;
+	int _width, _height, _bpp;
+
 	/**
 	 * Fill in the image pixel data from an uncompressed string of bytes.
 	 */
-	static void setFromRawData(Image *image, int width, int height, int bpp, const byte *rawData);
+	void setFromRawData(const byte *rawData);
 
 	/**
-	 * Sets the image from a source image
+	 * Get the expected pixel format based on the value of _bpp.
 	 */
-	static void setFromSurface(Image *image, const Graphics::ManagedSurface &src);
-public:
-	ImageLoader() {}
-	virtual ~ImageLoader() {}
-	virtual Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) = 0;
+	Graphics::PixelFormat getPixelFormatForBpp() const;
 };
 
 } // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/gfx/imageloader_fmtowns.cpp b/engines/ultima/ultima4/gfx/imageloader_fmtowns.cpp
index c7b70c2df7f..2dfb549239b 100644
--- a/engines/ultima/ultima4/gfx/imageloader_fmtowns.cpp
+++ b/engines/ultima/ultima4/gfx/imageloader_fmtowns.cpp
@@ -19,105 +19,68 @@
  *
  */
 
-#include "ultima/ultima4/core/config.h"
 #include "ultima/ultima4/core/utils.h"
-#include "ultima/ultima4/gfx/image.h"
-#include "ultima/ultima4/gfx/imageloader.h"
 #include "ultima/ultima4/gfx/imageloader_fmtowns.h"
 #include "ultima/ultima4/gfx/imageloader_u4.h"
+
 #include "common/stream.h"
+#include "common/textconsole.h"
+#include "graphics/surface.h"
 
 namespace Ultima {
 namespace Ultima4 {
 
-Image *FMTOWNSImageLoader::load(Common::SeekableReadStream &stream, int width, int height, int bpp) {
-	if (width == -1 || height == -1 || bpp == -1) {
+bool FMTOWNSImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+	destroy();
+
+	if (_width == -1 || _height == -1 || _bpp == -1) {
 		error("dimensions not set for fmtowns image");
 	}
 
-	assertMsg((bpp == 16) | (bpp == 4), "invalid bpp: %d", bpp);
+	assertMsg((_bpp == 16) | (_bpp == 4), "invalid bpp: %d", _bpp);
 
 	int rawLen = stream.size() - _offset;
+	int requiredLength = (_width * _height * _bpp / 8);
+	if (rawLen < requiredLength) {
+		warning("FMTOWNS Image of size %d does not fit anticipated size %d", rawLen, requiredLength);
+		return false;
+	}
+
 	stream.seek(_offset, 0);
 	byte *raw = (byte *) malloc(rawLen);
 	stream.read(raw, rawLen);
 
-	int requiredLength = (width * height * bpp / 8);
-	if (rawLen < requiredLength) {
-		if (raw)
-			free(raw);
-		warning("FMTOWNS Image of size %d does not fit anticipated size %d", rawLen, requiredLength);
-		return nullptr;
-	}
 
-	Image *image = Image::create(width, height, bpp <= 8, Image::HARDWARE);
-	if (!image) {
-		if (raw)
-			free(raw);
-		return nullptr;
-	}
+	if (_bpp == 4) {
+		_surface = new Graphics::Surface();
+		_surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8());
+		setFromRawData(raw);
 
-	if (bpp == 4) {
 		U4PaletteLoader pal;
-		image->setPalette(pal.loadEgaPalette(), 16);
-		setFromRawData(image, width, height, bpp, raw);
-//      if (width % 2)
-//          error("FMTOWNS 4bit images cannot handle widths not divisible by 2!");
-//      byte nibble_mask = 0x0F;
-//        for (int y = 0; y < height; y++)
-// {
-//            for (int x = 0; x < width; x+=2)
-// {
-//              int byte = raw[(y * width + x) / 2];
-//              image->putPixelIndex(x  ,y,(byte & nibble_mask)  << 4);
-//              image->putPixelIndex(x+1,y,(byte              )      );
-//            }
-//        }
+		_palette = pal.loadEgaPalette();
+		_paletteColorCount = 16;
 	}
 
 
-	if (bpp == 16) {
-
-		//The FM towns uses 16 bits for graphics. I'm assuming 5R 5G 5B and 1 Misc bit.
-		//Please excuse my ugly byte manipulation code
-
-		//Masks
-		//------------------------  //  0000000011111111    --Byte 0 and 1
-		//------------------------  //  RRRRRGGGGGBBBBB?
-		byte low5 = 0x1F;          //  11111000--------    low5
-		byte high6 = (byte)~3U;    //  --------00111111    high6
-		byte high3 = (byte)~31U;   //  00000111--------    high3
-		byte low2 = 3;             //  --------11000000    low2
-		byte lastbit = 128;        //  --------00000001    low2
-		// Warning, this diagram is left-to-right, not standard right-to-left
-
-		for (int y = 0; y < height; y++) {
-			for (int x = 0; x < width; x++) {
-				byte byte0 = raw[(y * width + x) * 2];
-				byte byte1 = raw[(y * width + x) * 2 + 1];
+	if (_bpp == 16) {
+		_surface = new Graphics::Surface();
+		_surface->create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 1, 5, 10, 0, 15));
 
-				int r = (byte0 & low5);
-				r <<= 3;
+		uint16 *dst = (uint16 *)_surface->getPixels();
+		const uint16 *src = (const uint16 *)raw;
 
-				int g = (byte0 & high3) >> 5;
-				g |= ((byte1 & low2) << 3);
-				g <<= 3;
-
-				int b = byte1 & high6;
-				b <<= 1;
-
-				// TODO: Previously r & b were reversed. See if this proper
-				// order is correct, and if not properly swap value calculations
-				image->putPixel(x, y, r, g, b,
-					lastbit & byte1 ? IM_TRANSPARENT : IM_OPAQUE);
+		for (int y = 0; y < _height; y++) {
+			for (int x = 0; x < _width; x++) {
+				dst[x] = FROM_LE_16(*src++) ^ 0x8000;
 			}
+
+			dst = (uint16 *)((uint8 *)dst + _surface->pitch);
 		}
 	}
 
-
 	free(raw);
 
-	return image;
+	return true;
 }
 
 } // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/gfx/imageloader_fmtowns.h b/engines/ultima/ultima4/gfx/imageloader_fmtowns.h
index 47e4a0bae4d..a7f0b5ca213 100644
--- a/engines/ultima/ultima4/gfx/imageloader_fmtowns.h
+++ b/engines/ultima/ultima4/gfx/imageloader_fmtowns.h
@@ -27,17 +27,14 @@
 namespace Ultima {
 namespace Ultima4 {
 
-class FMTOWNSImageLoader : public ImageLoader {
+class FMTOWNSImageDecoder : public U4ImageDecoder {
 protected:
 	int _offset;
 public:
-	FMTOWNSImageLoader(int offset) : _offset(offset) {}
-	virtual ~FMTOWNSImageLoader() {}
+	FMTOWNSImageDecoder(int width, int height, int bpp, int offset)
+	  : U4ImageDecoder(width, height, bpp), _offset(offset) {}
 
-	/**
-	 * Loads in an FM TOWNS files, which we assume is 16 bits.
-	 */
-	Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) override;
+	bool loadStream(Common::SeekableReadStream &stream) override;
 };
 
 } // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/gfx/imageloader_png.cpp b/engines/ultima/ultima4/gfx/imageloader_png.cpp
deleted file mode 100644
index 082d735f5c6..00000000000
--- a/engines/ultima/ultima4/gfx/imageloader_png.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "ultima/ultima4/gfx/image.h"
-#include "ultima/ultima4/gfx/imageloader.h"
-#include "ultima/ultima4/gfx/imageloader_png.h"
-#include "common/stream.h"
-#include "image/png.h"
-
-namespace Ultima {
-namespace Ultima4 {
-
-Image *PngImageLoader::load(Common::SeekableReadStream &stream, int width, int height, int bpp) {
-	if (width != -1 || height != -1 || bpp != -1) {
-		warning("dimensions set for PNG image, will be ignored");
-	}
-
-	::Image::PNGDecoder decoder;
-	if (!decoder.loadStream(stream))
-		return nullptr;
-
-	const Graphics::Surface *img = decoder.getSurface();
-	bpp = img->format.bpp();
-	if (img->format.bytesPerPixel == 1)
-		bpp = decoder.getPaletteColorCount() == 256 ? 8 : 4;
-
-	Image *image = Image::create(img->w, img->h, bpp == 4 || bpp == 8, Image::HARDWARE);
-	image->blitFrom(*img);
-
-	if (img->format.bytesPerPixel == 1) {
-		int palCount = decoder.getPaletteColorCount();
-		const byte *pal = decoder.getPalette();
-
-		RGBA *palette = new RGBA[palCount];
-		for (int c = 0; c < palCount; ++c, pal += 3) {
-			palette[c].r = pal[0];
-			palette[c].g = pal[1];
-			palette[c].b = pal[2];
-			palette[c].a = IM_OPAQUE;
-		}
-
-		image->setPalette(palette, palCount);
-		delete[] palette;
-	}
-
-	return image;
-}
-
-} // End of namespace Ultima4
-} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/gfx/imageloader_png.h b/engines/ultima/ultima4/gfx/imageloader_png.h
deleted file mode 100644
index b9d1153bd7b..00000000000
--- a/engines/ultima/ultima4/gfx/imageloader_png.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef ULTIMA4_GFX_IMAGELOADER_PNG_H
-#define ULTIMA4_GFX_IMAGELOADER_PNG_H
-
-#include "ultima/ultima4/gfx/imageloader.h"
-
-namespace Ultima {
-namespace Ultima4 {
-
-/**
- * Loader for PNG images.  All PNG images should be supported: indexed
- * images with palette, or true color, with or without an alpha
- * channel.
- */
-class PngImageLoader : public ImageLoader {
-public:
-	virtual ~PngImageLoader() {}
-
-	/**
-	 * Loads in the PNG with the libpng library.
-	 */
-	Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) override;
-};
-
-} // End of namespace Ultima4
-} // End of namespace Ultima
-
-#endif
diff --git a/engines/ultima/ultima4/gfx/imageloader_u4.cpp b/engines/ultima/ultima4/gfx/imageloader_u4.cpp
index 7bb1798bee1..0bd569f0e16 100644
--- a/engines/ultima/ultima4/gfx/imageloader_u4.cpp
+++ b/engines/ultima/ultima4/gfx/imageloader_u4.cpp
@@ -22,70 +22,73 @@
 #include "ultima/ultima4/core/config.h"
 #include "ultima/ultima4/core/utils.h"
 #include "ultima/ultima4/core/lzw/u4decode.h"
-#include "ultima/ultima4/gfx/image.h"
-#include "ultima/ultima4/gfx/imageloader.h"
 #include "ultima/ultima4/gfx/imageloader_u4.h"
 #include "ultima/ultima4/filesys/rle.h"
+
 #include "common/file.h"
+#include "graphics/surface.h"
 
 namespace Ultima {
 namespace Ultima4 {
 
-RGBA *U4PaletteLoader::_bwPalette = nullptr;
-RGBA *U4PaletteLoader::_egaPalette = nullptr;
-RGBA *U4PaletteLoader::_vgaPalette = nullptr;
+const byte U4PaletteLoader::_bwPalette[2 * 3] = {
+	0, 0, 0,
+	255, 255, 255
+};
+byte *U4PaletteLoader::_egaPalette = nullptr;
+byte *U4PaletteLoader::_vgaPalette = nullptr;
 
-Image *U4RawImageLoader::load(Common::SeekableReadStream &stream, int width, int height, int bpp) {
-	if (width == -1 || height == -1 || bpp == -1) {
+bool U4RawImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+	if (_width == -1 || _height == -1 || _bpp == -1) {
 		error("dimensions not set for u4raw image");
 	}
 
-	assertMsg(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 24 || bpp == 32, "invalid bpp: %d", bpp);
+	assertMsg(_bpp == 1 || _bpp == 4 || _bpp == 8 || _bpp == 24 || _bpp == 32, "invalid bpp: %d", _bpp);
 
 	long rawLen = stream.size();
 	byte *raw = (byte *)malloc(rawLen);
 	stream.read(raw, rawLen);
 
-	long requiredLength = (width * height * bpp / 8);
+	long requiredLength = (_width * _height * _bpp / 8);
 	if (rawLen < requiredLength) {
 		if (raw)
 			free(raw);
 		warning("u4Raw Image of size %ld does not fit anticipated size %ld", rawLen, requiredLength);
-		return nullptr;
+		return false;
 	}
 
-	Image *image = Image::create(width, height, bpp <= 8, Image::HARDWARE);
-	if (!image) {
-		if (raw)
-			free(raw);
-		return nullptr;
-	}
+	_surface = new Graphics::Surface();
+	_surface->create(_width, _height, getPixelFormatForBpp());
 
 	U4PaletteLoader paletteLoader;
-	if (bpp == 8)
-		image->setPalette(paletteLoader.loadVgaPalette(), 256);
-	else if (bpp == 4)
-		image->setPalette(paletteLoader.loadEgaPalette(), 16);
-	else if (bpp == 1)
-		image->setPalette(paletteLoader.loadBWPalette(), 2);
+	if (_bpp == 8) {
+		_palette = paletteLoader.loadVgaPalette();
+		_paletteColorCount = 256;
+	} else if (_bpp == 4) {
+		_palette = paletteLoader.loadEgaPalette();
+		_paletteColorCount = 16;
+	} else if (_bpp == 1) {
+		_palette = paletteLoader.loadBWPalette();
+		_paletteColorCount = 2;
+	}
 
-	setFromRawData(image, width, height, bpp, raw);
+	setFromRawData(raw);
 
 	free(raw);
 
-	return image;
+	return true;
 }
 
 /**
  * Loads in the rle-compressed image and apply the standard U4 16 or
  * 256 color palette.
  */
-Image *U4RleImageLoader::load(Common::SeekableReadStream &stream, int width, int height, int bpp) {
-	if (width == -1 || height == -1 || bpp == -1) {
+bool U4RleImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+	if (_width == -1 || _height == -1 || _bpp == -1) {
 		error("dimensions not set for u4rle image");
 	}
 
-	assertMsg(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 24 || bpp == 32, "invalid bpp: %d", bpp);
+	assertMsg(_bpp == 1 || _bpp == 4 || _bpp == 8 || _bpp == 24 || _bpp == 32, "invalid bpp: %d", _bpp);
 
 	long compressedLen = stream.size();
 	byte *compressed = (byte *) malloc(compressedLen);
@@ -95,44 +98,44 @@ Image *U4RleImageLoader::load(Common::SeekableReadStream &stream, int width, int
 	long rawLen = rleDecompressMemory(compressed, compressedLen, (void **) &raw);
 	free(compressed);
 
-	if (rawLen != (width * height * bpp / 8)) {
+	if (rawLen != (_width * _height * _bpp / 8)) {
 		if (raw)
 			free(raw);
-		return nullptr;
+		return false;
 	}
 
-	Image *image = Image::create(width, height, bpp <= 8, Image::HARDWARE);
-	if (!image) {
-		if (raw)
-			free(raw);
-		return nullptr;
-	}
+	_surface = new Graphics::Surface();
+	_surface->create(_width, _height, getPixelFormatForBpp());
 
 	U4PaletteLoader paletteLoader;
-	if (bpp == 8)
-		image->setPalette(paletteLoader.loadVgaPalette(), 256);
-	else if (bpp == 4)
-		image->setPalette(paletteLoader.loadEgaPalette(), 16);
-	else if (bpp == 1)
-		image->setPalette(paletteLoader.loadBWPalette(), 2);
+	if (_bpp == 8) {
+		_palette = paletteLoader.loadVgaPalette();
+		_paletteColorCount = 256;
+	} else if (_bpp == 4) {
+		_palette = paletteLoader.loadEgaPalette();
+		_paletteColorCount = 16;
+	} else if (_bpp == 1) {
+		_palette = paletteLoader.loadBWPalette();
+		_paletteColorCount = 2;
+	}
 
-	setFromRawData(image, width, height, bpp, raw);
+	setFromRawData(raw);
 
 	free(raw);
 
-	return image;
+	return true;
 }
 
 /**
  * Loads in the lzw-compressed image and apply the standard U4 16 or
  * 256 color palette.
  */
-Image *U4LzwImageLoader::load(Common::SeekableReadStream &stream, int width, int height, int bpp) {
-	if (width == -1 || height == -1 || bpp == -1) {
+bool U4LzwImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+	if (_width == -1 || _height == -1 || _bpp == -1) {
 		error("dimensions not set for u4lzw image");
 	}
 
-	assertMsg(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 24 || bpp == 32, "invalid bpp: %d", bpp);
+	assertMsg(_bpp == 1 || _bpp == 4 || _bpp == 8 || _bpp == 24 || _bpp == 32, "invalid bpp: %d", _bpp);
 
 	long compressedLen = stream.size();
 	byte *compressed = (byte *) malloc(compressedLen);
@@ -142,62 +145,51 @@ Image *U4LzwImageLoader::load(Common::SeekableReadStream &stream, int width, int
 	long rawLen = LZW::decompress_u4_memory(compressed, compressedLen, (void **) &raw);
 	free(compressed);
 
-	if (rawLen != (width * height * bpp / 8)) {
+	if (rawLen != (_width * _height * _bpp / 8)) {
 		if (raw)
 			free(raw);
-		return nullptr;
+		return false;
 	}
 
-	Image *image = Image::create(width, height, bpp <= 8, Image::HARDWARE);
-	if (!image) {
-		if (raw)
-			free(raw);
-		return nullptr;
-	}
+	_surface = new Graphics::Surface();
+	_surface->create(_width, _height, getPixelFormatForBpp());
 
 	U4PaletteLoader paletteLoader;
-	if (bpp == 8)
-		image->setPalette(paletteLoader.loadVgaPalette(), 256);
-	else if (bpp == 4)
-		image->setPalette(paletteLoader.loadEgaPalette(), 16);
-	else if (bpp == 1)
-		image->setPalette(paletteLoader.loadBWPalette(), 2);
+	if (_bpp == 8) {
+		_palette = paletteLoader.loadVgaPalette();
+		_paletteColorCount = 256;
+	} else if (_bpp == 4) {
+		_palette = paletteLoader.loadEgaPalette();
+		_paletteColorCount = 16;
+	} else if (_bpp == 1) {
+		_palette = paletteLoader.loadBWPalette();
+		_paletteColorCount = 2;
+	}
 
-	setFromRawData(image, width, height, bpp, raw);
+	setFromRawData(raw);
 
 	free(raw);
 
-	return image;
+	return true;
 }
 
+
 /**
  * Loads a simple black & white palette
  */
-RGBA *U4PaletteLoader::loadBWPalette() {
-	if (_bwPalette == nullptr) {
-		_bwPalette = new RGBA[2];
-
-		_bwPalette[0].r = 0;
-		_bwPalette[0].g = 0;
-		_bwPalette[0].b = 0;
-
-		_bwPalette[1].r = 255;
-		_bwPalette[1].g = 255;
-		_bwPalette[1].b = 255;
-
-	}
+const byte *U4PaletteLoader::loadBWPalette() {
 	return _bwPalette;
 }
 
 /**
  * Loads the basic EGA palette from egaPalette.xml
  */
-RGBA *U4PaletteLoader::loadEgaPalette() {
+const byte *U4PaletteLoader::loadEgaPalette() {
 	if (_egaPalette == nullptr) {
 		int index = 0;
 		const Config *config = Config::getInstance();
 
-		_egaPalette = new RGBA[16];
+		_egaPalette = new byte[16 * 3];
 
 		Std::vector<ConfigElement> paletteConf = config->getElement("egaPalette").getChildren();
 		for (Std::vector<ConfigElement>::iterator i = paletteConf.begin(); i != paletteConf.end(); i++) {
@@ -205,11 +197,9 @@ RGBA *U4PaletteLoader::loadEgaPalette() {
 			if (i->getName() != "color")
 				continue;
 
-			_egaPalette[index].r = i->getInt("red");
-			_egaPalette[index].g = i->getInt("green");
-			_egaPalette[index].b = i->getInt("blue");
-
-			index++;
+			_egaPalette[index++] = i->getInt("red");
+			_egaPalette[index++] = i->getInt("green");
+			_egaPalette[index++] = i->getInt("blue");
 		}
 	}
 	return _egaPalette;
@@ -218,18 +208,17 @@ RGBA *U4PaletteLoader::loadEgaPalette() {
 /**
  * Load the 256 color VGA palette from a file.
  */
-RGBA *U4PaletteLoader::loadVgaPalette() {
+const byte *U4PaletteLoader::loadVgaPalette() {
 	if (_vgaPalette == nullptr) {
 		Common::File pal;
 		if (!pal.open("u4vga.pal"))
 			return nullptr;
 
-		_vgaPalette = new RGBA[256];
+		_vgaPalette = new byte[256 * 3];
+		pal.read(_vgaPalette, 256 * 3);
 
-		for (int i = 0; i < 256; i++) {
-			_vgaPalette[i].r = pal.readByte() * 255 / 63;
-			_vgaPalette[i].g = pal.readByte() * 255 / 63;
-			_vgaPalette[i].b = pal.readByte() * 255 / 63;
+		for (int i = 0; i < 256 * 3; i++) {
+			_vgaPalette[i] = _vgaPalette[i] * 255 / 63;
 		}
 	}
 
diff --git a/engines/ultima/ultima4/gfx/imageloader_u4.h b/engines/ultima/ultima4/gfx/imageloader_u4.h
index 7945281b414..22dce4825dc 100644
--- a/engines/ultima/ultima4/gfx/imageloader_u4.h
+++ b/engines/ultima/ultima4/gfx/imageloader_u4.h
@@ -27,53 +27,57 @@
 namespace Ultima {
 namespace Ultima4 {
 
-struct RGBA;
-
 /**
- * Loader for U4 raw images.  Raw images are just an uncompressed
+ * Decoder for U4 raw images.  Raw images are just an uncompressed
  * stream of pixel data with no palette information (e.g. shapes.ega,
- * charset.ega).  This loader handles the original 4-bit images, as
+ * charset.ega).  This decoder handles the original 4-bit images, as
  * well as the 8-bit VGA upgrade images.
  */
-class U4RawImageLoader : public ImageLoader {
+class U4RawImageDecoder : public U4ImageDecoder {
 public:
-	/**
-	 * Loads in the raw image and apply the standard U4 16 or 256 color palette.
-	 */
-	Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) override;
+	U4RawImageDecoder(int width, int height, int bpp)
+	  : U4ImageDecoder(width, height, bpp) {}
+
+	bool loadStream(Common::SeekableReadStream &stream) override;
 };
 
 /**
- * Loader for U4 images with RLE compression.  Like raw images, the
+ * Decoder for U4 images with RLE compression.  Like raw images, the
  * data is just a stream of pixel data with no palette information
- * (e.g. start.ega, rune_*.ega).  This loader handles the original
+ * (e.g. start.ega, rune_*.ega).  This decoder handles the original
  * 4-bit images, as well as the 8-bit VGA upgrade images.
  */
-class U4RleImageLoader : public ImageLoader {
+class U4RleImageDecoder : public U4ImageDecoder {
 public:
-	Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) override;
+	U4RleImageDecoder(int width, int height, int bpp)
+	  : U4ImageDecoder(width, height, bpp) {}
+
+	bool loadStream(Common::SeekableReadStream &stream) override;
 };
 
 /**
- * Loader for U4 images with LZW compression.  Like raw images, the
+ * Decoder for U4 images with LZW compression.  Like raw images, the
  * data is just a stream of pixel data with no palette information
- * (e.g. title.ega, tree.ega).  This loader handles the original 4-bit
+ * (e.g. title.ega, tree.ega).  This decoder handles the original 4-bit
  * images, as well as the 8-bit VGA upgrade images.
  */
-class U4LzwImageLoader : public ImageLoader {
+class U4LzwImageDecoder : public U4ImageDecoder {
 public:
-	Image *load(Common::SeekableReadStream &stream, int width, int height, int bpp) override;
+	U4LzwImageDecoder(int width, int height, int bpp)
+	  : U4ImageDecoder(width, height, bpp) {}
+
+	bool loadStream(Common::SeekableReadStream &stream) override;
 };
 
 class U4PaletteLoader {
-	static RGBA *_bwPalette;
-	static RGBA *_egaPalette;
-	static RGBA *_vgaPalette;
+	static const byte _bwPalette[2 * 3];
+	static byte *_egaPalette;
+	static byte *_vgaPalette;
 
 public:
-	RGBA *loadBWPalette();
-	RGBA *loadEgaPalette();
-	RGBA *loadVgaPalette();
+	const byte *loadBWPalette();
+	const byte *loadEgaPalette();
+	const byte *loadVgaPalette();
 };
 
 } // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/gfx/imagemgr.cpp b/engines/ultima/ultima4/gfx/imagemgr.cpp
index 50dba67a549..09bd94b4afa 100644
--- a/engines/ultima/ultima4/gfx/imagemgr.cpp
+++ b/engines/ultima/ultima4/gfx/imagemgr.cpp
@@ -20,13 +20,16 @@
  */
 
 #include "ultima/ultima4/gfx/image.h"
-#include "ultima/ultima4/gfx/imageloader.h"
+#include "ultima/ultima4/gfx/imageloader_u4.h"
+#include "ultima/ultima4/gfx/imageloader_fmtowns.h"
 #include "ultima/ultima4/gfx/imagemgr.h"
 #include "ultima/ultima4/controllers/intro_controller.h"
 #include "ultima/ultima4/core/config.h"
 #include "ultima/ultima4/core/settings.h"
 #include "ultima/ultima4/ultima4.h"
 
+#include "image/png.h"
+
 namespace Ultima {
 namespace Ultima4 {
 
@@ -551,17 +554,32 @@ ImageInfo *ImageMgr::get(const Common::String &name, bool returnUnscaled) {
 		if (info->_filetype.empty())
 			info->_filetype = guessFileType(info->_filename);
 		Common::String filetype = info->_filetype;
-		ImageLoader *loader = g_ultima->_imageLoaders->getLoader(filetype);
-		if (loader == nullptr) {
+		::Image::ImageDecoder *decoder = createDecoder(filetype, info->_width, info->_height, info->_depth);
+		if (decoder == nullptr) {
 			warning("can't find loader to load image \"%s\" with type \"%s\"", info->_filename.c_str(), filetype.c_str());
 		} else {
-			unscaled = loader->load(*file, info->_width, info->_height, info->_depth);
-			if (info->_width == -1) {
-				// Write in the values for later use.
-				info->_width = unscaled->width();
-				info->_height = unscaled->height();
-				// ###            info->depth = ???
+			if (!decoder->loadStream(*file)) {
+				warning("can't load image \"%s\" with type \"%s\"", info->_filename.c_str(), filetype.c_str());
+			} else {
+				const Graphics::Surface *surface = decoder->getSurface();
+				unscaled = Image::create(surface->w, surface->h, decoder->hasPalette(), Image::HARDWARE);
+				unscaled->blitFrom(*surface);
+
+				if (decoder->hasPalette()) {
+					int palCount = decoder->getPaletteColorCount();
+					const byte *pal = decoder->getPalette();
+					unscaled->setPalette(pal, palCount);
+				}
+
+				if (info->_width == -1) {
+					// Write in the values for later use.
+					info->_width = unscaled->width();
+					info->_height = unscaled->height();
+					// ###            info->depth = ???
+				}
 			}
+
+			delete decoder;
 		}
 
 		delete file;
@@ -681,6 +699,20 @@ void ImageMgr::update(Settings *newSettings) {
 	_baseSet = getSet(setname);
 }
 
+::Image::ImageDecoder *ImageMgr::createDecoder(const Common::String &fileType, int width, int height, int bpp) {
+	if (fileType == "image/png")
+		return new ::Image::PNGDecoder();
+	if (fileType == "image/x-u4raw")
+		return new U4RawImageDecoder(width, height, bpp);
+	if (fileType == "image/x-u4rle")
+		return new U4RleImageDecoder(width, height, bpp);
+	if (fileType == "image/x-u4lzw")
+		return new U4LzwImageDecoder(width, height, bpp);
+	if (fileType == "image/fmtowns-tif")
+		return new FMTOWNSImageDecoder(width, height, bpp, 510);
+	return nullptr;
+}
+
 ImageSet::~ImageSet() {
 	for (Common::HashMap<Common::String, ImageInfo *>::iterator i = _info.begin(); i != _info.end(); i++) {
 		ImageInfo *imageInfo = i->_value;
diff --git a/engines/ultima/ultima4/gfx/imagemgr.h b/engines/ultima/ultima4/gfx/imagemgr.h
index a2dc8857328..6c54f4bbac9 100644
--- a/engines/ultima/ultima4/gfx/imagemgr.h
+++ b/engines/ultima/ultima4/gfx/imagemgr.h
@@ -30,6 +30,10 @@ namespace Common {
 class File;
 }
 
+namespace Image {
+class ImageDecoder;
+}
+
 namespace Ultima {
 namespace Ultima4 {
 
@@ -191,6 +195,11 @@ private:
 	 */
 	void update(Settings *newSettings);
 
+	/**
+	 * Create an image decoder for the specified file type.
+	 */
+	::Image::ImageDecoder *createDecoder(const Common::String &fileType, int width, int height, int bpp);
+
 	static ImageMgr *_instance;
 	Common::HashMap<Common::String, ImageSet *> _imageSets;
 	Std::vector<Common::String> _imageSetNames;
diff --git a/engines/ultima/ultima4/ultima4.cpp b/engines/ultima/ultima4/ultima4.cpp
index 08c17a59562..93bebcb76cf 100644
--- a/engines/ultima/ultima4/ultima4.cpp
+++ b/engines/ultima/ultima4/ultima4.cpp
@@ -39,7 +39,6 @@
 #include "ultima/ultima4/game/person.h"
 #include "ultima/ultima4/game/weapon.h"
 #include "ultima/ultima4/gfx/screen.h"
-#include "ultima/ultima4/gfx/imageloader.h"
 #include "ultima/ultima4/gfx/imagemgr.h"
 #include "ultima/ultima4/map/maploader.h"
 #include "ultima/ultima4/map/shrine.h"
@@ -59,7 +58,7 @@ Ultima4Engine::Ultima4Engine(OSystem *syst, const Ultima::UltimaGameDescription
 		Shared::UltimaEngine(syst, gameDesc), _saveSlotToLoad(-1), _armors(nullptr),
 		_codex(nullptr), _config(nullptr), _context(nullptr), _death(nullptr),
 		_dialogueLoaders(nullptr), _game(nullptr), _items(nullptr), _music(nullptr),
-		_imageLoaders(nullptr), _mapLoaders(nullptr), _moongates(nullptr),
+		_mapLoaders(nullptr), _moongates(nullptr),
 		_responseParts(nullptr), _saveGame(nullptr), _screen(nullptr), _shrines(nullptr),
 		_soundManager(nullptr), _spells(nullptr), _tileMaps(nullptr), _tileRules(nullptr),
 		_tileSets(nullptr), _weapons(nullptr) {
@@ -92,7 +91,6 @@ Ultima4Engine::~Ultima4Engine() {
 	delete _death;
 	delete _dialogueLoaders;
 	delete _game;
-	delete _imageLoaders;
 	delete _items;
 	delete _mapLoaders;
 	delete _moongates;
@@ -138,7 +136,6 @@ bool Ultima4Engine::initialize() {
 	_tileSets = new TileSets();
 	_tileMaps = new TileMaps();
 	_game = new GameController();
-	_imageLoaders = new ImageLoaders();
 	_saveGame = new SaveGame();
 	_weapons = new Weapons();
 
diff --git a/engines/ultima/ultima4/ultima4.h b/engines/ultima/ultima4/ultima4.h
index 8089c58bf52..720ad7dde7f 100644
--- a/engines/ultima/ultima4/ultima4.h
+++ b/engines/ultima/ultima4/ultima4.h
@@ -34,7 +34,6 @@ class Config;
 class Context;
 class Death;
 class DialogueLoaders;
-class ImageLoaders;
 class Items;
 class GameController;
 class MapLoaders;
@@ -73,7 +72,6 @@ public:
 	Context *_context;
 	Death *_death;
 	DialogueLoaders *_dialogueLoaders;
-	ImageLoaders *_imageLoaders;
 	GameController *_game;
 	Items *_items;
 	MapLoaders *_mapLoaders;




More information about the Scummvm-git-logs mailing list