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 }