IMG_pcx.c
changeset 642 7453e79c8cdb
parent 638 e3e9d7430674
child 643 b920be2b3fc6
equal deleted inserted replaced
641:61f1bf992955 642:7453e79c8cdb
    96     int width, height;
    96     int width, height;
    97     int y, bpl;
    97     int y, bpl;
    98     Uint8 *row, *buf = NULL;
    98     Uint8 *row, *buf = NULL;
    99     char *error = NULL;
    99     char *error = NULL;
   100     int bits, src_bits;
   100     int bits, src_bits;
       
   101     int count = 0;
       
   102     Uint8 ch;
   101 
   103 
   102     if ( !src ) {
   104     if ( !src ) {
   103         /* The error message has been set in SDL_RWFromFile */
   105         /* The error message has been set in SDL_RWFromFile */
   104         return NULL;
   106         return NULL;
   105     }
   107     }
   106     start = SDL_RWtell(src);
   108     start = SDL_RWtell(src);
   107 
   109 
   108     if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
   110     if ( !SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
   109         error = "file truncated";
   111         error = "file truncated";
   110         goto done;
   112         goto done;
   111     }
   113     }
   112     pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
   114     pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
   113     pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
   115     pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
   114     pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
   116     pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
   115     pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
   117     pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
   116     pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
   118     pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
       
   119 
       
   120 #if 0
       
   121     printf("Manufacturer = %d\n", pcxh.Manufacturer);
       
   122     printf("Version = %d\n", pcxh.Version);
       
   123     printf("Encoding = %d\n", pcxh.Encoding);
       
   124     printf("BitsPerPixel = %d\n", pcxh.BitsPerPixel);
       
   125     printf("Xmin = %d, Ymin = %d, Xmax = %d, Ymax = %d\n", pcxh.Xmin, pcxh.Ymin, pcxh.Xmax, pcxh.Ymax);
       
   126     printf("HDpi = %d, VDpi = %d\n", pcxh.HDpi, pcxh.VDpi);
       
   127     printf("NPlanes = %d\n", pcxh.NPlanes);
       
   128     printf("BytesPerLine = %d\n", pcxh.BytesPerLine);
       
   129     printf("PaletteInfo = %d\n", pcxh.PaletteInfo);
       
   130     printf("HscreenSize = %d\n", pcxh.HscreenSize);
       
   131     printf("VscreenSize = %d\n", pcxh.VscreenSize);
       
   132 #endif
   117 
   133 
   118     /* Create the surface of the appropriate type */
   134     /* Create the surface of the appropriate type */
   119     width = (pcxh.Xmax - pcxh.Xmin) + 1;
   135     width = (pcxh.Xmax - pcxh.Xmin) + 1;
   120     height = (pcxh.Ymax - pcxh.Ymin) + 1;
   136     height = (pcxh.Ymax - pcxh.Ymin) + 1;
   121     Rmask = Gmask = Bmask = Amask = 0;
   137     Rmask = Gmask = Bmask = Amask = 0;
   142                    bits, Rmask, Gmask, Bmask, Amask);
   158                    bits, Rmask, Gmask, Bmask, Amask);
   143     if ( surface == NULL )
   159     if ( surface == NULL )
   144         goto done;
   160         goto done;
   145 
   161 
   146     bpl = pcxh.NPlanes * pcxh.BytesPerLine;
   162     bpl = pcxh.NPlanes * pcxh.BytesPerLine;
   147     if (bpl > surface->pitch) {
   163     if ( bpl > surface->pitch ) {
   148         error = "bytes per line is too large (corrupt?)";
   164         error = "bytes per line is too large (corrupt?)";
   149     }
   165         goto done;
   150     buf = (Uint8 *)SDL_calloc(SDL_max(bpl, surface->pitch), 1);
   166     }
       
   167     buf = (Uint8 *)SDL_calloc(surface->pitch, 1);
   151     row = (Uint8 *)surface->pixels;
   168     row = (Uint8 *)surface->pixels;
   152     for ( y=0; y<surface->h; ++y ) {
   169     for ( y=0; y<surface->h; ++y ) {
   153         /* decode a scan line to a temporary buffer first */
   170         /* decode a scan line to a temporary buffer first */
   154         int i, count = 0;
   171         int i;
   155         Uint8 ch;
   172         Uint8 *dst = buf;
   156         Uint8 *dst = (src_bits == 8) ? row : buf;
       
   157         if ( pcxh.Encoding == 0 ) {
   173         if ( pcxh.Encoding == 0 ) {
   158             if(!SDL_RWread(src, dst, bpl, 1)) {
   174             if ( !SDL_RWread(src, dst, bpl, 1) ) {
   159                 error = "file truncated";
   175                 error = "file truncated";
   160                 goto done;
   176                 goto done;
   161             }
   177             }
   162         } else {
   178         } else {
   163             for(i = 0; i < bpl; i++) {
   179             for ( i = 0; i < bpl; i++ ) {
   164                 if(!count) {
   180                 if ( !count ) {
   165                     if(!SDL_RWread(src, &ch, 1, 1)) {
   181                     if ( !SDL_RWread(src, &ch, 1, 1) ) {
   166                         error = "file truncated";
   182                         error = "file truncated";
   167                         goto done;
   183                         goto done;
   168                     }
   184                     }
   169                     if( (ch & 0xc0) == 0xc0) {
   185                     if ( ch < 0xc0 ) {
   170                         count = ch & 0x3f;
   186                         count = 1;
   171                         if(!SDL_RWread(src, &ch, 1, 1)) {
   187                     } else {
       
   188                         count = ch - 0xc0;
       
   189                         if( !SDL_RWread(src, &ch, 1, 1) ) {
   172                             error = "file truncated";
   190                             error = "file truncated";
   173                             goto done;
   191                             goto done;
   174                         }
   192                         }
   175                     } else
   193                     }
   176                         count = 1;
       
   177                 }
   194                 }
   178                 dst[i] = ch;
   195                 dst[i] = ch;
   179                 count--;
   196                 count--;
   180             }
   197             }
   181         }
   198         }
   182 
   199 
   183         if(src_bits <= 4) {
   200         if ( src_bits <= 4 ) {
   184             /* expand planes to 1 byte/pixel */
   201             /* expand planes to 1 byte/pixel */
   185             Uint8 *innerSrc = buf;
   202             Uint8 *innerSrc = buf;
   186             int plane;
   203             int plane;
   187             for(plane = 0; plane < pcxh.NPlanes; plane++) {
   204             for ( plane = 0; plane < pcxh.NPlanes; plane++ ) {
   188                 int j, k, x = 0;
   205                 int j, k, x = 0;
   189                 for(j = 0; j < pcxh.BytesPerLine; j++) {
   206                 for( j = 0; j < pcxh.BytesPerLine; j++ ) {
   190                     Uint8 byte = *innerSrc++;
   207                     Uint8 byte = *innerSrc++;
   191                     for(k = 7; k >= 0; k--) {
   208                     for( k = 7; k >= 0; k-- ) {
   192                         unsigned bit = (byte >> k) & 1;
   209                         unsigned bit = (byte >> k) & 1;
   193                         /* skip padding bits */
   210                         /* skip padding bits */
   194                         if (j * 8 + k >= width)
   211                         if (j * 8 + k >= width)
   195                             continue;
   212                             continue;
   196                         row[x++] |= bit << plane;
   213                         row[x++] |= bit << plane;
   197                     }
   214                     }
   198                 }
   215                 }
   199             }
   216             }
   200         } else if(src_bits == 24) {
   217         } else if ( src_bits == 24 ) {
   201             /* de-interlace planes */
   218             /* de-interlace planes */
   202             Uint8 *innerSrc = buf;
   219             Uint8 *innerSrc = buf;
   203             int plane;
   220             int plane;
   204             for(plane = 0; plane < pcxh.NPlanes; plane++) {
   221             for ( plane = 0; plane < pcxh.NPlanes; plane++ ) {
   205                 int x;
   222                 int x;
   206                 dst = row + plane;
   223                 dst = row + plane;
   207                 for(x = 0; x < width; x++) {
   224                 for ( x = 0; x < width; x++ ) {
       
   225                     if ( dst >= row+surface->pitch ) {
       
   226                         error = "decoding out of bounds (corrupt?)";
       
   227                         goto done;
       
   228                     }
   208                     *dst = *innerSrc++;
   229                     *dst = *innerSrc++;
   209                     dst += pcxh.NPlanes;
   230                     dst += pcxh.NPlanes;
   210                 }
   231                 }
   211             }
   232             }
       
   233         } else {
       
   234             SDL_memcpy(row, buf, bpl);
   212         }
   235         }
   213 
   236 
   214         row += surface->pitch;
   237         row += surface->pitch;
   215     }
   238     }
   216 
   239 
   217     if(bits == 8) {
   240     if ( bits == 8 ) {
   218         SDL_Color *colors = surface->format->palette->colors;
   241         SDL_Color *colors = surface->format->palette->colors;
   219         int nc = 1 << src_bits;
   242         int nc = 1 << src_bits;
   220         int i;
   243         int i;
   221 
   244 
   222         surface->format->palette->ncolors = nc;
   245         surface->format->palette->ncolors = nc;
   223         if(src_bits == 8) {
   246         if ( src_bits == 8 ) {
   224             Uint8 ch;
   247             Uint8 ch;
   225             /* look for a 256-colour palette */
   248             /* look for a 256-colour palette */
   226             do {
   249             do {
   227                 if ( !SDL_RWread(src, &ch, 1, 1)) {
   250                 if ( !SDL_RWread(src, &ch, 1, 1) ) {
   228                     error = "file truncated";
   251                     /* Couldn't find the palette, try the end of the file */
   229                     goto done;
   252                     SDL_RWseek(src, -768, RW_SEEK_END);
       
   253                     break;
   230                 }
   254                 }
   231             } while ( ch != 12 );
   255             } while ( ch != 12 );
   232 
   256 
   233             for(i = 0; i < 256; i++) {
   257             for ( i = 0; i < 256; i++ ) {
   234                 SDL_RWread(src, &colors[i].r, 1, 1);
   258                 SDL_RWread(src, &colors[i].r, 1, 1);
   235                 SDL_RWread(src, &colors[i].g, 1, 1);
   259                 SDL_RWread(src, &colors[i].g, 1, 1);
   236                 SDL_RWread(src, &colors[i].b, 1, 1);
   260                 SDL_RWread(src, &colors[i].b, 1, 1);
   237             }
   261             }
   238         } else {
   262         } else {
   239             for(i = 0; i < nc; i++) {
   263             for ( i = 0; i < nc; i++ ) {
   240                 colors[i].r = pcxh.Colormap[i * 3];
   264                 colors[i].r = pcxh.Colormap[i * 3];
   241                 colors[i].g = pcxh.Colormap[i * 3 + 1];
   265                 colors[i].g = pcxh.Colormap[i * 3 + 1];
   242                 colors[i].b = pcxh.Colormap[i * 3 + 2];
   266                 colors[i].b = pcxh.Colormap[i * 3 + 2];
   243             }
   267             }
   244         }
   268         }