-#include "image.h"
-#include "io.h"
+#include "imageri.h"
#include "log.h"
#include "iolayer.h"
typedef struct {
- char idlength;
+ unsigned char idlength;
char colourmaptype;
char datatypecode;
short int colourmaporigin;
/*
=item bpp_to_channels(bpp)
-Convert bits per pixel into channels in the image
+Convert bits per pixel and the number of attribute bits into channels
+in the image
bpp - bits per pixel
+ attr_bit_count - number of attribute bits
=cut
*/
static
int
-bpp_to_channels(unsigned int bpp) {
+bpp_to_channels(unsigned int bpp, int attr_bit_count) {
switch (bpp) {
case 8:
return 1;
+ case 16:
+ if (attr_bit_count == 1)
+ return 4;
case 15:
return 3;
- case 16:
- return 4;
+ case 32:
+ if (attr_bit_count == 8)
+ return 4;
case 24:
return 3;
- case 32:
- return 4;
}
return 0;
}
val->rgba.r = (buf[1] & 0x7c) << 1;
val->rgba.g = ((buf[1] & 0x03) << 6) | ((buf[0] & 0xe0) >> 2);
val->rgba.b = (buf[0] & 0x1f) << 3;
- val->rgba.a = (buf[1] & 0x80) ? 255 : 0;
+ val->rgba.a = (buf[1] & 0x80) ? 0 : 255;
val->rgba.r |= val->rgba.r >> 5;
val->rgba.g |= val->rgba.g >> 5;
val->rgba.b |= val->rgba.b >> 5;
case 8:
buf[0] = val->gray.gray_color;
break;
+ case 16:
+ buf[0] = (val->rgba.b >> 3);
+ buf[0] |= (val->rgba.g & 0x38) << 2;
+ buf[1] = (val->rgba.r & 0xf8)>> 1;
+ buf[1] |= (val->rgba.g >> 6);
+ buf[1] |= val->rgba.a > 0x7f ? 0 : 0x80;
+ break;
case 15:
buf[0] = (val->rgba.b >> 3);
buf[0] |= (val->rgba.g & 0x38) << 2;
buf[1] = (val->rgba.r & 0xf8)>> 1;
buf[1] |= (val->rgba.g >> 6);
- case 16:
- buf[1] |= val->rgba.a & 0x80;
break;
case 24:
buf[0] = val->rgb.b;
}
+/* this function should never produce diagnostics to stdout, maybe to the logfile */
+int
+tga_header_verify(unsigned char headbuf[18]) {
+ tga_header header;
+ tga_header_unpack(&header, headbuf);
+ switch (header.datatypecode) {
+ default:
+ /*printf("bad typecode!\n");*/
+ return 0;
+ case 1: /* Uncompressed, color-mapped images */
+ case 3: /* Uncompressed, grayscale images */
+ case 9: /* Compressed, color-mapped images */
+ case 11: /* Compressed, grayscale images */
+ if (header.bitsperpixel != 8)
+ return 0;
+ break;
+ case 0:
+ case 2: /* Uncompressed, rgb images */
+ case 10: /* Compressed, rgb images */
+ if (header.bitsperpixel != 15 && header.bitsperpixel != 16
+ && header.bitsperpixel != 24 && header.bitsperpixel != 32)
+ return 0;
+ break;
+ }
+
+ switch (header.colourmaptype) {
+ default:
+ /*printf("bad colourmaptype!\n");*/
+ return 0;
+ case 1:
+ if (header.datatypecode != 1 && header.datatypecode != 9)
+ return 0; /* only get a color map on a color mapped image */
+ case 0:
+ break;
+ }
+
+ switch (header.colourmapdepth) {
+ default:
+ return 0;
+ case 0: /* can be 0 if no colour map */
+ case 15:
+ case 16:
+ case 24:
+ case 32:
+ break;
+ }
+
+ return 1;
+}
+
+
/*
=item tga_header_pack(header, headbuf)
s->len = (s->hdr &~(1<<7))+1;
s->state = (s->hdr & (1<<7)) ? Rle : Raw;
{
+/*
static cnt = 0;
printf("%04d %s: %d\n", cnt++, s->state==Rle?"RLE":"RAW", s->len);
- }
+ */
+ }
if (s->state == Rle && s->ig->readcb(s->ig, s->cval, s->bytepp) != s->bytepp) return 0;
break;
static
int
tga_dest_write(tga_dest *s, unsigned char *buf, size_t pixels) {
- int cp = 0, j, k;
+ int cp = 0;
if (!s->compressed) {
if (s->ig->writecb(s->ig, buf, pixels*s->bytepp) != pixels*s->bytepp) return 0;
i_img *
i_readtga_wiol(io_glue *ig, int length) {
i_img* img = NULL;
- int x, y, i;
+ int x, y;
int width, height, channels;
int mapped;
char *idstring = NULL;
tga_header header;
unsigned char headbuf[18];
unsigned char *databuf;
- unsigned char *reorderbuf;
i_color *linebuf = NULL;
i_clear_error();
width = header.width;
height = header.height;
+
/* Set tags here */
mapped = 1;
switch (header.datatypecode) {
- int tbpp;
case 2: /* Uncompressed, rgb images */
case 10: /* Compressed, rgb images */
mapped = 0;
case 9: /* Compressed, color-mapped images */
if ((channels = bpp_to_channels(mapped ?
header.colourmapdepth :
- header.bitsperpixel))) break;
+ header.bitsperpixel,
+ header.imagedescriptor & 0xF))) break;
i_push_error(0, "Targa Image has none of 15/16/24/32 pixel layout");
if (idstring) myfree(idstring);
return NULL;
mapped = 0;
channels = 1;
break;
+ default:
+ i_push_error(0, "invalid or unsupported datatype code");
+ return NULL;
+ }
+
+ if (!i_int_check_image_file_limits(width, height, channels,
+ sizeof(i_sample_t))) {
+ mm_log((1, "i_readtga_wiol: image size exceeds limits\n"));
+ return NULL;
}
img = mapped ?
i_img_pal_new(width, height, channels, 256) :
i_img_empty_ch(NULL, width, height, channels);
+
+ if (!img) {
+ if (idstring)
+ myfree(idstring);
+ return NULL;
+ }
if (idstring) {
i_tags_add(&img->tags, "tga_idstring", 0, idstring, header.idlength, 0);
for(y=0; y<height; y++) {
if (!tga_source_read(&src, databuf, width)) {
i_push_error(errno, "read for targa data failed");
+ if (linebuf) myfree(linebuf);
myfree(databuf);
if (img) i_img_destroy(img);
return NULL;
myfree(databuf);
if (linebuf) myfree(linebuf);
+ i_tags_add(&img->tags, "i_format", 0, "tga", -1, 0);
i_tags_addn(&img->tags, "tga_bitspp", 0, mapped?header.colourmapdepth:header.bitsperpixel);
if (src.compressed) i_tags_addn(&img->tags, "compressed", 0, 1);
return img;
undef_int
i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen) {
- static int rgb_chan[] = { 2, 1, 0, 3 };
tga_header header;
tga_dest dest;
unsigned char headbuf[18];
unsigned int bitspp;
+ unsigned int attr_bits = 0;
int mapped;
mm_log((1, "channels %d\n", img->channels));
i_clear_error();
-
+ io_glue_commit_types(ig);
+
switch (img->channels) {
case 1:
bitspp = 8;
break;
case 4:
bitspp = wierdpack ? 16 : 32;
+ attr_bits = wierdpack ? 1 : 8;
break;
default:
i_push_error(0, "Targa only handles 1,3 and 4 channel images.");
return 0;
}
- io_glue_commit_types(ig);
-
- header.idlength;
header.idlength = idlen;
header.colourmaptype = mapped ? 1 : 0;
header.datatypecode = mapped ? 1 : img->channels == 1 ? 3 : 2;
header.width = img->xsize;
header.height = img->ysize;
header.bitsperpixel = mapped ? 8 : bitspp;
- header.imagedescriptor = (1<<5); /* normal order instead of upside down */
+ header.imagedescriptor = (1<<5) | attr_bits; /* normal order instead of upside down */
tga_header_pack(&header, headbuf);
mm_log((1, "dest.bytepp = %d\n", dest.bytepp));
if (img->type == i_palette_type) {
- int i;
- int bytepp = bpp_to_bytes(bitspp);
if (!tga_palette_write(ig, img, bitspp, i_colorcount(img))) return 0;
if (!img->virtual && !dest.compressed) {