[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