]> git.sur5r.net Git - cc65/commitdiff
Some more work on reading pcx files.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 26 Feb 2012 11:54:05 +0000 (11:54 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 26 Feb 2012 11:54:05 +0000 (11:54 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@5554 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/sp65/bitmap.c
src/sp65/bitmap.h
src/sp65/main.c
src/sp65/pcx.c

index acf3f866633ed09c449a06388b20e883d18bc387..50846aa9928a176c8ae6876afb11380722dc2919 100644 (file)
@@ -65,7 +65,8 @@ Bitmap* NewBitmap (unsigned Width, unsigned Height)
 
     /* Initialize the data */
     B->Type     = bmUnknown;
-    SB_Init (&B->Name);
+    B->Name     = EmptyStrBuf;
+    B->Tag      = 0;
     B->Width    = Width;
     B->Height   = Height;
     B->Pal      = 0;
@@ -79,8 +80,10 @@ Bitmap* NewBitmap (unsigned Width, unsigned Height)
 void FreeBitmap (Bitmap* B)
 /* Free a dynamically allocated bitmap */
 {
-    /* Free the palette */
+    /* Free the format specific data, the palette and then the bitmap */
+    xfree (B->Tag);
     xfree (B->Pal);
+    xfree(B);
 }
 
 
index 9d0a967540313100765e49a856c5ba9a6935ee82..dd0ce7f94782e5a6b2a2974079be332335cdd2d1 100644 (file)
@@ -80,6 +80,11 @@ struct Bitmap {
      */
     StrBuf      Name;
 
+    /* Pointer to some format specific data. May be used by the frontend.
+     * The data is free'd as a block when calling FreeBitmap.
+     */
+    void*       Tag;
+
     /* Size of the bitmap */
     unsigned    Width;
     unsigned    Height;
index 66fb594b736bc460755b5e50148dede2890d0162..1c57de983b8346d0481526da10a09714c67b5a63 100644 (file)
@@ -40,6 +40,7 @@
 
 /* common */
 #include "cmdline.h"
+#include "print.h"
 #include "version.h"
 
 /* sp65 */
 static void Usage (void)
 /* Print usage information and exit */
 {
-    fprintf (stderr,
-            "Usage: %s [options] file [options] [file]\n"
-            "Short options:\n"
-                    "  -h\t\t\tHelp (this text)\n"
-                    "  -V\t\t\tPrint the version number and exit\n"
-            "\n"
-            "Long options:\n"
-            "  --help\t\tHelp (this text)\n"
-                    "  --version\t\tPrint the version number and exit\n",
-            ProgName);
+    printf (
+           "Usage: %s [options] file [options] [file]\n"
+           "Short options:\n"
+                   "  -V\t\t\tPrint the version number and exit\n"
+                   "  -h\t\t\tHelp (this text)\n"
+            "  -v\t\t\tIncrease verbosity\n"
+           "\n"
+           "Long options:\n"
+           "  --help\t\tHelp (this text)\n"
+            "  --verbose\t\tIncrease verbosity\n"
+                   "  --version\t\tPrint the version number and exit\n",
+           ProgName);
 }
 
 
@@ -81,6 +84,15 @@ static void OptHelp (const char* Opt attribute ((unused)),
 
 
 
+static void OptVerbose (const char* Opt attribute ((unused)),
+                       const char* Arg attribute ((unused)))
+/* Increase versbosity */
+{
+    ++Verbosity;
+}
+
+
+
 static void OptVersion (const char* Opt attribute ((unused)),
                        const char* Arg attribute ((unused)))
 /* Print the assembler version */
@@ -98,6 +110,7 @@ int main (int argc, char* argv [])
     /* Program long options */
     static const LongOpt OptTab[] = {
        { "--help",             0,      OptHelp                 },
+               { "--verbose",          0,      OptVerbose              },
        { "--version",          0,      OptVersion              },
     };
 
@@ -121,13 +134,17 @@ int main (int argc, char* argv [])
                    LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
                    break;
 
+                       case 'V':
+                   OptVersion (Arg, 0);
+                           break;
+
                case 'h':
                    OptHelp (Arg, 0);
                    break;
 
-                       case 'V':
-                   OptVersion (Arg, 0);
-                           break;
+               case 'v':
+                   OptVerbose (Arg, 0);
+                   break;
 
                        default:
                            UnknownOption (Arg);
index 2ba0652de874176af510864c4b7c3c4e7b0b83d0..5903a9066f8dbcae8eeb5d3553bdd0c71e3375b6 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+/* common */
+#include "print.h"
+#include "xmalloc.h"
+
 /* sp65 */
 #include "error.h"
 #include "fileio.h"
 
 
 
-/* Size of the PCX header and other constants */
-#define PCX_HEADER_SIZE         128
+/* Some PCX constants */
 #define PCX_MAGIC_ID            0x0A
 
-/* Type of a PCX header */
-typedef unsigned char           PCXHeader[PCX_HEADER_SIZE];
-
-/* The following macros are used to access the PCX header, which is a 128 byte
- * block of raw data.
- */
+/* A raw PCX header is just a block of bytes */
+typedef unsigned char           RawPCXHeader[128];
+
+/* Structured PCX header */
+typedef struct PCXHeader PCXHeader;
+struct PCXHeader {
+    unsigned    Id;
+    unsigned    FileVersion;
+    unsigned    Compressed;
+    unsigned    BPP;
+    unsigned    XMin;
+    unsigned    YMin;
+    unsigned    XMax;
+    unsigned    YMax;
+    unsigned    XDPI;
+    unsigned    YDPI;
+    unsigned    Planes;
+    unsigned    BytesPerPlane;
+    unsigned    PalInfo;
+    unsigned    ScreenWidth;
+    unsigned    ScreenHeight;
+
+    /* Calculated data */
+    unsigned    Width;
+    unsigned    Height;
+};
+
+/* Read a little endian word from a byte array at offset O */
 #define WORD(H, O)              ((H)[O] | ((H)[O+1] << 8))
-#define PCX_ID(H)               ((H)[0])
-#define PCX_FILE_VERSION(H)     ((H)[1])
-#define PCX_COMPRESSION(H)      ((H)[2])
-#define PCX_BPP(H)              ((H)[3])
-#define PCX_XMIN(H)             WORD(H, 4)
-#define PCX_YMIN(H)             WORD(H, 6)
-#define PCX_XMAX(H)             WORD(H, 8)
-#define PCX_YMAX(H)             WORD(H, 10)
-#define PCX_PLANES(H)           ((H)[65])
-#define PCX_BYTES_PER_LINE(H)   WORD(H, 66)
-#define PCX_PAL_INFO(H)         WORD(H, 68)
-#define PCX_WIDTH(H)            WORD(H, 70)
-#define PCX_HEIGHT(H)           WORD(H, 72)
 
 
 
@@ -83,13 +95,98 @@ typedef unsigned char           PCXHeader[PCX_HEADER_SIZE];
 
 
 
+static PCXHeader* NewPCXHeader (void)
+/* Allocate a new PCX header and return it */
+{
+    /* No initialization here */
+    return xmalloc (sizeof (PCXHeader));
+}
+
+
+
+static PCXHeader* ReadPCXHeader (FILE* F, const char* Name)
+/* Read a structured PCX header from the given file and return it */
+{
+    RawPCXHeader H;
+
+    /* Allocate a new PCXHeader structure */
+    PCXHeader* P = NewPCXHeader ();
+
+    /* Read the raw header */
+    ReadData (F, H, sizeof (H));
+
+    /* Convert the data into structured form */
+    P->Id               = H[0];
+    P->FileVersion      = H[1];
+    P->Compressed       = H[2];
+    P->BPP              = H[3];
+    P->XMin             = WORD (H, 4);
+    P->YMin             = WORD (H, 6);
+    P->XMax             = WORD (H, 8);
+    P->YMax             = WORD (H, 10);
+    P->XDPI             = WORD (H, 12);
+    P->YDPI             = WORD (H, 14);
+    P->Planes           = H[65];
+    P->BytesPerPlane    = WORD (H, 66);
+    P->PalInfo          = WORD (H, 68);
+    P->ScreenWidth      = WORD (H, 70);
+    P->ScreenHeight     = WORD (H, 72);
+    P->Width            = P->XMax - P->XMin + 1;
+    P->Height           = P->YMax - P->YMin + 1;
+
+    /* Check the header data */
+    if (P->Id != PCX_MAGIC_ID || P->FileVersion == 1 || P->FileVersion > 5) {
+        Error ("`%s' is not a PCX file", Name);
+    }
+    if (P->Compressed > 1) {
+        Error ("Unsupported compression (%d) in PCX file `%s'",
+               P->Compressed, Name);
+    }
+    if (P->BPP != 1 && P->BPP != 4 && P->BPP != 8) {
+        Error ("Unsupported bit depth (%u) in PCX file `%s'",
+               P->BPP, Name);
+    }
+    if (P->PalInfo != 1 && P->PalInfo != 2) {
+        Error ("Unsupported palette info (%u) in PCX file `%s'",
+               P->PalInfo, Name);
+    }
+    if (!ValidBitmapSize (P->Width, P->Height)) {
+        Error ("PCX file `%s' has an unsupported size (w=%u, h=%d)",
+               Name, P->Width, P->Height);
+    }
+
+    /* Return the structured header */
+    return P;
+}
+
+
+
+static void DumpPCXHeader (const PCXHeader* P, const char* Name)
+/* Dump the header of the PCX file in readable form to stdout */
+{
+    printf ("File name:      %s\n", Name);
+    printf ("PCX Version:    ");
+    switch (P->FileVersion) {
+        case 0: puts ("2.5");                             break;
+        case 2: puts ("2.8 with palette");                break;
+        case 3: puts ("2.8 without palette");             break;
+        case 4: puts ("PCX for Windows without palette"); break;
+        case 5: puts ("3.0");                             break;
+    }
+    printf ("Image type:     %s\n", P->PalInfo? "color" : "grayscale");
+    printf ("Compression:    %s\n", P->Compressed? "RLE" : "None");
+    printf ("Structure:      %u planes of %u bits\n", P->Planes, P->BPP);
+    printf ("Bounding box:   [%u/%u - %u/%u]\n", P->XMin, P->YMin, P->XMax, P->YMax);
+    printf ("Resolution:     %u/%u DPI\n", P->XDPI, P->YDPI);
+    printf ("Screen size:    %u/%u\n", P->ScreenWidth, P->ScreenHeight);
+}
+
+
+
 Bitmap* ReadPCXFile (const char* Name)
 /* Read a bitmap from a PCX file */
 {
-    PCXHeader H;
-    unsigned Version, Compression;
-    unsigned BPP, Planes, BytesPerLine;
-    unsigned Width, Height;
+    PCXHeader* P;
     Bitmap* B;
 
     /* Open the file */
@@ -99,34 +196,11 @@ Bitmap* ReadPCXFile (const char* Name)
     }
 
     /* Read the PCX header */
-    ReadData (F, H, sizeof (H));
-
-    /* Check the magic id byte */
-    if (PCX_ID (H) != PCX_MAGIC_ID) {
-        Error ("`%s' is not a PCX file", Name);
-    }
+    P = ReadPCXHeader (F, Name);
 
-    /* Read more data */
-    Version      = PCX_FILE_VERSION (H);
-    Compression  = PCX_COMPRESSION (H);
-    BPP          = PCX_BPP (H);
-    Planes       = PCX_PLANES (H);
-    BytesPerLine = PCX_BYTES_PER_LINE (H);
-    Width        = PCX_XMAX (H) - PCX_XMIN (H) + 1;
-    Height       = PCX_YMAX (H) - PCX_YMIN (H) + 1;
-
-    /* Check the data */
-    if (Compression != 0 && Compression != 1) {
-        Error ("Unsupported compression (%d) in PCX file `%s'",
-               Compression, Name);
-    }
-    if (BPP != 1 && BPP != 4 && BPP != 8) {
-        Error ("Unsupported bit depth (%d) in PCX file `%s'",
-               BPP, Name);
-    }
-    if (!ValidBitmapSize (Width, Height)) {
-        Error ("PCX file `%s' has an unsupported size (w=%u, h=%d)",
-               Name, Width, Height);
+    /* Dump the header if requested */
+    if (Verbosity > 0) {
+        DumpPCXHeader (P, Name);
     }
 
     /* Close the file */