mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-22 08:51:13 +00:00
`merge' the pcx and tga code
This commit is contained in:
parent
077c0bb6ad
commit
661e9bb6fd
4 changed files with 587 additions and 0 deletions
55
include/pcx.h
Normal file
55
include/pcx.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
pcx.h
|
||||
|
||||
pcx image hangling
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __pcx_h
|
||||
#define __pcx_h
|
||||
|
||||
#include "quakeio.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
unsigned short xmin, ymin, xmax, ymax;
|
||||
unsigned short hres, vres;
|
||||
unsigned char palette[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
char filler[58];
|
||||
} pcx_t;
|
||||
|
||||
void WritePCXfile (char *filename, byte * data, int width, int height,
|
||||
int rowbytes, byte * palette, qboolean upload,
|
||||
qboolean flip);
|
||||
struct tex_s *LoadPCX (QFile *f, int convert); // tex is from Hunk_TempAlloc
|
||||
|
||||
#endif // __pcx_h
|
74
include/tga.h
Normal file
74
include/tga.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
tga.h
|
||||
|
||||
targa image hangling
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __tga_h
|
||||
#define __tga_h
|
||||
|
||||
#include "gcc_attr.h"
|
||||
#include "qtypes.h"
|
||||
|
||||
#ifndef __GNUC__
|
||||
# if defined (__BORLANDC__) || defined (_MSC_VER)
|
||||
# if (defined(__BORLANDC__) && (__BORLANDC__ < 0x550))
|
||||
# pragma option -a1
|
||||
# else
|
||||
# pragma pack(push, tgainclude)
|
||||
# pragma pack(1)
|
||||
# endif
|
||||
# else
|
||||
# error do some data packing magic here (#pragma pack?)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct _TargaHeader {
|
||||
unsigned char id_length __attribute__((packed));
|
||||
unsigned char colormap_type __attribute__((packed));
|
||||
unsigned char image_type __attribute__((packed));
|
||||
unsigned short colormap_index __attribute__((packed));
|
||||
unsigned short colormap_length __attribute__((packed));
|
||||
unsigned char colormap_size __attribute__((packed));
|
||||
unsigned short x_origin __attribute__((packed));
|
||||
unsigned short y_origin __attribute__((packed));
|
||||
unsigned short width __attribute__((packed));
|
||||
unsigned short height __attribute__((packed));
|
||||
unsigned char pixel_size __attribute__((packed));
|
||||
unsigned char attributes __attribute__((packed));
|
||||
} TargaHeader;
|
||||
|
||||
#if defined (__BORLANDC__) || defined (_MSC_VER)
|
||||
# if (defined(__BORLANDC__) && (__BORLANDC__ < 0x550))
|
||||
# pragma option -a4
|
||||
# else
|
||||
# pragma pack(pop, tgainclude)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
byte *LoadTGA (QFile *fin);
|
||||
void WriteTGAfile (const char *tganame, byte *data, int width, int height);
|
||||
|
||||
#endif // __tga_h
|
216
libs/models/texture/pcx.c
Normal file
216
libs/models/texture/pcx.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
pcx.c
|
||||
|
||||
pcx image handling
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "cl_parse.h"
|
||||
#include "console.h"
|
||||
#include "host.h"
|
||||
#include "pcx.h"
|
||||
#include "qendian.h"
|
||||
#include "qtypes.h"
|
||||
#include "quakefs.h"
|
||||
#include "texture.h"
|
||||
#include "zone.h"
|
||||
|
||||
/*
|
||||
LoadPCX
|
||||
*/
|
||||
tex_t *
|
||||
LoadPCX (QFile *f, int convert)
|
||||
{
|
||||
pcx_t *pcx;
|
||||
int pcx_mark;
|
||||
byte *palette;
|
||||
byte *pix;
|
||||
byte *dataByte;
|
||||
int x, y;
|
||||
int runLength = 1;
|
||||
int count;
|
||||
tex_t *tex;
|
||||
|
||||
//
|
||||
// parse the PCX file
|
||||
//
|
||||
pcx_mark = Hunk_LowMark ();
|
||||
pcx = Hunk_AllocName (com_filesize, "PCX");
|
||||
Qread (f, pcx, com_filesize);
|
||||
|
||||
pcx->xmax = LittleShort (pcx->xmax);
|
||||
pcx->xmin = LittleShort (pcx->xmin);
|
||||
pcx->ymax = LittleShort (pcx->ymax);
|
||||
pcx->ymin = LittleShort (pcx->ymin);
|
||||
pcx->hres = LittleShort (pcx->hres);
|
||||
pcx->vres = LittleShort (pcx->vres);
|
||||
pcx->bytes_per_line = LittleShort (pcx->bytes_per_line);
|
||||
pcx->palette_type = LittleShort (pcx->palette_type);
|
||||
|
||||
if (pcx->manufacturer != 0x0a
|
||||
|| pcx->version != 5
|
||||
|| pcx->encoding != 1
|
||||
|| pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 256) {
|
||||
Con_Printf ("Bad pcx file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
palette = ((byte*)pcx) + com_filesize - 768;
|
||||
dataByte = (byte*)&pcx[1];
|
||||
|
||||
count = (pcx->xmax + 1) * (pcx->ymax + 1);
|
||||
if (convert)
|
||||
count *= 4;
|
||||
tex = Hunk_TempAlloc (sizeof (tex_t) + count);
|
||||
tex->width = pcx->xmax + 1;
|
||||
tex->height = pcx->ymax + 1;
|
||||
if (convert) {
|
||||
tex->palette = 0;
|
||||
} else {
|
||||
tex->palette = host_basepal;
|
||||
}
|
||||
pix = tex->data;
|
||||
|
||||
for (y = 0; y < tex->height; y++) {
|
||||
for (x = 0; x < tex->width;) {
|
||||
runLength = 1;
|
||||
if (dataByte >= palette)
|
||||
break;
|
||||
|
||||
if ((*dataByte & 0xC0) == 0xC0) {
|
||||
runLength = *dataByte++ & 0x3F;
|
||||
if (dataByte >= palette)
|
||||
break;
|
||||
}
|
||||
|
||||
if (convert) {
|
||||
while (count && runLength > 0) {
|
||||
pix[0] = palette[*dataByte * 3];
|
||||
pix[1] = palette[*dataByte * 3 + 1];
|
||||
pix[2] = palette[*dataByte * 3 + 2];
|
||||
pix[3] = 255;
|
||||
pix += 4;
|
||||
count -= 4;
|
||||
runLength--;
|
||||
x++;
|
||||
}
|
||||
} else {
|
||||
while (count && runLength > 0) {
|
||||
*pix++ = *dataByte;
|
||||
count--;
|
||||
runLength--;
|
||||
x++;
|
||||
}
|
||||
}
|
||||
if (runLength)
|
||||
break;
|
||||
dataByte++;
|
||||
}
|
||||
if (runLength)
|
||||
break;
|
||||
}
|
||||
Hunk_FreeToLowMark (pcx_mark);
|
||||
if (count || runLength) {
|
||||
Con_Printf ("PCX was malformed. You should delete it.\n");
|
||||
return 0;
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
||||
/*
|
||||
WritePCXfile
|
||||
*/
|
||||
void
|
||||
WritePCXfile (char *filename, byte * data, int width, int height,
|
||||
int rowbytes, byte * palette, qboolean upload, qboolean flip)
|
||||
{
|
||||
int i, j, length;
|
||||
pcx_t *pcx;
|
||||
byte *pack;
|
||||
|
||||
if (!(pcx = Hunk_TempAlloc (width * height * 2 + 1000))) {
|
||||
Con_Printf ("WritePCXfile: not enough memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pcx->manufacturer = 0x0a; // PCX id
|
||||
pcx->version = 5; // 256 color
|
||||
pcx->encoding = 1; // uncompressed
|
||||
pcx->bits_per_pixel = 8; // 256 color
|
||||
pcx->xmin = 0;
|
||||
pcx->ymin = 0;
|
||||
pcx->xmax = LittleShort ((short) (width - 1));
|
||||
pcx->ymax = LittleShort ((short) (height - 1));
|
||||
pcx->hres = LittleShort ((short) width);
|
||||
pcx->vres = LittleShort ((short) height);
|
||||
memset (pcx->palette, 0, sizeof (pcx->palette));
|
||||
pcx->color_planes = 1; // chunky image
|
||||
pcx->bytes_per_line = LittleShort ((short) width);
|
||||
pcx->palette_type = LittleShort (2); // not a grey scale
|
||||
memset (pcx->filler, 0, sizeof (pcx->filler));
|
||||
|
||||
// pack the image
|
||||
pack = (byte*)&pcx[1];
|
||||
|
||||
if (flip)
|
||||
data += rowbytes * (height - 1);
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
for (j = 0; j < width; j++) {
|
||||
if ((*data & 0xc0) != 0xc0)
|
||||
*pack++ = *data++;
|
||||
else {
|
||||
*pack++ = 0xc1;
|
||||
*pack++ = *data++;
|
||||
}
|
||||
}
|
||||
|
||||
data += rowbytes - width;
|
||||
if (flip)
|
||||
data -= rowbytes * 2;
|
||||
}
|
||||
|
||||
// write the palette
|
||||
*pack++ = 0x0c; // palette ID byte
|
||||
for (i = 0; i < 768; i++)
|
||||
*pack++ = *palette++;
|
||||
|
||||
// write output file
|
||||
length = pack - (byte *) pcx;
|
||||
|
||||
if (upload)
|
||||
CL_StartUpload ((void *) pcx, length);
|
||||
else
|
||||
COM_WriteFile (filename, pcx, length);
|
||||
}
|
242
libs/models/texture/tga.c
Normal file
242
libs/models/texture/tga.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
tga.c
|
||||
|
||||
targa image handling
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "qendian.h"
|
||||
#include "quakefs.h"
|
||||
#include "sys.h"
|
||||
#include "tga.h"
|
||||
|
||||
static int
|
||||
fgetLittleShort (QFile *f)
|
||||
{
|
||||
byte b1, b2;
|
||||
|
||||
b1 = Qgetc (f);
|
||||
b2 = Qgetc (f);
|
||||
|
||||
return (short) (b1 + b2 * 256);
|
||||
}
|
||||
|
||||
/*
|
||||
static int
|
||||
fgetLittleLong (QFile *f)
|
||||
{
|
||||
byte b1, b2, b3, b4;
|
||||
|
||||
b1 = Qgetc(f);
|
||||
b2 = Qgetc(f);
|
||||
b3 = Qgetc(f);
|
||||
b4 = Qgetc(f);
|
||||
|
||||
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
LoadTGA
|
||||
*/
|
||||
byte *
|
||||
LoadTGA (QFile *fin)
|
||||
{
|
||||
int columns, rows, numPixels;
|
||||
byte *pixbuf;
|
||||
int row, column;
|
||||
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
|
||||
|
||||
TargaHeader targa_header;
|
||||
byte *targa_rgba;
|
||||
|
||||
targa_header.id_length = Qgetc (fin);
|
||||
targa_header.colormap_type = Qgetc (fin);
|
||||
targa_header.image_type = Qgetc (fin);
|
||||
|
||||
targa_header.colormap_index = fgetLittleShort (fin);
|
||||
targa_header.colormap_length = fgetLittleShort (fin);
|
||||
targa_header.colormap_size = Qgetc (fin);
|
||||
targa_header.x_origin = fgetLittleShort (fin);
|
||||
targa_header.y_origin = fgetLittleShort (fin);
|
||||
targa_header.width = fgetLittleShort (fin);
|
||||
targa_header.height = fgetLittleShort (fin);
|
||||
targa_header.pixel_size = Qgetc (fin);
|
||||
targa_header.attributes = Qgetc (fin);
|
||||
|
||||
if (targa_header.image_type != 2 && targa_header.image_type != 10)
|
||||
Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
|
||||
|
||||
if (targa_header.colormap_type != 0
|
||||
|| (targa_header.pixel_size != 32 && targa_header.pixel_size != 24))
|
||||
Sys_Error
|
||||
("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
|
||||
|
||||
columns = targa_header.width;
|
||||
rows = targa_header.height;
|
||||
numPixels = columns * rows;
|
||||
|
||||
targa_rgba = malloc (numPixels * 4);
|
||||
|
||||
if (targa_header.id_length != 0)
|
||||
Qseek (fin, targa_header.id_length, SEEK_CUR); // skip TARGA image
|
||||
// comment
|
||||
|
||||
if (targa_header.image_type == 2) { // Uncompressed, RGB images
|
||||
for (row = rows - 1; row >= 0; row--) {
|
||||
pixbuf = targa_rgba + row * columns * 4;
|
||||
for (column = 0; column < columns; column++) {
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
alphabyte = Qgetc (fin);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (targa_header.image_type == 10) { // Runlength encoded RGB
|
||||
// images
|
||||
unsigned char packetHeader, packetSize, j;
|
||||
|
||||
for (row = rows - 1; row >= 0; row--) {
|
||||
pixbuf = targa_rgba + row * columns * 4;
|
||||
for (column = 0; column < columns;) {
|
||||
packetHeader = Qgetc (fin);
|
||||
packetSize = 1 + (packetHeader & 0x7f);
|
||||
if (packetHeader & 0x80) { // run-length packet
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
alphabyte = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
alphabyte = Qgetc (fin);
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = 0; j < packetSize; j++) {
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
column++;
|
||||
if (column == columns) { // run spans across rows
|
||||
column = 0;
|
||||
if (row > 0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
pixbuf = targa_rgba + row * columns * 4;
|
||||
}
|
||||
}
|
||||
} else { // non run-length packet
|
||||
for (j = 0; j < packetSize; j++) {
|
||||
switch (targa_header.pixel_size) {
|
||||
case 24:
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Qgetc (fin);
|
||||
green = Qgetc (fin);
|
||||
red = Qgetc (fin);
|
||||
alphabyte = Qgetc (fin);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
}
|
||||
column++;
|
||||
if (column == columns) { // pixel packet run spans
|
||||
// across rows
|
||||
column = 0;
|
||||
if (row > 0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
pixbuf = targa_rgba + row * columns * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
breakOut:;
|
||||
}
|
||||
}
|
||||
|
||||
Qclose (fin);
|
||||
return targa_rgba;
|
||||
}
|
||||
|
||||
void
|
||||
WriteTGAfile (const char *tganame, byte *data, int width, int height)
|
||||
{
|
||||
TargaHeader header;
|
||||
|
||||
memset (&header, 0, sizeof (header));
|
||||
header.image_type = 2; // uncompressed type
|
||||
header.width = LittleShort (width);
|
||||
header.height = LittleShort (height);
|
||||
header.pixel_size = 24;
|
||||
|
||||
COM_WriteBuffers (tganame, 2, &header, sizeof (header), data,
|
||||
width * height * 3);
|
||||
}
|
Loading…
Reference in a new issue