r103 - trunk/tools/lvl_tools

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Mar 17 18:39:59 EST 2005


Author: jonas
Date: 2005-03-17 18:39:59 -0500 (Thu, 17 Mar 2005)
New Revision: 103

Added:
   trunk/tools/lvl_tools/lvl2magick.c
Modified:
   trunk/tools/lvl_tools/Makefile
Log:
lvl2magick uses ImageMagick (libmagick-dev) to parse .lvl files,
read all images and write them as one big image. At the moment
the image is just one row which will result in illegal images
(for most programs), if the row size is too big.
Additionally it creates a text file with a description about the
image offsets, the format is:

Number of images
x_offset y_offset width height
...

The output format can be specified in the source file
(see char* type).



Modified: trunk/tools/lvl_tools/Makefile
===================================================================
--- trunk/tools/lvl_tools/Makefile	2005-03-15 13:40:58 UTC (rev 102)
+++ trunk/tools/lvl_tools/Makefile	2005-03-17 23:39:59 UTC (rev 103)
@@ -1,19 +1,27 @@
-CXX = gcc
-CXX_FLAGS = -W -Wall -ansi -pedantic
-CXX_DEBUG = -g #-fno-inline
-CXX_OPT = -O2 -march=pentium4 -ffast-math
-CXX_TOOL = -lpng
+CC         = gcc
+CC_FLAGS   = -ansi -pedantic -W -Wall
+CC_DEBUG   = -g #-fno-inline
+CC_OPT     = -O2 -march=pentium4 -ffast-math
+CC_TOOL    = -lpng
+CC_MAGICK  = `Magick-config --ldflags --libs`
 
-OBJS  = png_out.o xpm_out.o pgm_out.o png_xpm_out.o lvlextract.o
-BIN   = ../lvlextract
+OBJS        = png_out.o xpm_out.o pgm_out.o png_xpm_out.o lvlextract.o
+OBJS_MAGICK = lvl2magick.o
+BIN         = ../lvlextract
+BIN_MAGICK  = ../lvl2magick
 
-default: $(BIN)
+default: $(BIN_MAGICK)
 
+all: $(BIN) $(BIN_MAGICK)
+
 $(BIN): $(OBJS)
-	$(CXX) $(CXX_TOOL) $(OBJS) -o $(BIN)
+	$(CC) $(CC_TOOL) $(OBJS) -o $(BIN)
 
+$(BIN_MAGICK): $(OBJS_MAGICK)
+	$(CC) $(CC_MAGICK) $(OBJS_MAGICK) -o $(BIN_MAGICK)
+
 %.o: %.c
-	$(CXX) $(CXX_FLAGS) $(CXX_DEBUG) -c $< -o $@
+	$(CC) $(CC_FLAGS) $(CC_DEBUG) -c $< -o $@
 
 clean:
 	rm -f $(BIN)

