Subversion Repositories Kolibri OS

Rev

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.  * PNM (portable anymap) image loader:
  27.  *
  28.  * Supports: PBM, PGM and PPM, ASCII and binary formats
  29.  * (PBM and PGM are loaded as 8bpp surfaces)
  30.  * Does not support: maximum component value > 255
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <ctype.h>
  36. #include <string.h>
  37.  
  38. #include "SDL_image.h"
  39.  
  40. #ifdef LOAD_PNM
  41.  
  42. /* See if an image is contained in a data source */
  43. int IMG_isPNM(SDL_RWops *src)
  44. {
  45.         char magic[2];
  46.  
  47.         /*
  48.          * PNM magic signatures:
  49.          * P1   PBM, ascii format
  50.          * P2   PGM, ascii format
  51.          * P3   PPM, ascii format
  52.          * P4   PBM, binary format
  53.          * P5   PGM, binary format
  54.          * P6   PPM, binary format
  55.          */
  56.         return (SDL_RWread(src, magic, 2, 1)
  57.                 && magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6');
  58. }
  59.  
  60. /* read a non-negative integer from the source. return -1 upon error */
  61. static int ReadNumber(SDL_RWops *src)
  62. {
  63.         int number;
  64.         unsigned char ch;
  65.  
  66.         /* Initialize return value */
  67.         number = 0;
  68.  
  69.         /* Skip leading whitespace */
  70.         do {
  71.                 if ( ! SDL_RWread(src, &ch, 1, 1) ) {
  72.                         return(0);
  73.                 }
  74.                 /* Eat comments as whitespace */
  75.                 if ( ch == '#' ) {  /* Comment is '#' to end of line */
  76.                         do {
  77.                                 if ( ! SDL_RWread(src, &ch, 1, 1) ) {
  78.                                         return -1;
  79.                                 }
  80.                         } while ( (ch != '\r') && (ch != '\n') );
  81.                 }
  82.         } while ( isspace(ch) );
  83.  
  84.         /* Add up the number */
  85.         do {
  86.                 number *= 10;
  87.                 number += ch-'0';
  88.  
  89.                 if ( !SDL_RWread(src, &ch, 1, 1) ) {
  90.                         return -1;
  91.                 }
  92.         } while ( isdigit(ch) );
  93.  
  94.         return(number);
  95. }
  96.  
  97. SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
  98. {
  99.         SDL_Surface *surface = NULL;
  100.         int width, height;
  101.         int maxval, y, bpl;
  102.         Uint8 *row;
  103.         Uint8 *buf = NULL;
  104.         char *error = NULL;
  105.         Uint8 magic[2];
  106.         int ascii;
  107.         enum { PBM, PGM, PPM } kind;
  108.  
  109. #define ERROR(s) do { error = (s); goto done; } while(0)
  110.  
  111.         if(!src)
  112.                 return NULL;
  113.  
  114.         SDL_RWread(src, magic, 2, 1);
  115.         kind = magic[1] - '1';
  116.         ascii = 1;
  117.         if(kind >= 3) {
  118.                 ascii = 0;
  119.                 kind -= 3;
  120.         }
  121.  
  122.         width = ReadNumber(src);
  123.         height = ReadNumber(src);
  124.         if(width <= 0 || height <= 0)
  125.                 ERROR("Unable to read image width and height");
  126.  
  127.         if(kind != PBM) {
  128.                 maxval = ReadNumber(src);
  129.                 if(maxval <= 0 || maxval > 255)
  130.                         ERROR("unsupported PNM format");
  131.         } else
  132.                 maxval = 255;   /* never scale PBMs */
  133.  
  134.         /* binary PNM allows just a single character of whitespace after
  135.            the last parameter, and we've already consumed it */
  136.  
  137.         if(kind == PPM) {
  138.                 /* 24-bit surface in R,G,B byte order */
  139.                 surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24,
  140. #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  141.                                            0x000000ff, 0x0000ff00, 0x00ff0000,
  142. #else
  143.                                            0x00ff0000, 0x0000ff00, 0x000000ff,
  144. #endif
  145.                                            0);
  146.         } else {
  147.                 /* load PBM/PGM as 8-bit indexed images */
  148.                 surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8,
  149.                                            0, 0, 0, 0);
  150.         }
  151.         if ( surface == NULL )
  152.                 ERROR("Out of memory");
  153.         bpl = width * surface->format->BytesPerPixel;
  154.         if(kind == PGM) {
  155.                 SDL_Color *c = surface->format->palette->colors;
  156.                 int i;
  157.                 for(i = 0; i < 256; i++)
  158.                         c[i].r = c[i].g = c[i].b = i;
  159.                 surface->format->palette->ncolors = 256;
  160.         } else if(kind == PBM) {
  161.                 /* for some reason PBM has 1=black, 0=white */
  162.                 SDL_Color *c = surface->format->palette->colors;
  163.                 c[0].r = c[0].g = c[0].b = 255;
  164.                 c[1].r = c[1].g = c[1].b = 0;
  165.                 surface->format->palette->ncolors = 2;
  166.                 bpl = (width + 7) >> 3;
  167.                 buf = malloc(bpl);
  168.                 if(buf == NULL)
  169.                         ERROR("Out of memory");
  170.         }
  171.  
  172.         /* Read the image into the surface */
  173.         row = surface->pixels;
  174.         for(y = 0; y < height; y++) {
  175.                 if(ascii) {
  176.                         int i;
  177.                         if(kind == PBM) {
  178.                                 for(i = 0; i < width; i++) {
  179.                                         Uint8 ch;
  180.                                         do {
  181.                                                 if(!SDL_RWread(src, &ch,
  182.                                                                1, 1))
  183.                                                        ERROR("file truncated");
  184.                                                 ch -= '0';
  185.                                         } while(ch > 1);
  186.                                         row[i] = ch;
  187.                                 }
  188.                         } else {
  189.                                 for(i = 0; i < bpl; i++) {
  190.                                         int c;
  191.                                         c = ReadNumber(src);
  192.                                         if(c < 0)
  193.                                                 ERROR("file truncated");
  194.                                         row[i] = c;
  195.                                 }
  196.                         }
  197.                 } else {
  198.                         Uint8 *dst = (kind == PBM) ? buf : row;
  199.                         if(!SDL_RWread(src, dst, bpl, 1))
  200.                                 ERROR("file truncated");
  201.                         if(kind == PBM) {
  202.                                 /* expand bitmap to 8bpp */
  203.                                 int i;
  204.                                 for(i = 0; i < width; i++) {
  205.                                         int bit = 7 - (i & 7);
  206.                                         row[i] = (buf[i >> 3] >> bit) & 1;
  207.                                 }
  208.                         }
  209.                 }
  210.                 if(maxval < 255) {
  211.                         /* scale up to full dynamic range (slow) */
  212.                         int i;
  213.                         for(i = 0; i < bpl; i++)
  214.                                 row[i] = row[i] * 255 / maxval;
  215.                 }
  216.                 row += surface->pitch;
  217.         }
  218. done:
  219.         free(buf);
  220.         if(error) {
  221.                 SDL_FreeSurface(surface);
  222.                 IMG_SetError(error);
  223.                 surface = NULL;
  224.         }
  225.         return(surface);
  226. }
  227.  
  228. #else
  229.  
  230. /* See if an image is contained in a data source */
  231. int IMG_isPNM(SDL_RWops *src)
  232. {
  233.         return(0);
  234. }
  235.  
  236. /* Load a PNM type image from an SDL datasource */
  237. SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
  238. {
  239.         return(NULL);
  240. }
  241.  
  242. #endif /* LOAD_PNM */
  243.