/* --------------------------------------------------------------------------- * Return a pointer to a given pixel. Accounts for image orientation (T_TO_B, * R_TO_L, etc). Returns NULL if the pixel is out of range. */ uint8_t *tga_find_pixel(const tga_image *img, uint16_t x, uint16_t y) { if (x >= img->width || y >= img->height) return NULL; if (!tga_is_top_to_bottom(img)) y = img->height - 1 - y; if (tga_is_right_to_left(img)) x = img->width - 1 - x; return img->image_data + (x + y * img->width) * img->pixel_depth/8; }
void load_tga(tga_image *tga, const char *fn) { DONTFAIL( tga_read(tga, fn) ); printf("Loaded %dx%dx%dbpp targa (\"%s\").\n", tga->width, tga->height, tga->pixel_depth, fn); if (!tga_is_mono(tga)) DONTFAIL( tga_desaturate_rec_601_1(tga) ); if (!tga_is_top_to_bottom(tga)) DONTFAIL( tga_flip_vert(tga) ); if (tga_is_right_to_left(tga)) DONTFAIL( tga_flip_horiz(tga) ); if ((tga->width % 8 != 0) || (tga->height % 8 != 0)) { printf("Width and height must be multiples of 8\n"); exit(EXIT_FAILURE); } }
/* --------------------------------------------------------------------------- * Vertically flip the image in place. Reverses the top-to-bottom bit in * the image descriptor. */ tga_result tga_flip_vert(tga_image *img) { uint16_t col; size_t bpp, line; uint8_t *top, *bottom; int t_to_b; if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH; bpp = (size_t)(img->pixel_depth / 8); /* bytes per pixel */ line = bpp * img->width; /* bytes per line */ for (col=0; col<img->width; col++) { top = img->image_data + col * bpp; bottom = top + (img->height - 1) * line; /* reverse from top to bottom */ while (top < bottom) { uint8_t buffer[4]; /* swap */ memcpy(buffer, top, bpp); memcpy(top, bottom, bpp); memcpy(bottom, buffer, bpp); top += line; bottom -= line; } } /* Correct image_descriptor's top-to-bottom-ness. */ t_to_b = tga_is_top_to_bottom(img); img->image_descriptor &= ~TGA_T_TO_B_BIT; /* mask out t-to-b bit */ if (!t_to_b) /* was b-to-t, need to set t_to_b */ img->image_descriptor |= TGA_T_TO_B_BIT; /* else bit is already rubbed out */ return TGA_NOERR; }
static RGBSpectrum *ReadImageTGA(const std::string &name, int *width, int *height) { tga_image img; tga_result result; if ((result = tga_read(&img, name.c_str())) != TGA_NOERR) { Error("Unable to read from TGA file \"%s\" (%s)", name.c_str(), tga_error(result)); return nullptr; } if (tga_is_right_to_left(&img)) tga_flip_horiz(&img); if (!tga_is_top_to_bottom(&img)) tga_flip_vert(&img); if (tga_is_colormapped(&img)) tga_color_unmap(&img); *width = img.width; *height = img.height; // "Unpack" the pixels (origin in the lower left corner). // TGA pixels are in BGRA format. RGBSpectrum *ret = new RGBSpectrum[*width * *height]; RGBSpectrum *dst = ret; for (int y = *height - 1; y >= 0; y--) for (int x = 0; x < *width; x++) { uint8_t *src = tga_find_pixel(&img, x, y); if (tga_is_mono(&img)) *dst++ = RGBSpectrum(*src / 255.f); else { Float c[3]; c[2] = src[0] / 255.f; c[1] = src[1] / 255.f; c[0] = src[2] / 255.f; *dst++ = RGBSpectrum::FromRGB(c); } } tga_free_buffers(&img); Info("Read TGA image %s (%d x %d)", name.c_str(), *width, *height); return ret; }
void ImageFormat_TGA::CopyPixels(unsigned int* destination) { tga_image* image=static_cast<tga_image*>(image_); bool upsidedown=!tga_is_top_to_bottom(image); int width=image->width; int height=image->height; unsigned char* data=image->image_data; if (image->pixel_depth==24) { for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { unsigned int c=0xff000000; c|=data[2]<<16; c|=data[1]<<8; c|=data[0]; int yp=y; if (upsidedown) { yp=height-y-1; } destination[x+yp*width]=c; data+=3; } } return; } if (image->pixel_depth==32) { for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { unsigned int c=0x00000000; c|=data[3]<<24; c|=data[2]<<16; c|=data[1]<<8; c|=data[0]; int yp=y; if (upsidedown) { yp=height-y-1; } destination[x+yp*width]=c; data+=4; } } return; } if (image->pixel_depth==16) { for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { unsigned int s=data[1]<<8 | data[0]; unsigned int c=0xff000000; unsigned int b=((s&0x1f)); unsigned int g=(((s>>5)&0x1f)); unsigned int r=(((s>>10)&0x1f)); float fr=((float)r)/31.0f; float fg=((float)g)/31.0f; float fb=((float)b)/31.0f; r=(unsigned int)(255.0f*fr); g=(unsigned int)(255.0f*fg); b=(unsigned int)(255.0f*fb); c|=r<<16; c|=g<<8; c|=b; int yp=y; if (upsidedown) { yp=height-y-1; } destination[x+yp*width]=c; data+=2; } } return; } Assert(false,"Unsupported TGA file"); }