home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
rexx
/
library2
/
gbmrexx
/
gbm
/
gbmtga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-27
|
14KB
|
560 lines
/*
GBMTGA.C Truevision Targa/Vista support
Reads any uncompressed type as 8 bit or 24 bit.
Writes out only as 8 bit or 24 bit.
Output options: 16,24,32, ydown,yup (default: 24 yup)
*/
/*...sincludes:0:*/
#include <stdio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#ifdef AIX
#include <unistd.h>
#else
#include <io.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "standard.h"
#include "gbm.h"
/*...vgbm\46\h:0:*/
/*...e*/
/*...suseful:0:*/
#define low_byte(w) ((byte) ((w)&0x00ff) )
#define high_byte(w) ((byte) (((w)&0xff00)>>8))
#define make_word(a,b) (((word)a) + (((word)b) << 8))
/*...e*/
/*...ssame:0:*/
static BOOLEAN same(char *s1, char *s2, int n)
{
for ( ; n--; s1++, s2++ )
if ( tolower(*s1) != tolower(*s2) )
return ( FALSE );
return ( TRUE );
}
/*...e*/
/*...sfind_word:0:*/
static char *find_word(char *str, char *substr)
{
char buf [100+1], *s;
int len = strlen(substr);
for ( s = strtok(strcpy(buf, str), " \t,");
s != NULL;
s = strtok(NULL, " \t,") )
if ( same(s, substr, len) && s [len] == '\0' )
return ( str + (s - buf) );
return ( NULL );
}
/*...e*/
static GBMFT tga_gbmft =
{
"Targa",
"Truevision Targa/Vista bitmap",
"TGA VST AFI",
GBM_FT_R8|GBM_FT_R24|
GBM_FT_W8|GBM_FT_W24,
};
#define GBM_ERR_TGA_BAD_BPP ((GBM_ERR) 400)
#define GBM_ERR_TGA_BAD_TYPE ((GBM_ERR) 401)
#define GBM_ERR_TGA_BAD_PAL ((GBM_ERR) 402)
/*...starga file header definition:0:*/
/*
A Targa file is a header, followed by an identification string, followed by
a color map, followed by the data for the image. Both the identification
string and the color-map can be of zero length.
*/
#define TGA_NO_IMAGE 0 /* No image data included in file */
#define TGA_UNCOMP_CM 1 /* Uncompressed, Color-Mapped (VDA/D */
/* and Targa M-8 images) */
#define TGA_UNCOMP_RGB 2 /* Uncompressed, RGB images (eg: ICB */
/* Targa 16, 24 and 32) */
#define TGA_UNCOMP_BW 3 /* Uncompressed, B/W images (eg: */
/* Targa 8 and Targa M-8 images) */
#define TGA_RL_CM 9 /* Run-length, Color-Mapped (VDA/D */
/* and Targa M-8 images) */
#define TGA_RL_RGB 10 /* Run-length, RGB images (eg: ICB */
/* Targa 16, 24 and 32) */
#define TGA_RL_BW 11 /* Run-length, B/W images (eg: Targa */
/* 8 and Targa M-8) */
#define TGA_COMP_CM 32 /* Compressed Color-Mapped (VDA/D) */
/* data using Huffman, Delta, and */
/* run length encoding */
#define TGA_COMP_CM_4 33 /* Compressed Color-Mapped (VDA/D) */
/* data using Huffman, Delta, and */
/* run length encoding in 4 passes */
#define IDB_ATTRIBUTES 0x0f /* How many attrib bits per pixel */
/* ie: 1 for T16, 8 for T32 */
#define IDB_ORIGIN 0x20 /* Origin in top left corner bit */
/* else its in bottom left corner */
#define IDB_INTERLEAVE 0xc0 /* Interleave bits as defined below */
#define IDB_NON_INT 0x00 /* Non-Interlaced */
#define IDB_2_WAY 0x40 /* 2 way (even/odd) interleaving */
#define IDB_4_WAY 0x80 /* 4 way interleaving (eg: AT&T PC) */
typedef struct
{
byte n_chars_in_id; /* Length of identification text */
byte color_map_present; /* 0 means no, 1 yes */
byte image_type; /* Type of image file, one of TGA_ */
byte color_map_start_low; /* These 5 bytes are only valid if */
byte color_map_start_high; /* color_map_present is 1. They */
byte color_map_length_low; /* Specify the size of the color map */
byte color_map_length_high; /* and where it starts from */
byte color_map_entry_bits; /* Bits per color map entry */
/* Typically 15, 16, 24 or 32 */
byte x_origin_low;
byte x_origin_high;
byte y_origin_low;
byte y_origin_high;
byte width_low;
byte width_high;
byte height_low;
byte height_high;
byte bpp; /* Typically 16, 24 or 32 */
byte image_descriptor; /* Split into IDB_ bits */
} TGA_HEADER;
#define SIZEOF_TGA_HEADER 18
/*...e*/
/*...sconverters:0:*/
/*...st24_t32:0:*/
static void t24_t32(byte *dest, byte *src, int n)
{
while ( n-- )
{
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
dest++;
}
}
/*...e*/
/*...st32_t24:0:*/
static void t32_t24(byte *dest, byte *src, int n)
{
while ( n-- )
{
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
src++;
}
}
/*...e*/
/*...st24_t16:0:*/
static void t24_t16(byte *dest, byte *src, int n)
{
while ( n-- )
{
word b = (word) (*src++ & 0xf8);
word g = (word) (*src++ & 0xf8);
word r = (word) (*src++ & 0xf8);
word w;
w = ((r << 7) | (g << 2) | (b >> 3));
*dest++ = (byte) w;
*dest++ = (byte) (w >> 8);
}
}
/*...e*/
/*...st16_t24:0:*/
static void t16_t24(byte *dest, byte *src, int n)
{
while ( n-- )
{
word l = *src++;
word h = *src++;
word w = l + (h << 8);
*dest++ = (byte) ((w & 0x001f) << 3);
*dest++ = (byte) ((w & 0x03e0) >> 2);
*dest++ = (byte) ((w & 0x7c00) >> 7);
}
}
/*...e*/
/*...e*/
/*...stga_qft:0:*/
GBM_ERR tga_qft(GBMFT *gbmft)
{
*gbmft = tga_gbmft;
return ( GBM_ERR_OK );
}
/*...e*/
/*...stga_rhdr:0:*/
GBM_ERR tga_rhdr(char *fn, int fd, GBM *gbm, char *opt)
{
TGA_HEADER tga_header;
int w, h, bpp;
fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
lseek(fd, 0L, SEEK_SET);
read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
bpp = tga_header.bpp;
if ( tga_header.image_type != TGA_UNCOMP_CM &&
tga_header.image_type != TGA_UNCOMP_RGB )
return ( GBM_ERR_TGA_BAD_TYPE );
if ( !( (bpp == 8 && tga_header.image_type == TGA_UNCOMP_CM ) ||
(bpp == 16 && tga_header.image_type == TGA_UNCOMP_RGB) ||
(bpp == 24 && tga_header.image_type == TGA_UNCOMP_RGB) ||
(bpp == 32 && tga_header.image_type == TGA_UNCOMP_RGB) ) )
return ( GBM_ERR_TGA_BAD_BPP );
if ( bpp == 8 && tga_header.color_map_entry_bits != 24 )
return ( GBM_ERR_TGA_BAD_PAL );
w = make_word(tga_header.width_low , tga_header.width_high );
h = make_word(tga_header.height_low, tga_header.height_high);
if ( w <= 0 || h <= 0 )
return ( GBM_ERR_BAD_SIZE );
gbm -> w = w;
gbm -> h = h;
gbm -> bpp = ( bpp == 8 ) ? 8 : 24;
return ( GBM_ERR_OK );
}
/*...e*/
/*...stga_rpal:0:*/
GBM_ERR tga_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
{
if ( gbm -> bpp == 8 )
{
TGA_HEADER tga_header;
int color_map_start, color_map_length, i;
lseek(fd, 0L, SEEK_SET);
read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
lseek(fd, (long) tga_header.n_chars_in_id, SEEK_CUR); /* Skip ID string */
color_map_start = make_word(tga_header.color_map_start_low, tga_header.color_map_start_high);
color_map_length = make_word(tga_header.color_map_length_low, tga_header.color_map_length_high);
memset(gbmrgb, 0, 0x100 * sizeof(GBMRGB));
for ( i = color_map_start; i < color_map_start + color_map_length; i++ )
{
byte b [3];
read(fd, (char *) b, 3);
gbmrgb [i].b = b [0];
gbmrgb [i].g = b [1];
gbmrgb [i].r = b [2];
}
}
return ( GBM_ERR_OK );
}
/*...e*/
/*...stga_rdata:0:*/
GBM_ERR tga_rdata(int fd, GBM *gbm, byte *data)
{
TGA_HEADER tga_header;
BOOLEAN top_left_origin;
byte *linebuf, *p;
int i, stride;
lseek(fd, 0L, SEEK_SET);
read(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
lseek(fd, (long) tga_header.n_chars_in_id, SEEK_CUR); /* Skip ID string */
top_left_origin = ((tga_header.image_descriptor & IDB_ORIGIN) != 0);
if ( tga_header.color_map_present )
{
int color_map_length;
int bpp_pal = tga_header.color_map_entry_bits;
/* Valid values are 32, 24, 16 and sometimes 15 */
if ( bpp_pal == 15 ) bpp_pal = 16;
color_map_length = make_word(tga_header.color_map_length_low, tga_header.color_map_length_high);
lseek(fd, (long) ((color_map_length * bpp_pal) / 8L), SEEK_CUR);
}
switch ( tga_header.bpp )
{
/*...s8:16:*/
case 8:
stride = ((gbm -> w + 3) & ~3);
p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
for ( i = 0; i < gbm -> h; i++ )
{
read(fd, p, gbm -> w);
if ( top_left_origin )
p -= stride;
else
p += stride;
}
break;
/*...e*/
/*...s16:16:*/
case 16:
if ( (linebuf = malloc(gbm -> w * 2)) == NULL )
return ( GBM_ERR_MEM );
stride = ((gbm -> w * 3 + 3) & ~3);
p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
for ( i = 0; i < gbm -> h; i++ )
{
read(fd, linebuf, gbm -> w * 2);
t16_t24(p, linebuf, gbm -> w);
if ( top_left_origin )
p -= stride;
else
p += stride;
}
free(linebuf);
break;
/*...e*/
/*...s24:16:*/
case 24:
stride = ((gbm -> w * 3 + 3) & ~3);
p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
for ( i = 0; i < gbm -> h; i++ )
{
read(fd, p, gbm -> w * 3);
if ( top_left_origin )
p -= stride;
else
p += stride;
}
break;
/*...e*/
/*...s32:16:*/
case 32:
if ( (linebuf = malloc(gbm -> w * 4)) == NULL )
return ( GBM_ERR_MEM );
stride = ((gbm -> w * 3 + 3) & ~3);
p = ( top_left_origin ) ? data + ((gbm -> h - 1) * stride) : data;
for ( i = 0; i < gbm -> h; i++ )
{
read(fd, linebuf, gbm -> w * 4);
t32_t24(p, linebuf, gbm -> w);
if ( top_left_origin )
p -= stride;
else
p += stride;
}
free(linebuf);
break;
/*...e*/
}
return ( GBM_ERR_OK );
}
/*...e*/
/*...stga_w:0:*/
#define SW3(a,b,c) ((a)*4+(b)*2+(c))
GBM_ERR tga_w(char *fn, int fd, GBM *gbm, GBMRGB *gbmrgb, byte *data, char *opt)
{
TGA_HEADER tga_header;
int i, stride;
byte *p;
int obpp;
BOOLEAN o16 = ( find_word(opt, "16" ) != NULL );
BOOLEAN o24 = ( find_word(opt, "24" ) != NULL );
BOOLEAN o32 = ( find_word(opt, "32" ) != NULL );
BOOLEAN yup = ( find_word(opt, "yup" ) != NULL );
BOOLEAN ydown = ( find_word(opt, "ydown") != NULL );
fn=fn; /* Suppress 'unref arg' compiler warning */
if ( gbm -> bpp == 24 )
switch ( SW3(o16,o24,o32) )
{
case SW3(1,0,0): obpp = 16; break;
case SW3(0,0,0):
case SW3(0,1,0): obpp = 24; break;
case SW3(0,0,1): obpp = 32; break;
default: return ( GBM_ERR_BAD_OPTION );
}
else
{
if ( o16 || o24 || o32 )
return ( GBM_ERR_BAD_OPTION );
obpp = 8;
}
if ( yup && ydown )
return ( GBM_ERR_BAD_OPTION );
tga_header.n_chars_in_id = 0;
tga_header.image_type = ( obpp == 8 ) ? TGA_UNCOMP_CM : TGA_UNCOMP_RGB;
tga_header.color_map_present = (byte) ( gbm -> bpp == 8 );
tga_header.x_origin_low = low_byte(0);
tga_header.x_origin_high = high_byte(0);
tga_header.y_origin_low = low_byte(0);
tga_header.y_origin_high = high_byte(0);
tga_header.color_map_start_low = low_byte(0);
tga_header.color_map_start_high = high_byte(0);
tga_header.color_map_length_low = low_byte(0x100);
tga_header.color_map_length_high = high_byte(0x100);
tga_header.color_map_entry_bits = 24;
tga_header.width_low = low_byte(gbm -> w);
tga_header.width_high = high_byte(gbm -> w);
tga_header.height_low = low_byte(gbm -> h);
tga_header.height_high = high_byte(gbm -> h);
tga_header.bpp = (byte) obpp;
tga_header.image_descriptor = IDB_NON_INT;
if ( ydown )
tga_header.image_descriptor |= IDB_ORIGIN;
write(fd, (char *) &tga_header, SIZEOF_TGA_HEADER);
switch ( obpp )
{
/*...s8:16:*/
case 8:
for ( i = 0; i < 0x100; i++ )
{
byte b [3];
b [0] = gbmrgb [i].b;
b [1] = gbmrgb [i].g;
b [2] = gbmrgb [i].r;
write(fd, b, 3);
}
stride = ((gbm -> w + 3) & ~3);
p = data;
if ( ydown )
{
data += ((gbm -> h - 1) * stride);
stride = -stride;
}
for ( i = 0; i < gbm -> h; i++ )
{
write(fd, p, gbm -> w);
p += stride;
}
break;
/*...e*/
/*...s16:16:*/
case 16:
{
byte *linebuf;
if ( (linebuf = malloc(gbm -> w * 2)) == NULL )
return ( GBM_ERR_MEM );
stride = ((gbm -> w * 3 + 3) & ~3);
p = data;
if ( ydown )
{
data += ((gbm -> h - 1) * stride);
stride = -stride;
}
for ( i = 0; i < gbm -> h; i++ )
{
t24_t16(linebuf, p, gbm -> w);
write(fd, linebuf, gbm -> w * 2);
p += stride;
}
free(linebuf);
}
break;
/*...e*/
/*...s24:16:*/
case 24:
stride = ((gbm -> w * 3 + 3) & ~3);
p = data;
if ( ydown )
{
data += ((gbm -> h - 1) * stride);
stride = -stride;
}
for ( i = 0; i < gbm -> h; i++ )
{
write(fd, p, gbm -> w * 3);
p += stride;
}
break;
/*...e*/
/*...s32:16:*/
case 32:
{
byte *linebuf;
if ( (linebuf = malloc(gbm -> w * 4)) == NULL )
return ( GBM_ERR_MEM );
stride = ((gbm -> w * 3 + 3) & ~3);
p = data;
if ( ydown )
{
data += ((gbm -> h - 1) * stride);
stride = -stride;
}
for ( i = 0; i < gbm -> h; i++ )
{
t24_t32(linebuf, p, gbm -> w);
write(fd, linebuf, gbm -> w * 4);
p += stride;
}
free(linebuf);
}
break;
/*...e*/
}
return ( GBM_ERR_OK );
}
/*...e*/
/*...stga_err:0:*/
char *tga_err(GBM_ERR rc)
{
switch ( (int) rc )
{
case GBM_ERR_TGA_BAD_BPP:
return ( "bits per pixel not 8, 16, 24 or 32" );
case GBM_ERR_TGA_BAD_TYPE:
return ( "unsupported compression type for bits per pixel" );
case GBM_ERR_TGA_BAD_PAL:
return ( "color map entry size not 24 bits per pixel" );
}
return ( NULL );
}
/*...e*/