Added: trunk/tools/lvl_tools/lvl2magick.c
===================================================================
--- trunk/tools/lvl_tools/lvl2magick.c	2005-03-15 13:40:58 UTC (rev 102)
+++ trunk/tools/lvl_tools/lvl2magick.c	2005-03-17 23:39:59 UTC (rev 103)
@@ -0,0 +1,333 @@
+/*
+ * (C) 2004 Jonas Jermann
+ *
+ * License: GPL
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <magick/api.h>
+
+enum {
+    red=0,
+    green=1,
+    blue=2
+};
+
+enum {
+    img_x=0,
+    img_y=1,
+    img_w=2,
+    img_h=3
+};
+
+/* RGB palette */
+unsigned short lvl_palette[256][3]= {
+    /* (One of) the first two RGB values is the background
+     * (colorkey) color... (colorkey used: 0xff00ff
+     * (before: 0x00, 0x00, 0x00)
+     */
+    0xff, 0x00, 0xff,     0xff, 0x00, 0xff, 
+
+                                                0x00, 0x00, 0x00,     0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00, 
+    0x08, 0x04, 0x00,     0x00, 0x04, 0x10,     0x08, 0x10, 0x00,     0x08, 0x10, 0x10, 
+    0x18, 0x10, 0x00,     0x18, 0x14, 0x10,     0x00, 0x08, 0x29,     0x00, 0x0c, 0x39, 
+    0x10, 0x14, 0x20,     0x18, 0x18, 0x20,     0x08, 0x20, 0x08,     0x08, 0x24, 0x29, 
+    0x18, 0x28, 0x39,     0x29, 0x10, 0x08,     0x20, 0x24, 0x00,     0x20, 0x24, 0x10, 
+    0x31, 0x24, 0x00,     0x31, 0x24, 0x00,     0x31, 0x34, 0x00,     0x31, 0x34, 0x10, 
+    0x20, 0x20, 0x20,     0x29, 0x24, 0x20,     0x20, 0x34, 0x29,     0x31, 0x30, 0x29, 
+    0x31, 0x30, 0x39,     0x00, 0x0c, 0x4a,     0x62, 0x65, 0x08,     0x73, 0x6d, 0x52, 
+    0x73, 0x00, 0xb4,     0x94, 0x38, 0x20,     0xa4, 0x65, 0x39,     0x31, 0x34, 0x4a, 
+    0x29, 0x34, 0x62,     0x08, 0x44, 0x10,     0x00, 0x65, 0x00,     0x29, 0x59, 0x39, 
+    0x31, 0x7d, 0x39,     0x29, 0x48, 0x6a,     0x4a, 0x0c, 0x08,     0x41, 0x2c, 0x00, 
+    0x41, 0x28, 0x10,     0x52, 0x2c, 0x10,     0x52, 0x3c, 0x10,     0x4a, 0x38, 0x29, 
+    0x41, 0x3c, 0x39,     0x62, 0x1c, 0x08,     0x73, 0x08, 0x08,     0x62, 0x3c, 0x10, 
+    0x7b, 0x20, 0x08,     0x73, 0x34, 0x10,     0x41, 0x3c, 0x4a,     0x41, 0x40, 0x00, 
+    0x41, 0x40, 0x10,     0x4a, 0x55, 0x00,     0x52, 0x40, 0x00,     0x52, 0x55, 0x08, 
+    0x52, 0x55, 0x18,     0x52, 0x44, 0x39,     0x5a, 0x59, 0x39,     0x62, 0x44, 0x00, 
+    0x62, 0x55, 0x00,     0x62, 0x55, 0x18,     0x73, 0x44, 0x10,     0x73, 0x59, 0x00, 
+    0x73, 0x59, 0x10,     0x62, 0x40, 0x20,     0x62, 0x44, 0x39,     0x73, 0x40, 0x20, 
+    0x7b, 0x44, 0x20,     0x7b, 0x55, 0x20,     0x7b, 0x59, 0x31,     0x62, 0x65, 0x08, 
+    0x62, 0x65, 0x18,     0x62, 0x75, 0x18,     0x7b, 0x6d, 0x08,     0x73, 0x6d, 0x18, 
+    0x7b, 0x7d, 0x08,     0x7b, 0x7d, 0x18,     0x7b, 0x6d, 0x29,     0x7b, 0x7d, 0x29, 
+    0x4a, 0x48, 0x52,     0x52, 0x50, 0x52,     0x4a, 0x4c, 0x6a,     0x4a, 0x4c, 0x7b, 
+    0x5a, 0x59, 0x62,     0x4a, 0x71, 0x5a,     0x6a, 0x55, 0x52,     0x73, 0x6d, 0x52, 
+    0x62, 0x65, 0x62,     0x62, 0x6d, 0x7b,     0x73, 0x71, 0x6a,     0x7b, 0x79, 0x7b, 
+    0x08, 0x10, 0x94,     0x00, 0x04, 0xac,     0x10, 0x1c, 0xa4,     0x18, 0x20, 0xbd, 
+    0x20, 0x30, 0x83,     0x00, 0x04, 0xf6,     0x29, 0x30, 0xc5,     0x29, 0x4c, 0x83, 
+    0x20, 0x40, 0xa4,     0x20, 0x55, 0xc5,     0x20, 0x4c, 0xee,     0x73, 0x00, 0xb4, 
+    0x4a, 0x4c, 0xac,     0x4a, 0x71, 0x83,     0x52, 0x6d, 0xac,     0x4a, 0x48, 0xcd, 
+    0x52, 0x4c, 0xee,     0x5a, 0x6d, 0xe6,     0x00, 0x99, 0x00,     0x10, 0xea, 0x08, 
+    0x4a, 0x85, 0x39,     0x4a, 0xa5, 0xac,     0x7b, 0x85, 0xa4,     0x5a, 0xba, 0xee, 
+    0x6a, 0x89, 0xee,     0x94, 0x08, 0x08,     0x94, 0x2c, 0x08,     0x94, 0x38, 0x20, 
+    0xac, 0x0c, 0x08,     0xb4, 0x30, 0x10,     0xb4, 0x34, 0x31,     0x94, 0x50, 0x10, 
+    0x8b, 0x4c, 0x20,     0x8b, 0x5d, 0x20,     0x8b, 0x5d, 0x31,     0x8b, 0x69, 0x00, 
+    0x9c, 0x69, 0x08,     0x94, 0x7d, 0x00,     0x94, 0x79, 0x39,     0xac, 0x55, 0x00, 
+    0xa4, 0x59, 0x20,     0xa4, 0x5d, 0x31,     0xbd, 0x50, 0x20,     0xa4, 0x65, 0x39, 
+    0xa4, 0x7d, 0x20,     0xac, 0x75, 0x39,     0xbd, 0x65, 0x29,     0xbd, 0x6d, 0x39, 
+    0x8b, 0x61, 0x4a,     0x9c, 0x79, 0x5a,     0xd5, 0x08, 0x08,     0xd5, 0x30, 0x20, 
+    0xf6, 0x08, 0x08,     0xf6, 0x28, 0x20,     0xf6, 0x38, 0x39,     0xc5, 0x59, 0x39, 
+    0xc5, 0x79, 0x29,     0xc5, 0x7d, 0x39,     0xde, 0x7d, 0x31,     0xe6, 0x59, 0x29, 
+    0xe6, 0x59, 0x52,     0xff, 0x59, 0x52,     0xb4, 0x24, 0xbd,     0x8b, 0x81, 0x10, 
+    0x94, 0x95, 0x00,     0x8b, 0x81, 0x20,     0x9c, 0x99, 0x20,     0xa4, 0x81, 0x00, 
+    0xa4, 0x81, 0x10,     0xac, 0x9d, 0x00,     0xbd, 0x81, 0x08,     0xac, 0x99, 0x20, 
+    0xb4, 0xae, 0x18,     0xa4, 0xaa, 0x20,     0xb4, 0xae, 0x29,     0xbd, 0xb6, 0x39, 
+    0x94, 0x81, 0x73,     0xa4, 0x99, 0x41,     0xbd, 0x99, 0x5a,     0xb4, 0x8d, 0x73, 
+    0xbd, 0xaa, 0x73,     0xc5, 0x9d, 0x00,     0xcd, 0x99, 0x20,     0xcd, 0xb6, 0x00, 
+    0xc5, 0xb6, 0x29,     0xd5, 0xba, 0x20,     0xde, 0xba, 0x39,     0xff, 0x99, 0x00, 
+    0xe6, 0xae, 0x00,     0xc5, 0x81, 0x4a,     0xc5, 0x95, 0x41,     0xd5, 0x99, 0x41, 
+    0xd5, 0x99, 0x52,     0xde, 0x85, 0x73,     0xd5, 0xaa, 0x5a,     0xd5, 0xb2, 0x6a, 
+    0xd5, 0xb6, 0x7b,     0xe6, 0x81, 0x52,     0xf6, 0x85, 0x73,     0xee, 0xa5, 0x5a, 
+    0xf6, 0xb2, 0x73,     0xd5, 0xce, 0x00,     0xd5, 0xca, 0x31,     0xd5, 0xd2, 0x20, 
+    0xde, 0xda, 0x39,     0xf6, 0xd2, 0x00,     0xff, 0xf2, 0x00,     0xee, 0xee, 0x20, 
+    0xf6, 0xf2, 0x39,     0xd5, 0xca, 0x41,     0xde, 0xda, 0x4a,     0xee, 0xde, 0x52, 
+    0xf6, 0xde, 0x73,     0xee, 0xe2, 0x41,     0xf6, 0xf2, 0x52,     0x8b, 0x89, 0x83, 
+    0x94, 0x95, 0x9c,     0x8b, 0x99, 0xb4,     0xb4, 0xa5, 0x94,     0xa4, 0xa5, 0xac, 
+    0xb4, 0xb2, 0xb4,     0xbe, 0xbd, 0xbe,     0x94, 0x91, 0xf6,     0xac, 0xb6, 0xd5, 
+    0xac, 0xb2, 0xff,     0xbd, 0xd2, 0xee,     0xd5, 0xb6, 0x94,     0xcd, 0xba, 0xb4, 
+    0xf6, 0x99, 0x94,     0xf6, 0xba, 0x9c,     0xde, 0xca, 0x8b,     0xde, 0xce, 0xa4, 
+    0xde, 0xd2, 0xb4,     0xff, 0xde, 0x94,     0xf6, 0xda, 0xbd,     0xff, 0xfa, 0xbd, 
+    0xcd, 0xca, 0xcd,     0xde, 0xda, 0xcd,     0xde, 0xda, 0xde,     0xd5, 0xf6, 0xff, 
+    0xe6, 0xe2, 0xee,     0xf6, 0xf2, 0xe6,     0xff, 0xfa, 0xff,     0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00,     0x00, 0x00, 0x00
+};
+
+
+/*
+ * Create an ImageMagick image of size width x height
+ * 
+ * image_info is an initialized ImageMagick ImageInfo* ptr
+ * ptr is the pointer to the image data offset
+ */
+Image* write_magick(unsigned char* ptr, ImageInfo* image_info, unsigned int width, unsigned int height) {
+    Image* image;
+    unsigned int y;
+    register unsigned int x;
+    register PixelPacket *q,t;
+    register unsigned char *p;
+
+    image=AllocateImage(image_info);
+    image->columns=width;
+    image->rows=height;  
+    t=image->matte_color;
+      t.red=MaxRGB;
+      t.green=0;   
+      t.blue=MaxRGB;
+      image->matte_color=t;
+
+    p=ptr;
+    for (y=0; y < image->rows; y++) {
+        q=SetImagePixels(image,0,y,image->columns,1);
+        if (q == (PixelPacket *) NULL) break;
+        for (x=0; x < image->columns; x++) { 
+            q->red=MaxRGB*(lvl_palette[*p][red])/255;
+            q->green=MaxRGB*(lvl_palette[*p][green])/255;
+            q->blue=MaxRGB*(lvl_palette[*p][blue])/255; 
+            p++;
+            q++;
+        }
+        if (!SyncImagePixels(image)) break;
+    }
+    return image;
+}
+
+
+int main(int argc, char *argv[]) {
+    FILE *lvl_file, *unknown_file, *append_file;
+    char dirname[16], buf[100];
+
+    /* Initial start pointer to the beginning of the file */
+    unsigned char *data;
+    /* Temporary variable to indicate the last offset to start searching from:
+     * Either after (1+) an invalid "T" or after the image of a valid "TRPS" */
+    unsigned char *last_ptr;
+    /* Either index position (start) or the last known position after an image */
+    unsigned char *save_ptr;
+    /* Iterates through all offsets at a "T" */
+    unsigned char *off_ptr;
+
+    /* temporary variables */
+    struct stat sb;
+    unsigned int i=0;
+    unsigned int width,height;
+
+    const char entry_id[]="TRPS";
+    char type[]="png";
+    int debug=0;
+    unsigned int data_size;
+    unsigned int num_entries;
+    unsigned int unknown=0;
+
+    unsigned int x_off=0;
+    Image* image_list=NULL;
+    ImageInfo *image_info=NULL;
+    MontageInfo montage_info;
+    ExceptionInfo exception;
+    Image *big_image, *tmp_img;
+    register PixelPacket colorkey;
+
+    /* -------------------------------------------------------------------- */
+
+    if (argc < 2) {
+        printf("Usage: %s input.lvl [destination]\n", argv[0]);
+        return 1;
+    }
+    
+    lvl_file = fopen(argv[1],"r");
+
+    if (lvl_file == NULL) {
+        perror("Error opening file");
+        return 1;
+    }
+
+    fread(buf,1,12,lvl_file);
+
+    if ((buf[0] != 'D') && (buf[1] != 'A') &&
+      (buf[2] != 'T') && (buf[3] != 'A')) {
+        printf("Invalid file\n");
+        fclose(lvl_file);
+        return 1;
+    }
+
+    /* get file size */
+    fstat(fileno(lvl_file), &sb);
+    data_size = sb.st_size;
+
+    /* Get directory name and create directory */
+    if (argc > 2) {
+        strncpy(dirname, argv[1], 16);
+    } else {
+        /* copy the filename */
+        if (strrchr(argv[1], '/')) strncpy(dirname, strrchr(argv[1], '/')+1, 16);
+        else strncpy(dirname, argv[1], 16);
+
+        /* truncate filename at . */
+        if (strrchr(dirname, '.')) {   
+            char *loc = strrchr(dirname, '.');
+            *loc = 0;
+        }
+    }
+    mkdir(dirname, 0777);
+    chdir(dirname);
+    printf("Directory: %s\n", dirname);
+
+    /* Create file for image informations */
+    snprintf(buf,16,"%s.txt",dirname);
+    append_file = fopen(buf,"w");
+    append_file = freopen(buf,"a",append_file);
+
+    /* ImageMagick stuff */
+    image_list=NewImageList(); 
+    image_info=CloneImageInfo((ImageInfo *) NULL);
+    image_info->colorspace = RGBColorspace;
+    colorkey.red=MaxRGB;
+    colorkey.green=0;
+    colorkey.blue=MaxRGB;
+    colorkey.opacity=0;
+
+    /* Map the entire file into process memory space */
+    data = mmap(NULL, data_size, PROT_READ, MAP_PRIVATE, fileno(lvl_file), 0);
+
+    /* Iterate through all image data offsets to get the number of entries and the
+     * size of the unknown chunk */
+    num_entries=0;
+    last_ptr=data;
+    save_ptr=data;
+    while (off_ptr=(unsigned char*)memchr(last_ptr,'T',(data_size-(last_ptr-data)))) {
+        unknown+=(off_ptr-last_ptr);
+        if (!strncmp((char*)off_ptr,entry_id,4)) {
+            num_entries++;
+            width=*((unsigned int *)(off_ptr+4));
+            height=*((unsigned int *)(off_ptr+8));
+            last_ptr=off_ptr+12+width*height;
+            save_ptr=last_ptr;
+        } else {
+            last_ptr=off_ptr+1;
+        }
+    }
+
+    unsigned short geometry[num_entries][4];
+
+    /* Iterate through all image data offsets */
+    i=0;
+    last_ptr=data;
+    save_ptr=data;
+    while (off_ptr=(unsigned char*)memchr(last_ptr,'T',(data_size-(last_ptr-data)))) {
+        unknown+=(off_ptr-last_ptr);
+        if (!strncmp((char*)off_ptr,entry_id,4)) {
+            i++;
+            /*
+             * Write unknown content (up to this image position (off_ptr)) to a file.
+             * If the file size would be 0, skip it.
+             */
+            if (debug && (off_ptr-save_ptr > 0)) {
+                snprintf(buf, 100, "%08d.bin", i);
+                unknown_file = fopen(buf, "wb");
+                fwrite(save_ptr,1,(off_ptr-save_ptr),unknown_file);
+                fclose(unknown_file);
+            }
+
+            /* --== Parse header ==-- */
+            width=*((unsigned int *)(off_ptr+4));
+            height=*((unsigned int *)(off_ptr+8));
+            geometry[i-1][img_x]=x_off;
+            geometry[i-1][img_y]=0;
+            geometry[i-1][img_w]=width;
+            geometry[i-1][img_h]=height;
+            x_off+=width;
+
+            /* update last_ptr, get the image and append it to the list */
+            tmp_img=write_magick(off_ptr+12,image_info,width,height);
+            snprintf(buf,100,"%08d.%s",i,type);
+            strcpy(tmp_img->filename,buf);
+            AppendImageToList(&image_list,tmp_img);
+
+            /* update pointers */
+            last_ptr=off_ptr+12+width*height;
+            save_ptr=last_ptr;
+        } else {
+            last_ptr=off_ptr+1;
+        }
+    }
+
+    /* Montage the image and save it */
+    GetMontageInfo(image_info,&montage_info);
+    GetExceptionInfo(&exception);
+    montage_info.tile="3000x1";
+    montage_info.geometry="+0+0";
+    montage_info.background_color=colorkey;
+    montage_info.matte_color=colorkey;
+    montage_info.gravity=NorthWestGravity;
+
+    big_image=MontageImages(image_list,&montage_info,&exception);
+    big_image->matte_color=colorkey;
+
+    snprintf(buf, 100, "%s.%s",dirname,type);
+    strcpy(big_image->filename,buf);
+    WriteImage(image_info,big_image);
+    DestroyImage(big_image);
+
+    fprintf(append_file,"%d\n",num_entries);
+    for (i=0; i<num_entries;i++) {
+        fprintf(append_file,"%d %d %d %d\n",geometry[i][0],geometry[i][1],geometry[i][2],geometry[i][3]);
+    }
+/*    DestroyMontageInfo(&montage_info); */
+    DestroyImageList(image_list);
+    DestroyImageInfo(image_info);
+    DestroyMagick();
+
+    printf("Contains %d extracted images, unknown content: %d bytes\n",num_entries,unknown);
+
+    munmap(data, data_size);
+    fclose(lvl_file);
+    fclose(append_file);
+
+    return 0;
+}




More information about the lostpenguins-commits mailing list