IMG_pcx.c
changeset 642 7453e79c8cdb
parent 638 e3e9d7430674
child 643 b920be2b3fc6
     1.1 --- a/IMG_pcx.c	Fri Apr 12 16:29:43 2019 -0400
     1.2 +++ b/IMG_pcx.c	Mon Jun 10 13:07:58 2019 -0700
     1.3 @@ -98,6 +98,8 @@
     1.4      Uint8 *row, *buf = NULL;
     1.5      char *error = NULL;
     1.6      int bits, src_bits;
     1.7 +    int count = 0;
     1.8 +    Uint8 ch;
     1.9  
    1.10      if ( !src ) {
    1.11          /* The error message has been set in SDL_RWFromFile */
    1.12 @@ -105,7 +107,7 @@
    1.13      }
    1.14      start = SDL_RWtell(src);
    1.15  
    1.16 -    if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
    1.17 +    if ( !SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
    1.18          error = "file truncated";
    1.19          goto done;
    1.20      }
    1.21 @@ -115,6 +117,20 @@
    1.22      pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
    1.23      pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
    1.24  
    1.25 +#if 0
    1.26 +    printf("Manufacturer = %d\n", pcxh.Manufacturer);
    1.27 +    printf("Version = %d\n", pcxh.Version);
    1.28 +    printf("Encoding = %d\n", pcxh.Encoding);
    1.29 +    printf("BitsPerPixel = %d\n", pcxh.BitsPerPixel);
    1.30 +    printf("Xmin = %d, Ymin = %d, Xmax = %d, Ymax = %d\n", pcxh.Xmin, pcxh.Ymin, pcxh.Xmax, pcxh.Ymax);
    1.31 +    printf("HDpi = %d, VDpi = %d\n", pcxh.HDpi, pcxh.VDpi);
    1.32 +    printf("NPlanes = %d\n", pcxh.NPlanes);
    1.33 +    printf("BytesPerLine = %d\n", pcxh.BytesPerLine);
    1.34 +    printf("PaletteInfo = %d\n", pcxh.PaletteInfo);
    1.35 +    printf("HscreenSize = %d\n", pcxh.HscreenSize);
    1.36 +    printf("VscreenSize = %d\n", pcxh.VscreenSize);
    1.37 +#endif
    1.38 +
    1.39      /* Create the surface of the appropriate type */
    1.40      width = (pcxh.Xmax - pcxh.Xmin) + 1;
    1.41      height = (pcxh.Ymax - pcxh.Ymin) + 1;
    1.42 @@ -144,51 +160,52 @@
    1.43          goto done;
    1.44  
    1.45      bpl = pcxh.NPlanes * pcxh.BytesPerLine;
    1.46 -    if (bpl > surface->pitch) {
    1.47 +    if ( bpl > surface->pitch ) {
    1.48          error = "bytes per line is too large (corrupt?)";
    1.49 +        goto done;
    1.50      }
    1.51 -    buf = (Uint8 *)SDL_calloc(SDL_max(bpl, surface->pitch), 1);
    1.52 +    buf = (Uint8 *)SDL_calloc(surface->pitch, 1);
    1.53      row = (Uint8 *)surface->pixels;
    1.54      for ( y=0; y<surface->h; ++y ) {
    1.55          /* decode a scan line to a temporary buffer first */
    1.56 -        int i, count = 0;
    1.57 -        Uint8 ch;
    1.58 -        Uint8 *dst = (src_bits == 8) ? row : buf;
    1.59 +        int i;
    1.60 +        Uint8 *dst = buf;
    1.61          if ( pcxh.Encoding == 0 ) {
    1.62 -            if(!SDL_RWread(src, dst, bpl, 1)) {
    1.63 +            if ( !SDL_RWread(src, dst, bpl, 1) ) {
    1.64                  error = "file truncated";
    1.65                  goto done;
    1.66              }
    1.67          } else {
    1.68 -            for(i = 0; i < bpl; i++) {
    1.69 -                if(!count) {
    1.70 -                    if(!SDL_RWread(src, &ch, 1, 1)) {
    1.71 +            for ( i = 0; i < bpl; i++ ) {
    1.72 +                if ( !count ) {
    1.73 +                    if ( !SDL_RWread(src, &ch, 1, 1) ) {
    1.74                          error = "file truncated";
    1.75                          goto done;
    1.76                      }
    1.77 -                    if( (ch & 0xc0) == 0xc0) {
    1.78 -                        count = ch & 0x3f;
    1.79 -                        if(!SDL_RWread(src, &ch, 1, 1)) {
    1.80 +                    if ( ch < 0xc0 ) {
    1.81 +                        count = 1;
    1.82 +                    } else {
    1.83 +                        count = ch - 0xc0;
    1.84 +                        if( !SDL_RWread(src, &ch, 1, 1) ) {
    1.85                              error = "file truncated";
    1.86                              goto done;
    1.87                          }
    1.88 -                    } else
    1.89 -                        count = 1;
    1.90 +                    }
    1.91                  }
    1.92                  dst[i] = ch;
    1.93                  count--;
    1.94              }
    1.95          }
    1.96  
    1.97 -        if(src_bits <= 4) {
    1.98 +        if ( src_bits <= 4 ) {
    1.99              /* expand planes to 1 byte/pixel */
   1.100              Uint8 *innerSrc = buf;
   1.101              int plane;
   1.102 -            for(plane = 0; plane < pcxh.NPlanes; plane++) {
   1.103 +            for ( plane = 0; plane < pcxh.NPlanes; plane++ ) {
   1.104                  int j, k, x = 0;
   1.105 -                for(j = 0; j < pcxh.BytesPerLine; j++) {
   1.106 +                for( j = 0; j < pcxh.BytesPerLine; j++ ) {
   1.107                      Uint8 byte = *innerSrc++;
   1.108 -                    for(k = 7; k >= 0; k--) {
   1.109 +                    for( k = 7; k >= 0; k-- ) {
   1.110                          unsigned bit = (byte >> k) & 1;
   1.111                          /* skip padding bits */
   1.112                          if (j * 8 + k >= width)
   1.113 @@ -197,46 +214,53 @@
   1.114                      }
   1.115                  }
   1.116              }
   1.117 -        } else if(src_bits == 24) {
   1.118 +        } else if ( src_bits == 24 ) {
   1.119              /* de-interlace planes */
   1.120              Uint8 *innerSrc = buf;
   1.121              int plane;
   1.122 -            for(plane = 0; plane < pcxh.NPlanes; plane++) {
   1.123 +            for ( plane = 0; plane < pcxh.NPlanes; plane++ ) {
   1.124                  int x;
   1.125                  dst = row + plane;
   1.126 -                for(x = 0; x < width; x++) {
   1.127 +                for ( x = 0; x < width; x++ ) {
   1.128 +                    if ( dst >= row+surface->pitch ) {
   1.129 +                        error = "decoding out of bounds (corrupt?)";
   1.130 +                        goto done;
   1.131 +                    }
   1.132                      *dst = *innerSrc++;
   1.133                      dst += pcxh.NPlanes;
   1.134                  }
   1.135              }
   1.136 +        } else {
   1.137 +            SDL_memcpy(row, buf, bpl);
   1.138          }
   1.139  
   1.140          row += surface->pitch;
   1.141      }
   1.142  
   1.143 -    if(bits == 8) {
   1.144 +    if ( bits == 8 ) {
   1.145          SDL_Color *colors = surface->format->palette->colors;
   1.146          int nc = 1 << src_bits;
   1.147          int i;
   1.148  
   1.149          surface->format->palette->ncolors = nc;
   1.150 -        if(src_bits == 8) {
   1.151 +        if ( src_bits == 8 ) {
   1.152              Uint8 ch;
   1.153              /* look for a 256-colour palette */
   1.154              do {
   1.155 -                if ( !SDL_RWread(src, &ch, 1, 1)) {
   1.156 -                    error = "file truncated";
   1.157 -                    goto done;
   1.158 +                if ( !SDL_RWread(src, &ch, 1, 1) ) {
   1.159 +                    /* Couldn't find the palette, try the end of the file */
   1.160 +                    SDL_RWseek(src, -768, RW_SEEK_END);
   1.161 +                    break;
   1.162                  }
   1.163              } while ( ch != 12 );
   1.164  
   1.165 -            for(i = 0; i < 256; i++) {
   1.166 +            for ( i = 0; i < 256; i++ ) {
   1.167                  SDL_RWread(src, &colors[i].r, 1, 1);
   1.168                  SDL_RWread(src, &colors[i].g, 1, 1);
   1.169                  SDL_RWread(src, &colors[i].b, 1, 1);
   1.170              }
   1.171          } else {
   1.172 -            for(i = 0; i < nc; i++) {
   1.173 +            for ( i = 0; i < nc; i++ ) {
   1.174                  colors[i].r = pcxh.Colormap[i * 3];
   1.175                  colors[i].g = pcxh.Colormap[i * 3 + 1];
   1.176                  colors[i].b = pcxh.Colormap[i * 3 + 2];