1 #include <assert.h>
2 #include <SDL2/SDL_image.h>
3 #include "Image.h"
4 #include "../SharedDefines.h"
5
Image()6 Image::Image()
7 :
8 m_Width(0),
9 m_Height(0),
10 m_OffsetX(0),
11 m_OffsetY(0),
12 m_pTexture(NULL)
13 {
14
15 }
16
Image(SDL_Texture * pSDLTexture)17 Image::Image(SDL_Texture* pSDLTexture)
18 :
19 m_pTexture(pSDLTexture),
20 m_OffsetX(0),
21 m_OffsetY(0)
22 {
23 assert(pSDLTexture != NULL);
24 SDL_QueryTexture(pSDLTexture, NULL, NULL, &m_Width, &m_Height);
25 }
26
~Image()27 Image::~Image()
28 {
29 SDL_DestroyTexture(m_pTexture);
30 m_pTexture = NULL;
31 }
32
GetPositonRect(int32_t x,int32_t y)33 SDL_Rect Image::GetPositonRect(int32_t x, int32_t y)
34 {
35 int positionX = x - m_Width / 2 + m_OffsetX;
36 int positionY = y - m_Height / 2 + m_OffsetY;
37
38 SDL_Rect rect = { positionX, positionY, m_Width, m_Height };
39
40 return rect;
41 }
42
PutPixel(SDL_Surface * surface,int x,int y,Uint32 pixel)43 static void PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
44 {
45 int bpp = surface->format->BytesPerPixel;
46 /* Here p is the address to the pixel we want to set */
47 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
48
49 switch (bpp) {
50 case 1:
51 *p = pixel;
52 break;
53
54 case 2:
55 *(Uint16 *)p = pixel;
56 break;
57
58 case 3:
59 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
60 p[0] = (pixel >> 16) & 0xff;
61 p[1] = (pixel >> 8) & 0xff;
62 p[2] = pixel & 0xff;
63 }
64 else {
65 p[0] = pixel & 0xff;
66 p[1] = (pixel >> 8) & 0xff;
67 p[2] = (pixel >> 16) & 0xff;
68 }
69 break;
70
71 case 4:
72 *(Uint32 *)p = pixel;
73 break;
74 }
75 }
76
GetTextureFromPid(WapPid * pid,SDL_Renderer * renderer)77 SDL_Texture* Image::GetTextureFromPid(WapPid* pid, SDL_Renderer* renderer)
78 {
79 assert(pid != NULL);
80 assert(renderer != NULL);
81
82 uint32_t rmask, gmask, bmask, amask;
83 uint32_t width = pid->width;
84 uint32_t height = pid->height;
85
86 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
87 rmask = 0xff000000;
88 gmask = 0x00ff0000;
89 bmask = 0x0000ff00;
90 amask = 0x000000ff;
91 #else
92 rmask = 0x000000ff;
93 gmask = 0x0000ff00;
94 bmask = 0x00ff0000;
95 amask = 0xff000000;
96 #endif
97
98 SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask);
99 assert(surface != NULL);
100
101 uint32_t colorIdx;
102 uint32_t colorsCount = pid->colorsCount;
103 for (colorIdx = 0; colorIdx < colorsCount; colorIdx++)
104 {
105 WAP_ColorRGBA color = pid->colors[colorIdx];
106 uint32_t x = colorIdx % width;
107 uint32_t y = colorIdx / width;
108
109 PutPixel(surface, x, y, SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a));
110 }
111
112 SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
113 assert(texture != NULL);
114
115 SDL_FreeSurface(surface);
116
117 return texture;
118 }
119
CreateImage(WapPid * pid,SDL_Renderer * renderer)120 Image* Image::CreateImage(WapPid* pid, SDL_Renderer* renderer)
121 {
122 Image* image = new Image();
123 if (!image->Initialize(pid, renderer))
124 {
125 delete image;
126 return NULL;
127 }
128
129 return image;
130 }
131
CreatePcxImage(char * rawBuffer,uint32_t size,SDL_Renderer * renderer,bool useColorKey,SDL_Color colorKey)132 Image* Image::CreatePcxImage(char* rawBuffer, uint32_t size, SDL_Renderer* renderer, bool useColorKey, SDL_Color colorKey)
133 {
134 Image* pImage = new Image();
135 SDL_RWops* pRWops = SDL_RWFromMem((void*)rawBuffer, size);
136 SDL_Surface* pSurface = IMG_LoadPCX_RW(pRWops);
137 if (pSurface == NULL)
138 {
139 LOG_ERROR(IMG_GetError());
140 return NULL;
141 }
142
143 if (useColorKey)
144 {
145 SDL_SetColorKey(pSurface, SDL_TRUE, SDL_MapRGB(pSurface->format, colorKey.r, colorKey.g, colorKey.b));
146 }
147
148 SDL_Texture* pTexture = SDL_CreateTextureFromSurface(renderer, pSurface);
149 SDL_FreeSurface(pSurface);
150
151 if (pTexture == NULL)
152 {
153 LOG_ERROR(IMG_GetError());
154 return NULL;
155 }
156
157 if (!pImage->Initialize(pTexture))
158 {
159 LOG_ERROR(IMG_GetError());
160 return NULL;
161 }
162
163 return pImage;
164 }
165
CreatePngImage(char * rawBuffer,uint32_t size,SDL_Renderer * renderer)166 Image* Image::CreatePngImage(char* rawBuffer, uint32_t size, SDL_Renderer* renderer)
167 {
168 Image* pImage = new Image();
169 SDL_RWops* pRWops = SDL_RWFromMem((void*)rawBuffer, size);
170 SDL_Surface* pSurface = IMG_LoadPNG_RW(pRWops);
171 if (pSurface == NULL)
172 {
173 LOG_ERROR(IMG_GetError());
174 return NULL;
175 }
176
177 SDL_Texture* pTexture = SDL_CreateTextureFromSurface(renderer, pSurface);
178 SDL_FreeSurface(pSurface);
179
180 if (pTexture == NULL)
181 {
182 LOG_ERROR(IMG_GetError());
183 delete pImage;
184 return NULL;
185 }
186
187 if (!pImage->Initialize(pTexture))
188 {
189 LOG_ERROR(IMG_GetError());
190 delete pImage;
191 SDL_DestroyTexture(pTexture);
192 return NULL;
193 }
194
195 return pImage;
196 }
197
CreateImageFromColor(SDL_Color color,int w,int h,SDL_Renderer * pRenderer)198 Image* Image::CreateImageFromColor(SDL_Color color, int w, int h, SDL_Renderer* pRenderer)
199 {
200 Image* pImage = new Image();
201
202 SDL_Surface* pSurface = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
203 SDL_FillRect(pSurface, NULL, SDL_MapRGB(pSurface->format, color.r, color.g, color.b));
204 SDL_Texture* pTextureRect = SDL_CreateTextureFromSurface(pRenderer, pSurface);
205
206 SDL_FreeSurface(pSurface);
207
208 if (pTextureRect == NULL)
209 {
210 LOG_ERROR(IMG_GetError());
211 delete pImage;
212 return NULL;
213 }
214
215 if (!pImage->Initialize(pTextureRect))
216 {
217 LOG_ERROR(IMG_GetError());
218 delete pImage;
219 SDL_DestroyTexture(pTextureRect);
220 return NULL;
221 }
222
223 return pImage;
224 }
225
Initialize(WapPid * pid,SDL_Renderer * renderer)226 bool Image::Initialize(WapPid* pid, SDL_Renderer* renderer)
227 {
228 if (pid == NULL || renderer == NULL)
229 {
230 return false;
231 }
232
233 m_Width = pid->width;
234 m_Height = pid->height;
235 m_OffsetX = pid->offsetX;
236 m_OffsetY = pid->offsetY;
237
238 m_pTexture = GetTextureFromPid(pid, renderer);
239 if (m_pTexture == NULL)
240 {
241 return false;
242 }
243
244 return true;
245 }
246
Initialize(SDL_Texture * pTexture)247 bool Image::Initialize(SDL_Texture* pTexture)
248 {
249 if (pTexture == NULL)
250 {
251 return false;
252 }
253
254 SDL_QueryTexture(pTexture, NULL, NULL, &m_Width, &m_Height);
255 m_OffsetX = m_OffsetY = 0;
256 m_pTexture = pTexture;
257
258 return true;
259 }