2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
25 * 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
26 * 8 bits/pixel in single-planar format (8 bits/plane/pixel)
27 * 24 bits/pixel in 3-plane format (8 bits/plane/pixel)
29 * (The <8bpp formats are expanded to 8bpp surfaces)
32 * single-planar packed-pixel formats other than 8bpp
33 * 4-plane 32bpp format with a fourth "intensity" plane
38 #include "SDL_endian.h"
40 #include "SDL_image.h"
49 Sint16 Xmin, Ymin, Xmax, Ymax;
61 /* See if an image is contained in a data source */
62 int IMG_isPCX(SDL_RWops *src)
66 const int ZSoft_Manufacturer = 10;
67 const int PC_Paintbrush_Version = 5;
68 const int PCX_Uncompressed_Encoding = 0;
69 const int PCX_RunLength_Encoding = 1;
70 struct PCXheader pcxh;
74 start = SDL_RWtell(src);
76 if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
77 if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
78 (pcxh.Version == PC_Paintbrush_Version) &&
79 (pcxh.Encoding == PCX_RunLength_Encoding ||
80 pcxh.Encoding == PCX_Uncompressed_Encoding) ) {
84 SDL_RWseek(src, start, RW_SEEK_SET);
88 /* Load a PCX type image from an SDL datasource */
89 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
92 struct PCXheader pcxh;
97 SDL_Surface *surface = NULL;
100 Uint8 *row, *buf = NULL;
105 /* The error message has been set in SDL_RWFromFile */
108 start = SDL_RWtell(src);
110 if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
111 error = "file truncated";
114 pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
115 pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
116 pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
117 pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
118 pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
120 /* Create the surface of the appropriate type */
121 width = (pcxh.Xmax - pcxh.Xmin) + 1;
122 height = (pcxh.Ymax - pcxh.Ymin) + 1;
123 Rmask = Gmask = Bmask = Amask = 0;
124 src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
125 if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
126 || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
128 } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
130 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
140 error = "unsupported PCX format";
143 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
144 bits, Rmask, Gmask, Bmask, Amask);
145 if ( surface == NULL )
148 bpl = pcxh.NPlanes * pcxh.BytesPerLine;
149 if (bpl > surface->pitch) {
150 error = "bytes per line is too large (corrupt?)";
152 buf = (Uint8 *)SDL_malloc(bpl);
153 row = (Uint8 *)surface->pixels;
154 for ( y=0; y<surface->h; ++y ) {
155 /* decode a scan line to a temporary buffer first */
158 Uint8 *dst = (src_bits == 8) ? row : buf;
159 if ( pcxh.Encoding == 0 ) {
160 if(!SDL_RWread(src, dst, bpl, 1)) {
161 error = "file truncated";
165 for(i = 0; i < bpl; i++) {
167 if(!SDL_RWread(src, &ch, 1, 1)) {
168 error = "file truncated";
171 if( (ch & 0xc0) == 0xc0) {
173 if(!SDL_RWread(src, &ch, 1, 1)) {
174 error = "file truncated";
186 /* expand planes to 1 byte/pixel */
187 Uint8 *innerSrc = buf;
189 for(plane = 0; plane < pcxh.NPlanes; plane++) {
191 for(j = 0; j < pcxh.BytesPerLine; j++) {
192 Uint8 byte = *innerSrc++;
193 for(k = 7; k >= 0; k--) {
194 unsigned bit = (byte >> k) & 1;
195 /* skip padding bits */
196 if (j * 8 + k >= width)
198 row[x++] |= bit << plane;
202 } else if(src_bits == 24) {
203 /* de-interlace planes */
204 Uint8 *innerSrc = buf;
206 for(plane = 0; plane < pcxh.NPlanes; plane++) {
209 for(x = 0; x < width; x++) {
216 row += surface->pitch;
220 SDL_Color *colors = surface->format->palette->colors;
221 int nc = 1 << src_bits;
224 surface->format->palette->ncolors = nc;
227 /* look for a 256-colour palette */
229 if ( !SDL_RWread(src, &ch, 1, 1)) {
230 error = "file truncated";
233 } while ( ch != 12 );
235 for(i = 0; i < 256; i++) {
236 SDL_RWread(src, &colors[i].r, 1, 1);
237 SDL_RWread(src, &colors[i].g, 1, 1);
238 SDL_RWread(src, &colors[i].b, 1, 1);
241 for(i = 0; i < nc; i++) {
242 colors[i].r = pcxh.Colormap[i * 3];
243 colors[i].g = pcxh.Colormap[i * 3 + 1];
244 colors[i].b = pcxh.Colormap[i * 3 + 2];
252 SDL_RWseek(src, start, RW_SEEK_SET);
254 SDL_FreeSurface(surface);
264 /* See if an image is contained in a data source */
265 int IMG_isPCX(SDL_RWops *src)
270 /* Load a PCX type image from an SDL datasource */
271 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
276 #endif /* LOAD_PCX */