added buffering to minimise GtkTextBuffer insert calls
[xonotic/netradiant.git] / plugins / imagehl / hlw.cpp
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 // by Hydra - hydra@hydras-world.com
23 //
24 // HLW = Half-Life-WAD, I don't know if the actual in data in the WAD files
25 // has it's own name, so I'm just calling the individal textures .HLW files :)
26 //
27 // Thanks to the guys that made Wally for releasing an example WAD loader.
28 // without it this would not have been possible.
29
30 #include "hlw.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35
36 typedef unsigned char byte;
37
38 #include "ifilesystem.h"
39
40 #include "imagelib.h"
41
42
43 /*
44 ============================================================================
45
46 HLW IMAGE
47
48   HalfLife WAD files contain files that look like this:
49
50         Mip section
51                 First mip
52                         Mip header
53                         First mip (width * height)
54                         Second mip (width * height / 4)
55                         Third mip (width * height / 16)
56                         Fourth mip (width * height / 64)
57                         Palette size (WORD)
58                         Palette (Palette size * 3)
59                         Padding (WORD)
60
61 ============================================================================
62 */
63
64 #define GET_MIP_DATA_SIZE(WIDTH, HEIGHT) (sizeof(WAD3_MIP) + (WIDTH * HEIGHT) + (WIDTH * HEIGHT / 4) + (WIDTH * HEIGHT / 16) + (WIDTH * HEIGHT / 64))
65
66 typedef struct
67 {
68         char            name[16];
69         unsigned int            width, height;
70         unsigned int            offsets[4];             // four mip maps stored
71 } WAD3_MIP, *LPWAD3_MIP;
72
73 /*
74 =========================================================
75
76 HLW LOADING
77
78   Hydra: this code isn't bullet proof and probably won't
79   like corrupt WAD files, but it works for now.
80
81   TODO: make it more robust.
82 =========================================================
83 */
84
85 /*
86 =============
87 LoadHLW
88 =============
89 */
90
91 Image* LoadHLWBuff(byte* buffer)
92 {
93   byte *buf_p;
94   unsigned long mipdatasize;
95   int columns, rows, numPixels;
96   byte *pixbuf;
97   int row, column;
98   byte *palette;
99         LPWAD3_MIP              lpMip;
100         unsigned char red, green, blue, alphabyte;
101
102   lpMip = (LPWAD3_MIP)buffer; //!\todo Make endian-safe.
103
104   mipdatasize = GET_MIP_DATA_SIZE(lpMip->width,lpMip->height);
105
106   palette = buffer+mipdatasize+2;
107
108   buf_p = buffer+lpMip->offsets[0];
109
110   columns = lpMip->width;
111   rows = lpMip->height;
112   numPixels = columns * rows;
113
114   RGBAImage* image = new RGBAImage(columns, rows);
115
116   for (row = 0; row < rows; row++)
117   {
118     pixbuf = image->getRGBAPixels() + row * columns * 4;
119
120     for (column = 0; column < columns; column++)
121     {
122       int palIndex;
123
124             palIndex = *buf_p++;
125
126       red = *(palette+(palIndex*3));
127       green = *(palette+(palIndex*3)+1);
128       blue = *(palette+(palIndex*3)+2);
129
130       // HalfLife engine makes pixels that are BLUE transparent.
131       // So show them that way in the editor.
132       if (blue == 0xff && red == 0x00 && green == 0x00)
133       {
134         alphabyte = 0x00;
135         blue = 0x00; // don't set the resulting pixel to blue
136       } 
137       else
138       {
139         alphabyte = 0xff;        
140       }
141
142             *pixbuf++ = red;
143             *pixbuf++ = green;
144             *pixbuf++ = blue;
145
146             *pixbuf++ = alphabyte;
147     }
148   }
149
150   return image;
151 }
152
153 Image* LoadHLW(ArchiveFile& file)
154 {
155   ScopedArchiveBuffer buffer(file);
156   return LoadHLWBuff(buffer.buffer );
157 }