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