Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.     IMGLIB:  An example image loading library for use with SDL
  3.     Copyright (C) 1999  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  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.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     5635-34 Springhouse Dr.
  21.     Pleasanton, CA 94588 (USA)
  22.     slouken@devolution.com
  23. */
  24.  
  25. /*
  26.  * PCX file reader:
  27.  * Supports:
  28.  *  1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
  29.  *  8 bits/pixel in single-planar format (8 bits/plane/pixel)
  30.  *  24 bits/pixel in 3-plane format (8 bits/plane/pixel)
  31.  *
  32.  * (The <8bpp formats are expanded to 8bpp surfaces)
  33.  *
  34.  * Doesn't support:
  35.  *  single-planar packed-pixel formats other than 8bpp
  36.  *  4-plane 32bpp format with a fourth "intensity" plane
  37.  */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40.  
  41. #include "SDL_endian.h"
  42.  
  43. #include "SDL_image.h"
  44.  
  45. #ifdef LOAD_PCX
  46.  
  47. struct PCXheader {
  48.         Uint8 Manufacturer;
  49.         Uint8 Version;
  50.         Uint8 Encoding;
  51.         Uint8 BitsPerPixel;
  52.         Sint16 Xmin, Ymin, Xmax, Ymax;
  53.         Sint16 HDpi, VDpi;
  54.         Uint8 Colormap[48];
  55.         Uint8 Reserved;
  56.         Uint8 NPlanes;
  57.         Sint16 BytesPerLine;
  58.         Sint16 PaletteInfo;
  59.         Sint16 HscreenSize;
  60.         Sint16 VscreenSize;
  61.         Uint8 Filler[54];
  62. };
  63.  
  64. /* See if an image is contained in a data source */
  65. int IMG_isPCX(SDL_RWops *src)
  66. {
  67.         int is_PCX;
  68.         const int ZSoft_Manufacturer = 10;
  69.         const int PC_Paintbrush_Version = 5;
  70.         const int PCX_RunLength_Encoding = 1;
  71.         struct PCXheader pcxh;
  72.  
  73.         is_PCX = 0;
  74.         if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
  75.                 if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
  76.                      (pcxh.Version == PC_Paintbrush_Version) &&
  77.                      (pcxh.Encoding == PCX_RunLength_Encoding) ) {
  78.                         is_PCX = 1;
  79.                 }
  80.         }
  81.         return(is_PCX);
  82. }
  83.  
  84. /* Load a PCX type image from an SDL datasource */
  85. SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
  86. {
  87.         struct PCXheader pcxh;
  88.         Uint32 Rmask;
  89.         Uint32 Gmask;
  90.         Uint32 Bmask;
  91.         Uint32 Amask;
  92.         SDL_Surface *surface = NULL;
  93.         int width, height;
  94.         int y, bpl;
  95.         Uint8 *row, *buf = NULL;
  96.         char *error = NULL;
  97.         int bits, src_bits;
  98.  
  99.         if ( ! src ) {
  100.                 goto done;
  101.         }
  102.  
  103.         if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
  104.                 error = "file truncated";
  105.                 goto done;
  106.         }
  107.         pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
  108.         pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
  109.         pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
  110.         pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
  111.         pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
  112.  
  113.         /* Create the surface of the appropriate type */
  114.         width = (pcxh.Xmax - pcxh.Xmin) + 1;
  115.         height = (pcxh.Ymax - pcxh.Ymin) + 1;
  116.         Rmask = Gmask = Bmask = Amask = 0;
  117.         src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
  118.         if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
  119.            || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
  120.                 bits = 8;
  121.         } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
  122.                 bits = 24;
  123.                 if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
  124.                         Rmask = 0x000000FF;
  125.                         Gmask = 0x0000FF00;
  126.                         Bmask = 0x00FF0000;
  127.                 } else {
  128.                         Rmask = 0xFF0000;
  129.                         Gmask = 0x00FF00;
  130.                         Bmask = 0x0000FF;
  131.                 }
  132.         } else {
  133.                 error = "unsupported PCX format";
  134.                 goto done;
  135.         }
  136.         surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
  137.                                    bits, Rmask, Gmask, Bmask, Amask);
  138.         if ( surface == NULL )
  139.                 goto done;
  140.  
  141.         bpl = pcxh.NPlanes * pcxh.BytesPerLine;
  142.         buf = malloc(bpl);
  143.         row = surface->pixels;
  144.         for ( y=0; y<surface->h; ++y ) {
  145.                 /* decode a scan line to a temporary buffer first */
  146.                 int i, count = 0;
  147.                 Uint8 ch;
  148.                 Uint8 *dst = (src_bits == 8) ? row : buf;
  149.                 for(i = 0; i < bpl; i++) {
  150.                         if(!count) {
  151.                                 if(!SDL_RWread(src, &ch, 1, 1)) {
  152.                                         error = "file truncated";
  153.                                         goto done;
  154.                                 }
  155.                                 if( (ch & 0xc0) == 0xc0) {
  156.                                         count = ch & 0x3f;
  157.                                         if(!SDL_RWread(src, &ch, 1, 1)) {
  158.                                                 error = "file truncated";
  159.                                                 goto done;
  160.                                         }
  161.                                 } else
  162.                                         count = 1;
  163.                         }
  164.                         dst[i] = ch;
  165.                         count--;
  166.                 }
  167.  
  168.                 if(src_bits <= 4) {
  169.                         /* expand planes to 1 byte/pixel */
  170.                         Uint8 *src = buf;
  171.                         int plane;
  172.                         for(plane = 0; plane < pcxh.NPlanes; plane++) {
  173.                                 int i, j, x = 0;
  174.                                 for(i = 0; i < pcxh.BytesPerLine; i++) {
  175.                                         Uint8 byte = *src++;
  176.                                         for(j = 7; j >= 0; j--) {
  177.                                                 unsigned bit = (byte >> j) & 1;
  178.                                                 row[x++] |= bit << plane;
  179.                                         }
  180.                                 }
  181.                         }
  182.                 } else if(src_bits == 24) {
  183.                         /* de-interlace planes */
  184.                         Uint8 *src = buf;
  185.                         int plane;
  186.                         for(plane = 0; plane < pcxh.NPlanes; plane++) {
  187.                                 int x;
  188.                                 dst = row + plane;
  189.                                 for(x = 0; x < width; x++) {
  190.                                         *dst = *src++;
  191.                                         dst += pcxh.NPlanes;
  192.                                 }
  193.                         }
  194.                 }
  195.  
  196.                 row += surface->pitch;
  197.         }
  198.  
  199.         if(bits == 8) {
  200.                 SDL_Color *colors = surface->format->palette->colors;
  201.                 int nc = 1 << src_bits;
  202.                 int i;
  203.  
  204.                 surface->format->palette->ncolors = nc;
  205.                 if(src_bits == 8) {
  206.                         Uint8 ch;
  207.                         /* look for a 256-colour palette */
  208.                         do {
  209.                                 if ( !SDL_RWread(src, &ch, 1, 1)) {
  210.                                         error = "file truncated";
  211.                                         goto done;
  212.                                 }
  213.                         } while ( ch != 12 );
  214.  
  215.                         for(i = 0; i < 256; i++) {
  216.                                 SDL_RWread(src, &colors[i].r, 1, 1);
  217.                                 SDL_RWread(src, &colors[i].g, 1, 1);
  218.                                 SDL_RWread(src, &colors[i].b, 1, 1);
  219.                         }
  220.                 } else {
  221.                         for(i = 0; i < nc; i++) {
  222.                                 colors[i].r = pcxh.Colormap[i * 3];
  223.                                 colors[i].g = pcxh.Colormap[i * 3 + 1];
  224.                                 colors[i].b = pcxh.Colormap[i * 3 + 2];
  225.                         }
  226.                 }
  227.         }
  228.  
  229. done:
  230.         free(buf);
  231.         if ( error ) {
  232.                 SDL_FreeSurface(surface);
  233.                 IMG_SetError(error);
  234.                 surface = NULL;
  235.         }
  236.         return(surface);
  237. }
  238.  
  239. #else
  240.  
  241. /* See if an image is contained in a data source */
  242. int IMG_isPCX(SDL_RWops *src)
  243. {
  244.         return(0);
  245. }
  246.  
  247. /* Load a PCX type image from an SDL datasource */
  248. SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
  249. {
  250.         return(NULL);
  251. }
  252.  
  253. #endif /* LOAD_PCX */
  254.