1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2011 by The Allacrost Project 3 // Copyright (C) 2012-2016 by Bertram (Valyria Tear) 4 // All Rights Reserved 5 // 6 // This code is licensed under the GNU GPL version 2. It is free software 7 // and you may modify it and/or redistribute it under the terms of this license. 8 // See http://www.gnu.org/copyleft/gpl.html for details. 9 /////////////////////////////////////////////////////////////////////////////// 10 11 /** **************************************************************************** 12 *** \file image_base.h 13 *** \author Tyler Olsen, roots@allacrost.org 14 *** \author Yohann Ferreira, yohann ferreira orange fr 15 *** \brief Header file for image base classes 16 *** 17 *** This file contains several classes that represent various types of images 18 *** and image data manipulated by the video engine. All of these classes are 19 *** embedded in the private_video namespace, and thus are of no concern to 20 *** those who simply wish to use the video engine API. Below is a list and 21 *** short description of all the classes represented defined in this header: 22 *** 23 *** - <b>ImageMemory</b> is a class used for loading and manipulating raw 24 *** image data stored in a system side buffer (ie not in texture memory) 25 *** 26 *** - <b>BaseTexture</b> describes a sub-rectangle contained within a 27 *** texture sheet. In other words, it can essentially be viewed as a pointer 28 *** to an image's location in texture memory. It is an abstract class. 29 *** 30 *** - <b>ImageTexture</b> derives from BaseTexture and adds a filename 31 *** and tag information to the member data. This is used to internally 32 *** represent an image that has been loaded from a file and any special 33 *** properties of that image data. 34 *** 35 *** \note There are more derived classes from this set in other areas of the 36 *** code. In particular, there is a TextTexture and TextElement class 37 *** defined in the text.h header file. 38 *** ***************************************************************************/ 39 40 #ifndef __IMAGE_BASE_HEADER__ 41 #define __IMAGE_BASE_HEADER__ 42 43 #include "color.h" 44 #include "texture.h" 45 46 #include <string> 47 #include <vector> 48 49 namespace vt_video 50 { 51 52 namespace private_video 53 { 54 55 /** **************************************************************************** 56 *** \brief A wrapper around an image buffer in system memory 57 *** 58 *** This class is used to pass image texture data between the CPU and GPU. 59 *** There are also several routines for performing manipulations on the raw 60 *** image data. This class may also be used as a temporary holder for pixel 61 *** data. 62 *** 63 *** \note All of the members of this class are public, so you must be careful 64 *** not to assign them to an incorrect value. 65 *** 66 *** \todo Write copy constructor and copy assignment operator to avoid double 67 *** memory frees 68 *** ***************************************************************************/ 69 class ImageMemory 70 { 71 public: 72 ImageMemory(); 73 explicit ImageMemory(const SDL_Surface* surface); 74 ~ImageMemory()75 ~ImageMemory() 76 {} 77 GetWidth()78 size_t GetWidth() const { 79 return _width; 80 } 81 GetHeight()82 size_t GetHeight() const { 83 return _height; 84 } 85 GetSize2D()86 size_t GetSize2D() const { 87 return _width * _height; 88 } 89 GetBytesPerPixel()90 size_t GetBytesPerPixel() const { 91 return _rgb_format ? 3 : 4; 92 } 93 94 /** \brief Loads raw image data from a file and stores the data in the class members 95 *** \param filename The name of the image file to load. 96 *** \return True if the image was loaded successfully, false if it was not 97 **/ 98 bool LoadImage(const std::string &filename); 99 100 /** \brief Saves raw image data to a file 101 *** \param filename The full filename of the image to save in PNG format. 102 *** \return True if the image was saved successfully, false if it was not 103 **/ 104 bool SaveImage(const std::string &filename); 105 106 /** \brief Converts the image data to grayscale format 107 *** \note Calling this function when the image data is already grayscaled will create the 108 *** exact same grayscaled image, but still take CPU time to do the conversion. There is 109 *** no way 110 *** \note You can not convert from grayscale back to the original image. If you wish to 111 *** do that, you must re-load or otherwise re-create the original. 112 **/ 113 void ConvertToGrayscale(); 114 115 /** \brief Converts the RGBA pixel buffer to a RGB one 116 *** \note Upon conversion, this function will also reduced the memory size pointed to 117 *** by pixels to 3/4s of its original size, since the alpha information is no longer 118 *** neeeded. 119 **/ 120 void RGBAToRGB(); 121 122 /** \brief Set the class members by making a copy of a texture sheet 123 *** \param texture A pointer to the TexSheet to be copied 124 *** 125 *** This function effectively copies a texture (in video memory) to a system-side memory buffer 126 **/ 127 void CopyFromTexture(TexSheet *texture); 128 129 /** \brief Set the class members by making a copy of a texture sheet image 130 *** \param img A pointer to the image to be copied 131 *** 132 *** This function effectively copies an image (in video memory) to a system-side memory buffer 133 **/ 134 void CopyFromImage(BaseTexture *img); 135 136 /** \brief delete an image and allocate a new one of specified size 137 *** \param width_ width of the new image 138 *** \param heigt_ height of the new image 139 *** \throws std::bad_alloc when allocation failed (because std::vector can throw that) 140 *** \TODO use an enum instead of bool for better readability 141 **/ 142 void Resize(size_t width, size_t height, bool is_rgb); 143 144 //! \brief Wrapper of glGetTexImage on the image pixels. 145 void GlGetTexImage(); 146 147 //! \brief Wrapper of glTexSubImage on the image pixels at the given coordinates. 148 void GlTexSubImage(int32_t x, int32_t y); 149 150 //! \brief Wrapper of glReadPixels on the image pixels at the given coordinates. 151 void GlReadPixels(int32_t x, int32_t y); 152 153 //! \brief Copy a texture at given pixel coordinates. 154 void CopyFrom(const ImageMemory& src, uint32_t src_offset, uint32_t dst_bytes, uint32_t dst_offset); 155 void CopyFrom(const ImageMemory& src, uint32_t src_offset); 156 157 //! \brief Flip the image pixels vertically. 158 void VerticalFlip(); 159 160 private: 161 //! \brief The width of the image data (in pixels) 162 size_t _width; 163 164 //! \brief The height of the image data (in pixels) 165 size_t _height; 166 167 //! \brief Buffer of data, usually of size width * height * 4 (RGBA, 8 bits per component) 168 std::vector<uint8_t> _pixels; 169 170 //! \brief Set to true if the data is in RGB format, false if the data is in RGBA format. 171 bool _rgb_format; 172 }; // class ImageMemory 173 174 175 /** **************************************************************************** 176 *** \brief Represents the location and properties of an image in texture memory 177 *** 178 *** This class can be thought of as a pointer to the image in texture (GPU) 179 *** memory. The TextureManager singleton has a container filled with each 180 *** instance of this object (and its derivative classes), which primarily 181 *** serves to prevent the duplication of the same image data in more than one 182 *** location in texture memory. 183 *** 184 *** \note Whenever you create an instance of this class or one of its child 185 *** classes and you intend to have some piece of code use it, you MUST remember 186 *** to call AddReference() at least once, otherwise bad things can happen. 187 *** 188 *** \note Objects of this class are intended to be constructed via the new 189 *** operator. The copy constructor and copy assignment operator are kept 190 *** private because we do not wish to allow duplicate pointers to the same 191 *** texture data, as this greatly complicates the reference counting system. 192 *** 193 *** \note Although this class is not abstract, typically we do not create any 194 *** instances of it. Instead, we create instances of its derivative classes. 195 *** ***************************************************************************/ 196 class BaseTexture 197 { 198 friend class VideoEngine; 199 200 public: 201 BaseTexture(); 202 BaseTexture(uint32_t width_, uint32_t height_); 203 BaseTexture(TexSheet *texture_sheet_, uint32_t width_, uint32_t height_); 204 205 virtual ~BaseTexture(); 206 207 // ---------- Public members 208 209 //! \brief A pointer to the texture sheet where the image is contained. 210 TexSheet *texture_sheet; 211 212 //! \brief The image's width and height as stored in the texture sheet, in pixels 213 uint32_t width, height; 214 215 //! \brief The coordiates of where the image is located in the texture sheet (in pixels) 216 int32_t x, y; 217 218 /** \brief The actual uv coordinates. 219 *** This is a little redundant, but saves effort on floating point calcuations. 220 *** u1 and v1 are the upper-left UV coordinates, while u2 and v2 correspond to 221 *** the lower-right. They are expressed in the [0.0, 1.0] range. 222 **/ 223 float u1, v1, u2, v2; 224 225 //! \brief True if the image should be drawn smoothed (using GL_LINEAR) 226 bool smooth; 227 228 /** \brief The number of times that this image is refereced by ImageDescriptors 229 *** This is used to determine when the image may be safely deleted. 230 **/ 231 int32_t ref_count; 232 233 // ---------- Public methods 234 235 /** \brief Decrements the reference count by one 236 *** \return True if there are no more references to the image 237 **/ 238 bool RemoveReference(); 239 240 //! \brief Increments the reference count by one AddReference()241 void AddReference() { 242 ref_count++; 243 } 244 245 private: 246 BaseTexture(const BaseTexture ©); 247 BaseTexture &operator=(const BaseTexture ©); 248 }; // class BaseTexture 249 250 251 /** **************************************************************************** 252 *** \brief Represents a single image that is loaded and stored in a texture sheet. 253 *** 254 *** This object is intended to reperesent a texture image that was created by 255 *** loading an image file. The TextureManager singleton keeps a std::map of all 256 *** ImageTexture objects created, using the concatenated filename and tags of 257 *** each object as the map key. When creating a new ImageTexture object, you 258 *** should generally do the following: 259 *** 260 *** -# First make sure that the filename + tags is not already located in the 261 *** image map in the TextureController class 262 *** -# Invoke the class constructor if the map search found no matching entry 263 *** -# Call the TextureManager to insert the new image into a texture sheet 264 *** -# If insertion was successful, call AddReference() 265 *** -# If insertion was successful, add the new object to the TextureManager's 266 *** image map 267 *** 268 *** \note Like its base class, this class is only intended to be created via the 269 *** new operator, and the copy constructor and copy assignment operator are kept 270 *** private to avoid complex reference management requirements. 271 *** ***************************************************************************/ 272 class ImageTexture : public BaseTexture 273 { 274 public: 275 ImageTexture(const std::string &filename_, const std::string &tags_, int32_t width_, int32_t height_); 276 ImageTexture(TexSheet *texture_sheet_, const std::string &filename_, const std::string &tags_, int32_t width_, int32_t height_); 277 278 virtual ~ImageTexture() override; 279 280 // ---------- Public members 281 282 /** \brief The name of the image file where this texture data was loaded from 283 *** This is stored for every image file to prevent duplicate copies of the same image file data 284 *** in multiple ImageTextures, and also in case for when the image data needs to be reloaded. 285 *** The reload case may happen when a context change happens, such a screen resolution change or 286 *** a toggle between fullscreen and windowed modes. 287 **/ 288 std::string filename; 289 290 /** \brief Retains various tags used to uniquely identify the image when certain properties are applied 291 *** 292 *** Tags should always be presented in the same order, since the tag information is used in the key 293 *** to lookup the image in the TextureManager's image map. The list of tags below is sorted from highest 294 *** priority (should be at the beginning of the tag) to lowest priority (should be at the end of the tag). 295 *** 296 *** -# \<Xrow_ROWS>: used for multi image elements. "row" is the row number of this particular element 297 *** while "ROWS" is the total number of rows of elements in the multi image 298 *** -# \<Ycol_COLS>: used for multi image elements. "col" is the column number of this particular element 299 *** while "COLS" is the total number of columns of elements in the multi image 300 *** -# \<G>: used to indicate that this image texture has been converted to grayscale mode 301 *** 302 *** \note Please remember to document new tags here when they are added 303 **/ 304 std::string tags; 305 306 private: 307 ImageTexture(const ImageTexture ©); 308 ImageTexture &operator=(const ImageTexture ©); 309 }; // class ImageTexture : public BaseTexture 310 311 } // namespace private_video 312 313 } // namespace vt_video 314 315 #endif // __IMAGE_BASE_HEADER__ 316