2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
27 * 8 bits/pixel in single-planar format (8 bits/plane/pixel)
28 * 24 bits/pixel in 3-plane format (8 bits/plane/pixel)
30 * (The <8bpp formats are expanded to 8bpp surfaces)
33 * single-planar packed-pixel formats other than 8bpp
34 * 4-plane 32bpp format with a fourth "intensity" plane
39 #include "SDL_endian.h"
41 #include "SDL_image.h"
50 Sint16 Xmin, Ymin, Xmax, Ymax;
62 /* See if an image is contained in a data source */
63 int IMG_isPCX(SDL_RWops *src)
67 const int ZSoft_Manufacturer = 10;
68 const int PC_Paintbrush_Version = 5;
69 const int PCX_Uncompressed_Encoding = 0;
70 const int PCX_RunLength_Encoding = 1;
71 struct PCXheader pcxh;
75 start = SDL_RWtell(src);
77 if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
78 if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
79 (pcxh.Version == PC_Paintbrush_Version) &&
80 (pcxh.Encoding == PCX_RunLength_Encoding ||
81 pcxh.Encoding == PCX_Uncompressed_Encoding) ) {
85 SDL_RWseek(src, start, SEEK_SET);
89 /* Load a PCX type image from an SDL datasource */
90 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
93 struct PCXheader pcxh;
98 SDL_Surface *surface = NULL;
101 Uint8 *row, *buf = NULL;
106 /* The error message has been set in SDL_RWFromFile */
109 start = SDL_RWtell(src);
111 if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
112 error = "file truncated";
115 pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
116 pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
117 pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
118 pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
119 pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
121 /* Create the surface of the appropriate type */
122 width = (pcxh.Xmax - pcxh.Xmin) + 1;
123 height = (pcxh.Ymax - pcxh.Ymin) + 1;
124 Rmask = Gmask = Bmask = Amask = 0;
125 src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
126 if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
127 || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
129 } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
131 if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
141 error = "unsupported PCX format";
144 surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
145 bits, Rmask, Gmask, Bmask, Amask);
146 if ( surface == NULL )
149 bpl = pcxh.NPlanes * pcxh.BytesPerLine;
150 if (bpl > surface->pitch) {
151 error = "bytes per line is too large (corrupt?)";
154 row = surface->pixels;
155 for ( y=0; y<surface->h; ++y ) {
156 /* decode a scan line to a temporary buffer first */
159 Uint8 *dst = (src_bits == 8) ? row : buf;
160 if ( pcxh.Encoding == 0 ) {
161 if(!SDL_RWread(src, dst, bpl, 1)) {
162 error = "file truncated";
166 for(i = 0; i < bpl; i++) {
168 if(!SDL_RWread(src, &ch, 1, 1)) {
169 error = "file truncated";
172 if( (ch & 0xc0) == 0xc0) {
174 if(!SDL_RWread(src, &ch, 1, 1)) {
175 error = "file truncated";
187 /* expand planes to 1 byte/pixel */
190 for(plane = 0; plane < pcxh.NPlanes; plane++) {
192 for(i = 0; i < pcxh.BytesPerLine; i++) {
194 for(j = 7; j >= 0; j--) {
195 unsigned bit = (byte >> j) & 1;
196 /* skip padding bits */
197 if (i * 8 + j >= width)
199 row[x++] |= bit << plane;
203 } else if(src_bits == 24) {
204 /* de-interlace planes */
207 for(plane = 0; plane < pcxh.NPlanes; plane++) {
210 for(x = 0; x < width; x++) {
217 row += surface->pitch;
221 SDL_Color *colors = surface->format->palette->colors;
222 int nc = 1 << src_bits;
225 surface->format->palette->ncolors = nc;
228 /* look for a 256-colour palette */
230 if ( !SDL_RWread(src, &ch, 1, 1)) {
231 error = "file truncated";
234 } while ( ch != 12 );
236 for(i = 0; i < 256; i++) {
237 SDL_RWread(src, &colors[i].r, 1, 1);
238 SDL_RWread(src, &colors[i].g, 1, 1);
239 SDL_RWread(src, &colors[i].b, 1, 1);
242 for(i = 0; i < nc; i++) {
243 colors[i].r = pcxh.Colormap[i * 3];
244 colors[i].g = pcxh.Colormap[i * 3 + 1];
245 colors[i].b = pcxh.Colormap[i * 3 + 2];
253 SDL_RWseek(src, start, SEEK_SET);
255 SDL_FreeSurface(surface);
265 /* See if an image is contained in a data source */
266 int IMG_isPCX(SDL_RWops *src)
271 /* Load a PCX type image from an SDL datasource */
272 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
277 #endif /* LOAD_PCX */