1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
|
/* 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/>.
*
*/
//=============================================================================
//
// SpriteFile class handles sprite file parsing and streaming sprites.
// SpriteFileWriter manages writing sprites into the output stream one by one,
// accumulating index information, and may therefore be suitable for a variety
// of situations.
//
//=============================================================================
#ifndef AGS_SHARED_AC_SPRITE_FILE_H
#define AGS_SHARED_AC_SPRITE_FILE_H
#include "ags/shared/core/types.h"
#include "common/std/memory.h"
#include "common/std/vector.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
class Bitmap;
// TODO: research old version differences
enum SpriteFileVersion {
kSprfVersion_Undefined = 0,
kSprfVersion_Uncompressed = 4,
kSprfVersion_Compressed = 5,
kSprfVersion_Last32bit = 6,
kSprfVersion_64bit = 10,
kSprfVersion_HighSpriteLimit = 11,
kSprfVersion_StorageFormats = 12,
kSprfVersion_Current = kSprfVersion_StorageFormats
};
enum SpriteIndexFileVersion {
kSpridxfVersion_Initial = 1,
kSpridxfVersion_Last32bit = 2,
kSpridxfVersion_64bit = 10,
kSpridxfVersion_HighSpriteLimit = 11,
kSpridxfVersion_Current = kSpridxfVersion_HighSpriteLimit
};
// Instructions to how the sprites are allowed to be stored
enum SpriteStorage {
// When possible convert the sprite into another format for less disk space
// e.g. save 16/32-bit images as 8-bit colormaps with palette
kSprStore_OptimizeForSize = 0x01
};
// Format in which the sprite's pixel data is stored
enum SpriteFormat {
kSprFmt_Undefined = 0, // undefined, or keep as-is
// Encoded as a 8-bit colormap with palette of 24-bit RGB values
kSprFmt_PaletteRgb888 = 32,
// Encoded as a 8-bit colormap with palette of 32-bit ARGB values
kSprFmt_PaletteArgb8888 = 33,
// Encoded as a 8-bit colormap with palette of 16-bit RGB565 values
kSprFmt_PaletteRgb565 = 34
};
enum SpriteCompression {
kSprCompress_None = 0,
kSprCompress_RLE,
kSprCompress_LZW,
kSprCompress_Deflate
};
typedef int32_t sprkey_t;
// SpriteFileIndex contains sprite file's table of contents
struct SpriteFileIndex {
int SpriteFileIDCheck = 0; // tag matching sprite file and index file
std::vector<int16_t> Widths;
std::vector<int16_t> Heights;
std::vector<soff_t> Offsets;
inline size_t GetCount() const {
return Offsets.size();
}
inline sprkey_t GetLastSlot() const {
return (sprkey_t)GetCount() - 1;
}
};
// Invidual sprite data header (as read from the file)
struct SpriteDatHeader {
int BPP = 0; // color depth (bytes per pixel); or input format
SpriteFormat SFormat = kSprFmt_Undefined; // storage format
uint32_t PalCount = 0; // palette length, if applicable to storage format
SpriteCompression Compress = kSprCompress_None; // compression type
int Width = 0; // sprite's width
int Height = 0; // sprite's height
SpriteDatHeader() = default;
SpriteDatHeader(int bpp, SpriteFormat sformat = kSprFmt_Undefined,
uint32_t pal_count = 0, SpriteCompression compress = kSprCompress_None,
int w = 0, int h = 0) : BPP(bpp), SFormat(sformat), PalCount(pal_count),
Compress(compress), Width(w), Height(h) {
}
};
// SpriteFile opens a sprite file for reading, reports general information,
// and lets read sprites in any order.
class SpriteFile {
public:
// Standart sprite file and sprite index names
static const char *DefaultSpriteFileName;
static const char *DefaultSpriteIndexName;
SpriteFile();
// Loads sprite reference information and inits sprite stream
HError OpenFile(const String &filename, const String &sprindex_filename,
std::vector<Size> &metrics);
// Closes stream; no reading will be possible unless opened again
void Close();
int GetStoreFlags() const;
// Tells if bitmaps in the file are compressed
SpriteCompression GetSpriteCompression() const;
// Tells the highest known sprite index
sprkey_t GetTopmostSprite() const;
// Loads sprite index file
bool LoadSpriteIndexFile(const String &filename, int expectedFileID,
soff_t spr_initial_offs, sprkey_t topmost, std::vector<Size> &metrics);
// Rebuilds sprite index from the main sprite file
HError RebuildSpriteIndex(Stream *in, sprkey_t topmost,
std::vector<Size> &metrics);
// Loads an image data and creates a ready bitmap
HError LoadSprite(sprkey_t index, Bitmap *&sprite);
// Loads a raw sprite element data into the buffer, stores header info separately
HError LoadRawData(sprkey_t index, SpriteDatHeader &hdr, std::vector<uint8_t> &data);
private:
// Seek stream to sprite
void SeekToSprite(sprkey_t index);
// Internal sprite reference
struct SpriteRef {
soff_t Offset = 0; // data offset
size_t RawSize = 0; // file size of element, in bytes
// TODO: RawSize is currently unused, due to incompleteness of spriteindex format
};
// Array of sprite references
std::vector<SpriteRef> _spriteData;
std::unique_ptr<Stream> _stream; // the sprite stream
SpriteFileVersion _version = kSprfVersion_Current;
int _storeFlags = 0; // storage flags, specify how sprites may be stored
SpriteCompression _compress = kSprCompress_None; // sprite compression typ
sprkey_t _curPos; // current stream position (sprite slot)
};
// SpriteFileWriter class writes a sprite file in a requested format.
// Start using it by calling Begin, write ready bitmaps or copy raw sprite data
// over slot by slot, then call Finalize to let it close the format correctly.
class SpriteFileWriter {
public:
SpriteFileWriter(std::unique_ptr<Stream> &out);
~SpriteFileWriter() {
}
// Get the sprite index, accumulated after write
const SpriteFileIndex &GetIndex() const {
return _index;
}
// Initializes new sprite file format;
// store_flags are SpriteStorage;
// optionally hint how many sprites will be written.
void Begin(int store_flags, SpriteCompression compress, sprkey_t last_slot = -1);
// Writes a bitmap into file, compressing if necessary
void WriteBitmap(Bitmap *image);
// Writes an empty slot marker
void WriteEmptySlot();
// Writes a raw sprite data without any additional processing
void WriteRawData(const SpriteDatHeader &hdr, const uint8_t *data, size_t data_sz);
// Finalizes current format; no further writing is possible after this
void Finalize();
private:
// Writes prepared image data in a proper file format, following explicit data_bpp rule
void WriteSpriteData(const SpriteDatHeader &hdr,
const uint8_t *im_data, size_t im_data_sz, int im_bpp,
const uint32_t palette[256]);
std::unique_ptr<Stream> &_out;
int _storeFlags = 0;
SpriteCompression _compress = kSprCompress_None;
soff_t _lastSlotPos = -1; // last slot save position in file
// sprite index accumulated on write for reporting back to user
SpriteFileIndex _index;
// compression buffer
std::vector<uint8_t> _membuf;
};
// Saves all sprites to file; fills in index data for external use.
// TODO: refactor to be able to save main file and index file separately (separate function for gather data?)
// Accepts available sprites as pairs of bool and Bitmap pointer, where boolean value
// tells if sprite exists and Bitmap pointer may be null;
// If a sprite's bitmap is missing, it will try reading one from the input file stream.
int SaveSpriteFile(const String &save_to_file,
const std::vector<std::pair<bool, Bitmap *> > &sprites,
SpriteFile *read_from_file, // optional file to read missing sprites from
int store_flags, SpriteCompression compress, SpriteFileIndex &index);
// Saves sprite index table in a separate file
extern int SaveSpriteIndex(const String &filename, const SpriteFileIndex &index);
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif
|