rnd-20020319-2-src
authorHolger Schemel <info@artsoft.org>
Tue, 19 Mar 2002 22:22:26 +0000 (23:22 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:36:21 +0000 (10:36 +0200)
CHANGES
src/libgame/image.c
src/libgame/image.h
src/libgame/pcx.c
src/main.h

diff --git a/CHANGES b/CHANGES
index 4cac89f6eeedc1227d630b6e9dc8632e835cd538..873ae7a6266369e77db38c0ab0aaa20f808f23a3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+Release Version 2.0.2 [XX XXX XXXX]
+-----------------------------------
+
 Release Version 2.0.1 [19 MAR 2002]
 -----------------------------------
        - bug in explosion code fixed that broke level 24 of "Baby Ghost Mine"
index 836f28435b4b2e2c6380cccd5e61aa3da5d80f09..ae53b44a3b8b2d909b610adf2ef0176655d4db5d 100644 (file)
@@ -30,15 +30,23 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
     Error(ERR_EXIT, "images with more than 256 colors are not supported");
 
   depth = 8;
+
   image = checked_malloc(sizeof(Image));
   image->data = checked_malloc(width * height * bytes_per_pixel);
   image->width = width;
   image->height = height;
   image->depth = depth;
   image->rgb.used = 0;
+
   for (i=0; i<MAX_COLORS; i++)
     image->rgb.color_used[i] = FALSE;
 
+  image->type = (depth < 8 ? IMAGETYPE_BITMAP :
+                depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
+
+  image->bytes_per_row = (depth + 7) / 8;
+  image->bytes_per_row *= width;
+
   return image;
 }
 
@@ -53,20 +61,33 @@ void freeImage(Image *image)
 /* extra colors to try allocating in private color maps to minimize flashing */
 #define NOFLASH_COLORS 256
 
-/* architecture independent value-to-memory conversion
+/* architecture independent value <-> memory conversions;
    note: the internal format is big endian */
 
-#define value_to_memory(value, ptr, length) (                          \
-(length) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :              \
-(length) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),        \
-                *(((byte *)(ptr))+1) = ( value     ) ) :               \
-(length) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),        \
-                *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
-                *(((byte *)(ptr))+2) = ( value     ) ) :               \
-                (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),        \
-                *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
-                *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
-                *(((byte *)(ptr))+3) = ( value     ) ))
+#define memory_to_value(ptr, len) (                                        \
+(len) == 1 ? (unsigned long)(                 *( (byte *)(ptr))         ) : \
+(len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<< 8)   \
+                         + (                 *(((byte *)(ptr))+1)      ) : \
+(len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<16)   \
+                         + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8)   \
+                         + (                 *(((byte *)(ptr))+2)      ) : \
+            (unsigned long)(((unsigned long)(*( (byte *)(ptr))   ))<<24)   \
+                         + (((unsigned long)(*(((byte *)(ptr))+1)))<<16)   \
+                         + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8)   \
+                         + (                 *(((byte *)(ptr))+3)      ) )
+
+
+#define value_to_memory(value, ptr, len) (                             \
+(len) == 1 ? (*( (byte *)(ptr)   ) = ( value     ) ) :                 \
+(len) == 2 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>> 8),   \
+             *(((byte *)(ptr))+1) = ( value     ) ) :                  \
+(len) == 3 ? (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>16),   \
+             *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8),    \
+             *(((byte *)(ptr))+2) = ( value     ) ) :                  \
+             (*( (byte *)(ptr)   ) = (((unsigned long)(value))>>24),   \
+             *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16),    \
+             *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8),    \
+             *(((byte *)(ptr))+3) = ( value     ) ))
 
 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
 {
@@ -243,7 +264,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
 
          /* something completely unexpected happened */
 
-         fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n");
+         fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
           free(redvalue);
           free(greenvalue);
           free(bluevalue);
@@ -416,18 +437,49 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
     {
       Pixel pixval;
 
-      for (y=0; y<image->height; y++)          /* general case */
+      switch (image->type)
       {
-       for (x=0; x<image->width; x++)
+        case IMAGETYPE_RGB:
+       {
+         for (y=0; y<image->height; y++)               /* general case */
+         {
+           for (x=0; x<image->width; x++)
+           {
+             pixval = *src_ptr++;
+             pixval =
+               redvalue[image->rgb.red[pixval] >> 8] |
+               greenvalue[image->rgb.green[pixval] >> 8] |
+               bluevalue[image->rgb.blue[pixval] >> 8];
+             value_to_memory(pixval, dst_ptr, bytes_per_pixel);
+             dst_ptr += bytes_per_pixel;
+           }
+         }
+         break;
+       }
+
+        case IMAGETYPE_TRUECOLOR:
        {
-         pixval = *src_ptr++;
-         pixval =
-           redvalue[image->rgb.red[pixval] >> 8] |
-           greenvalue[image->rgb.green[pixval] >> 8] |
-           bluevalue[image->rgb.blue[pixval] >> 8];
-         value_to_memory(pixval, dst_ptr, bytes_per_pixel);
-         dst_ptr += bytes_per_pixel;
+         for (y=0; y<image->height; y++)               /* general case */
+         {
+           for (x=0; x<image->width; x++)
+           {
+             pixval = memory_to_value(src_ptr, image->depth);
+             pixval =
+               redvalue[TRUECOLOR_RED(pixval)] |
+               greenvalue[TRUECOLOR_GREEN(pixval)] |
+               bluevalue[TRUECOLOR_BLUE(pixval)];
+             value_to_memory(pixval, dst_ptr, bytes_per_pixel);
+             src_ptr += image->depth;
+             dst_ptr += bytes_per_pixel;
+           }
+         }
+         break;
        }
+
+        default:
+         Error(ERR_RETURN, "image type not supported");
+         Error(ERR_EXIT, "RGB or TrueColor image needed");
+         break;
       }
       break;
     }
index 1e1b6cb5d50fc2672c6a313f6acf9bf0e00d9f9a..2b3af63d7723c61060309e2e546796d93b0b66fd 100644 (file)
@@ -45,13 +45,24 @@ struct RGBMap
 
 typedef struct
 {
+  unsigned int  type;          /* type of image (True-Color etc.)     */
   struct RGBMap rgb;           /* RGB map of image if IRGB type       */
   unsigned int  width;         /* width of image in pixels            */
   unsigned int  height;                /* height of image in pixels           */
   unsigned int  depth;         /* depth of image in bits if IRGB type */
+  unsigned int  bytes_per_row; /* ((depth + 7) / 8) bytes * width     */
   byte         *data;          /* image data                          */
 } Image;
 
+#define IMAGETYPE_BITMAP       0       /* monochrome bitmap       */
+#define IMAGETYPE_RGB          1       /* RGB image with colormap */
+#define IMAGETYPE_TRUECOLOR    2       /* true-color image        */
+
+#define TRUECOLOR_RED(pixel)   (((unsigned long)((pixel) & 0xff0000)) >> 16)
+#define TRUECOLOR_GREEN(pixel) (((unsigned long)((pixel) & 0xff00)) >> 8)
+#define TRUECOLOR_BLUE(pixel)  ( (unsigned long)((pixel) & 0xff))
+#define RGB_TO_TRUECOLOR(r,g,b)        ((((unsigned long)((r) & 0xff00)) << 8) | ((g) & 0xff00) | (((unsigned short)(b)) >> 8))
+
 Image *newImage(unsigned int, unsigned int, unsigned int);
 void freeImage(Image *);
 void freeXImage(Image *, XImageInfo *);
index a43e67d5ff4ea2d5ccbbe17857c80fc7c2d3249c..58c19bd3caac8e9616244c474b7b456642ebbc55 100644 (file)
 #include "misc.h"
 
 
-#define PCX_DEBUG              FALSE
+#define PCX_DEBUG              TRUE
 
 #define PCX_MAGIC              0x0a    /* first byte in a PCX image file    */
-#define PCX_LAST_VERSION       5       /* last acceptable version number    */
+#define PCX_SUPPORTED_VERSION  5       /* last acceptable version number    */
 #define PCX_ENCODING           1       /* PCX encoding method               */
 #define PCX_256COLORS_MAGIC    0x0c    /* first byte of a PCX 256 color map */
-#define PCX_MAXDEPTH           8       /* supports up to 8 bits per pixel   */
 #define PCX_MAXCOLORS          256     /* maximum number of colors          */
 
 #define PCX_HEADER_SIZE                128
@@ -36,7 +35,7 @@ struct PCX_Header
   unsigned char signature;     /* PCX file identifier                 */
   unsigned char version;       /* version compatibility level         */
   unsigned char encoding;      /* encoding method                     */
-  unsigned char bits_per_pixel;        /* bits per pixel, or depth            */
+  unsigned char bits_per_pixel;        /* bits per pixel (not depth!)         */
   unsigned short xmin;         /* X position of left edge             */
   unsigned short ymin;         /* Y position of top edge              */
   unsigned short xmax;         /* X position of right edge            */
@@ -45,7 +44,7 @@ struct PCX_Header
   unsigned short vres;         /* Y screen resolution of source image */
   unsigned char palette[16][3];        /* PCX color map                       */
   unsigned char reserved;      /* should be 0, 1 if std res fax       */
-  unsigned char color_planes;  /* bit planes in image                 */
+  unsigned char color_planes;  /* "color planes" in image             */
   unsigned short bytes_per_line;/* byte delta between scanlines        */
   unsigned short palette_type; /* 0 = undef, 1 = color, 2 = grayscale */
   unsigned char filler[58];    /* fill to struct size of 128          */
@@ -54,6 +53,7 @@ struct PCX_Header
 /* global PCX error value */
 int errno_pcx = PCX_Success;
 
+#if 0
 static byte *PCX_ReadBitmap(Image *image, byte *buffer_ptr, byte *buffer_last)
 {
   /* Run Length Encoding: If the two high bits are set,
@@ -97,7 +97,99 @@ static byte *PCX_ReadBitmap(Image *image, byte *buffer_ptr, byte *buffer_last)
   /* return current buffer position for next decoding function */
   return buffer_ptr;
 }
+#endif
+
+static boolean PCX_ReadBitmap(FILE *file, struct PCX_Header *pcx, Image *image)
+{
+  int width = image->width;
+  int height = image->height;
+  int pcx_depth = pcx->bits_per_pixel * pcx->color_planes;
+  int bytes_per_row = pcx->color_planes * pcx->bytes_per_line;
+  byte *row_buffer = checked_malloc(bytes_per_row);
+  byte *bitmap_ptr = image->data;
+  int y;
+
+  for (y = 0; y < height; y++)
+  {
+    /* decode a scan line into a temporary buffer first */
+    byte *dst_ptr = (pcx_depth == 8) ? bitmap_ptr : row_buffer;
+    byte value = 0, count = 0;
+    int value_int;
+    int i;
+
+    for (i = 0; i < bytes_per_row; i++)
+    {
+      if (count == 0)
+      {
+       if ((value_int = fgetc(file)) == EOF)
+         return FALSE;
+       value = (byte)value_int;
+
+       if ((value & 0xc0) == 0xc0)     /* this is a repeat count byte */
+       {
+         count = value & 0x3f;         /* extract repeat count from byte */
+         if ((value_int = fgetc(file)) == EOF)
+           return FALSE;
+         value = (byte)value_int;
+       }
+       else
+         count = 1;
+      }
+
+      dst_ptr[i] = value;
+      count--;
+
+      if (pcx_depth == 8)
+       image->rgb.color_used[value] = TRUE;
+    }
+
+    if (pcx_depth <= 4)                        /* expand planes to 1 byte/pixel */
+    {
+      byte *src_ptr = row_buffer;
+      int plane;
+
+      for (plane = 0; plane < pcx->color_planes; plane++)
+      {
+       int i, j, x = 0;
+
+       for(i = 0; i < pcx->bytes_per_line; i++)
+       {
+         byte value = *src_ptr++;
+
+         for(j = 7; j >= 0; j--)
+         {
+           byte bit = (value >> j) & 1;
+
+           bitmap_ptr[x++] |= bit << plane;
+         }
+       }
+      }
+    }
+    else if (pcx_depth == 24)          /* de-interlace planes */
+    {
+      byte *src_ptr = row_buffer;
+      int plane;
+
+      for(plane = 0; plane < pcx->color_planes; plane++)
+      {
+       int x;
+
+       dst_ptr = bitmap_ptr + plane;
+       for(x = 0; x < width; x++)
+       {
+         *dst_ptr = *src_ptr++;
+         dst_ptr += pcx->color_planes;
+       }
+      }
+    }
+
+    bitmap_ptr += image->bytes_per_row;
+  }
 
+  return TRUE;
+}
+
+#if 0
 static byte *PCX_ReadColormap(Image *image,byte *buffer_ptr, byte *buffer_last)
 {
   int i, magic;
@@ -124,16 +216,59 @@ static byte *PCX_ReadColormap(Image *image,byte *buffer_ptr, byte *buffer_last)
   /* return current buffer position for next decoding function */
   return buffer_ptr;
 }
+#endif
+
+static boolean PCX_ReadColormap(FILE *file,struct PCX_Header *pcx,Image *image)
+{
+  int pcx_depth = pcx->bits_per_pixel * pcx->color_planes;
+  int num_colors = (1 << pcx_depth);
+  int i;
+
+  if (image->depth != 8)
+    return TRUE;
+
+  if (pcx_depth == 8)
+  {
+    byte value;
+    int value_int;
+
+    /* look for a 256-colour palette */
+    do
+    {
+      if ((value_int = fgetc(file)) == EOF)
+       return FALSE;
+      value = (byte)value_int;
+    }
+    while (value != PCX_256COLORS_MAGIC);
+
+    /* read 256 colors from PCX colormap */
+    for(i = 0; i < PCX_MAXCOLORS; i++)
+    {
+      image->rgb.red[i]   = (byte)fgetc(file) << 8;
+      image->rgb.green[i] = (byte)fgetc(file) << 8;
+      image->rgb.blue[i]  = (byte)fgetc(file) << 8;
+    }
+  }
+  else
+  {
+    for(i = 0; i < num_colors; i++)
+    {
+      image->rgb.red[i]   = pcx->palette[i][0] << 8;
+      image->rgb.green[i] = pcx->palette[i][1] << 8;
+      image->rgb.blue[i]  = pcx->palette[i][2] << 8;
+    }
+  }
+
+  return TRUE;
+}
 
 Image *Read_PCX_to_Image(char *filename)
 {
   FILE *file;
-  byte *file_buffer;
-  byte *buffer_ptr, *buffer_last;
-  unsigned int file_length;
+  byte header_buffer[PCX_HEADER_SIZE];
   struct PCX_Header pcx;
   Image *image;
-  int width, height, depth;
+  int width, height, depth, pcx_depth;
   int i;
 
   errno_pcx = PCX_Success;
@@ -144,57 +279,40 @@ Image *Read_PCX_to_Image(char *filename)
     return NULL;
   }
 
-  if (fseek(file, 0, SEEK_END) == -1)
-  {
-    fclose(file);
-    errno_pcx = PCX_ReadFailed;
-    return NULL;
-  }
-
-  file_length = ftell(file);
-  rewind(file);
-
-  if (file_length < PCX_HEADER_SIZE)
+  if (fread(header_buffer, 1, PCX_HEADER_SIZE, file) != PCX_HEADER_SIZE)
   {
-    /* PCX file is too short to contain a valid PCX header */
     fclose(file);
 
-    errno_pcx = PCX_FileInvalid;
-    return NULL;
-  }
-
-  file_buffer = checked_malloc(file_length);
-
-  if (fread(file_buffer, 1, file_length, file) != file_length)
-  {
-    fclose(file);
     errno_pcx = PCX_ReadFailed;
     return NULL;
   }
 
-  fclose(file);
-
-  pcx.signature      = file_buffer[0];
-  pcx.version        = file_buffer[1];
-  pcx.encoding       = file_buffer[2];
-  pcx.bits_per_pixel = file_buffer[3];
-  pcx.xmin           = file_buffer[4]  + 256 * file_buffer[5];
-  pcx.ymin           = file_buffer[6]  + 256 * file_buffer[7];
-  pcx.xmax           = file_buffer[8]  + 256 * file_buffer[9];
-  pcx.ymax           = file_buffer[10] + 256 * file_buffer[11];
-  pcx.color_planes   = file_buffer[65];
-  pcx.bytes_per_line = file_buffer[66] + 256 * file_buffer[67];
-  pcx.palette_type   = file_buffer[68] + 256 * file_buffer[69];
+  pcx.signature      = header_buffer[0];
+  pcx.version        = header_buffer[1];
+  pcx.encoding       = header_buffer[2];
+  pcx.bits_per_pixel = header_buffer[3];
+  pcx.xmin           = (header_buffer[5]  << 8) | header_buffer[4];
+  pcx.ymin           = (header_buffer[7]  << 8) | header_buffer[6];
+  pcx.xmax           = (header_buffer[9]  << 8) | header_buffer[8];
+  pcx.ymax           = (header_buffer[11] << 8) | header_buffer[10];
+  pcx.color_planes   = header_buffer[65];
+  pcx.bytes_per_line = (header_buffer[67] << 8) | header_buffer[66];
+  pcx.palette_type   = (header_buffer[69] << 8) | header_buffer[68];
+
+  for (i = 0; i < 48; i++)
+    pcx.palette[i / 3][i % 3] = header_buffer[16 + i];
 
   width  = pcx.xmax - pcx.xmin + 1;
   height = pcx.ymax - pcx.ymin + 1;
-  depth  = pcx.bits_per_pixel;
+  pcx_depth = pcx.bits_per_pixel * pcx.color_planes;
+  depth = ((pcx_depth + 7) / 8) * 8;
 
-  if (pcx.signature != PCX_MAGIC || pcx.version > PCX_LAST_VERSION ||
-      pcx.encoding != PCX_ENCODING || pcx.color_planes > PCX_MAXDEPTH ||
+  if (pcx.signature != PCX_MAGIC ||
+      pcx.version != PCX_SUPPORTED_VERSION ||
+      pcx.encoding != PCX_ENCODING ||
       width < 0 || height < 0)
   {
-    free(file_buffer);
+    fclose(file);
 
     errno_pcx = PCX_FileInvalid;
     return NULL;
@@ -203,10 +321,9 @@ Image *Read_PCX_to_Image(char *filename)
 #if PCX_DEBUG
   if (options.verbose)
   {
-    printf("%s is a %dx%d PC Paintbrush image with %d bitplanes\n",
-          filename, width, height,
-          pcx.color_planes);
-    printf("depth: %d\n", pcx.bits_per_pixel);
+    printf("%s is a %dx%d PC Paintbrush image\n", filename, width, height);
+    printf("depth: %d\n", depth);
+    printf("bits_per_pixel: %d\n", pcx.bits_per_pixel);
     printf("color_planes: %d\n", pcx.color_planes);
     printf("bytes_per_line: %d\n", pcx.bytes_per_line);
     printf("palette type: %s\n",
@@ -218,43 +335,36 @@ Image *Read_PCX_to_Image(char *filename)
   /* allocate new image structure */
   image = newImage(width, height, depth);
 
-  buffer_ptr  = file_buffer + PCX_HEADER_SIZE;
-  buffer_last = file_buffer + file_length;
-
   /* read compressed bitmap data */
-  if ((buffer_ptr = PCX_ReadBitmap(image, buffer_ptr, buffer_last)) == NULL)
+  if (!PCX_ReadBitmap(file, &pcx, image))
   {
-    free(file_buffer);
+    fclose(file);
     freeImage(image);
 
     errno_pcx = PCX_FileInvalid;
     return NULL;
   }
 
-  if (file_length < PCX_HEADER_SIZE + PCX_COLORMAP_SIZE)
-  {
-    /* PCX file is too short to contain a valid 256 colors colormap */
-    fclose(file);
-    errno_pcx = PCX_ColorFailed;
-    return NULL;
-  }
-
   /* read colormap data */
-  if (!PCX_ReadColormap(image, buffer_ptr, buffer_last))
+  if (!PCX_ReadColormap(file, &pcx, image))
   {
-    free(file_buffer);
+    fclose(file);
     freeImage(image);
+
     errno_pcx = PCX_ColorFailed;
     return NULL;
   }
 
-  free(file_buffer);
+  fclose(file);
 
-  /* determine number of used colormap entries */
-  image->rgb.used = 0;
-  for (i=0; i<PCX_MAXCOLORS; i++)
-    if (image->rgb.color_used[i])
-      image->rgb.used++;
+  if (pcx_depth == 8)
+  {
+    /* determine number of used colormap entries for 8-bit PCX images */
+    image->rgb.used = 0;
+    for (i=0; i<PCX_MAXCOLORS; i++)
+      if (image->rgb.color_used[i])
+       image->rgb.used++;
+  }
 
 #if PCX_DEBUG
   if (options.verbose)
index 27cc057bde42de7ad8d069aac1422924ab4a964d..46d911202b0fc1293163f23a23651b6efc05a8c2 100644 (file)
@@ -1528,8 +1528,8 @@ extern int                num_element_info;
 
 #define PROGRAM_VERSION_MAJOR  2
 #define PROGRAM_VERSION_MINOR  0
-#define PROGRAM_VERSION_PATCH  1
-#define PROGRAM_VERSION_STRING "2.0.1"
+#define PROGRAM_VERSION_PATCH  2
+#define PROGRAM_VERSION_STRING "2.0.2"
 
 #define PROGRAM_TITLE_STRING   "Rocks'n'Diamonds"
 #define PROGRAM_AUTHOR_STRING  "Holger Schemel"