PageRenderTime 40ms CodeModel.GetById 17ms app.highlight 19ms RepoModel.GetById 2ms app.codeStats 0ms

/project/jni/sdl_image/IMG_pcx.c

https://github.com/aichunyu/FFPlayer
C | 276 lines | 210 code | 22 blank | 44 comment | 64 complexity | 3e2c8fadbf524a6b8db12cc11d83e42f MD5 | raw file
  1/*
  2  SDL_image:  An example image loading library for use with SDL
  3  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
  4
  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.
  8
  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:
 12
 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.
 20*/
 21
 22/*
 23 * PCX file reader:
 24 * Supports:
 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)
 28 *
 29 * (The <8bpp formats are expanded to 8bpp surfaces)
 30 *
 31 * Doesn't support:
 32 *  single-planar packed-pixel formats other than 8bpp
 33 *  4-plane 32bpp format with a fourth "intensity" plane
 34 */
 35#include <stdio.h>
 36#include <stdlib.h>
 37
 38#include "SDL_endian.h"
 39
 40#include "SDL_image.h"
 41
 42#ifdef LOAD_PCX
 43
 44struct PCXheader {
 45	Uint8 Manufacturer;
 46	Uint8 Version;
 47	Uint8 Encoding;
 48	Uint8 BitsPerPixel;
 49	Sint16 Xmin, Ymin, Xmax, Ymax;
 50	Sint16 HDpi, VDpi;
 51	Uint8 Colormap[48];
 52	Uint8 Reserved;
 53	Uint8 NPlanes;
 54	Sint16 BytesPerLine;
 55	Sint16 PaletteInfo;
 56	Sint16 HscreenSize;
 57	Sint16 VscreenSize;
 58	Uint8 Filler[54];
 59};
 60
 61/* See if an image is contained in a data source */
 62int IMG_isPCX(SDL_RWops *src)
 63{
 64	int start;
 65	int is_PCX;
 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;
 71
 72	if ( !src )
 73		return 0;
 74	start = SDL_RWtell(src);
 75	is_PCX = 0;
 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) ) {
 81			is_PCX = 1;
 82		}
 83	}
 84	SDL_RWseek(src, start, RW_SEEK_SET);
 85	return(is_PCX);
 86}
 87
 88/* Load a PCX type image from an SDL datasource */
 89SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
 90{
 91	int start;
 92	struct PCXheader pcxh;
 93	Uint32 Rmask;
 94	Uint32 Gmask;
 95	Uint32 Bmask;
 96	Uint32 Amask;
 97	SDL_Surface *surface = NULL;
 98	int width, height;
 99	int y, bpl;
100	Uint8 *row, *buf = NULL;
101	char *error = NULL;
102	int bits, src_bits;
103
104	if ( !src ) {
105		/* The error message has been set in SDL_RWFromFile */
106		return NULL;
107	}
108	start = SDL_RWtell(src);
109
110	if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
111		error = "file truncated";
112		goto done;
113	}
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);
119
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)) {
127		bits = 8;
128	} else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
129		bits = 24;
130		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
131			Rmask = 0x000000FF;
132			Gmask = 0x0000FF00;
133			Bmask = 0x00FF0000;
134		} else {
135			Rmask = 0xFF0000;
136			Gmask = 0x00FF00;
137			Bmask = 0x0000FF;
138		}
139	} else {
140		error = "unsupported PCX format";
141		goto done;
142	}
143	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
144				   bits, Rmask, Gmask, Bmask, Amask);
145	if ( surface == NULL )
146		goto done;
147
148	bpl = pcxh.NPlanes * pcxh.BytesPerLine;
149	if (bpl > surface->pitch) {
150		error = "bytes per line is too large (corrupt?)";
151	}
152	buf = malloc(bpl);
153	row = surface->pixels;
154	for ( y=0; y<surface->h; ++y ) {
155		/* decode a scan line to a temporary buffer first */
156		int i, count = 0;
157		Uint8 ch;
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";
162				goto done;
163			}
164		} else {
165			for(i = 0; i < bpl; i++) {
166				if(!count) {
167					if(!SDL_RWread(src, &ch, 1, 1)) {
168						error = "file truncated";
169						goto done;
170					}
171					if( (ch & 0xc0) == 0xc0) {
172						count = ch & 0x3f;
173						if(!SDL_RWread(src, &ch, 1, 1)) {
174							error = "file truncated";
175							goto done;
176						}
177					} else
178						count = 1;
179				}
180				dst[i] = ch;
181				count--;
182			}
183		}
184
185		if(src_bits <= 4) {
186			/* expand planes to 1 byte/pixel */
187			Uint8 *src = buf;
188			int plane;
189			for(plane = 0; plane < pcxh.NPlanes; plane++) {
190				int i, j, x = 0;
191				for(i = 0; i < pcxh.BytesPerLine; i++) {
192					Uint8 byte = *src++;
193					for(j = 7; j >= 0; j--) {
194						unsigned bit = (byte >> j) & 1;
195						/* skip padding bits */
196						if (i * 8 + j >= width)
197							continue;
198						row[x++] |= bit << plane;
199					}
200				}
201			}
202 		} else if(src_bits == 24) {
203			/* de-interlace planes */
204			Uint8 *src = buf;
205			int plane;
206			for(plane = 0; plane < pcxh.NPlanes; plane++) {
207				int x;
208				dst = row + plane;
209				for(x = 0; x < width; x++) {
210					*dst = *src++;
211					dst += pcxh.NPlanes;
212				}
213			}
214		}
215
216		row += surface->pitch;
217	}
218
219	if(bits == 8) {
220		SDL_Color *colors = surface->format->palette->colors;
221		int nc = 1 << src_bits;
222		int i;
223
224		surface->format->palette->ncolors = nc;
225		if(src_bits == 8) {
226			Uint8 ch;
227			/* look for a 256-colour palette */
228			do {
229				if ( !SDL_RWread(src, &ch, 1, 1)) {
230					error = "file truncated";
231					goto done;
232				}
233			} while ( ch != 12 );
234
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);
239			}
240		} else {
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];
245			}
246		}
247	}
248
249done:
250	free(buf);
251	if ( error ) {
252		SDL_RWseek(src, start, RW_SEEK_SET);
253		if ( surface ) {
254			SDL_FreeSurface(surface);
255			surface = NULL;
256		}
257		IMG_SetError(error);
258	}
259	return(surface);
260}
261
262#else
263
264/* See if an image is contained in a data source */
265int IMG_isPCX(SDL_RWops *src)
266{
267	return(0);
268}
269
270/* Load a PCX type image from an SDL datasource */
271SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
272{
273	return(NULL);
274}
275
276#endif /* LOAD_PCX */