📄 plugintarga.cpp
字号:
// ==========================================================// TARGA Loader//// Design and implementation by// - Floris van den Berg (flvdberg@wxs.nl)// - Jani Kajala (janik@remedy.fi)// - Martin Weber (martweb@gmx.net)// - Machiel ten Brinke (brinkem@uni-one.nl)//// This file is part of FreeImage 2//// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER// THIS DISCLAIMER.//// Use at your own risk!// ==========================================================#include <assert.h>#include "thirdparty/common/FreeImage/Source/FreeImage.h"#include "thirdparty/common/FreeImage/Source/Utilities.h" // ----------------------------------------------------------// Constants + headers// ----------------------------------------------------------#ifdef WIN32#pragma pack(push, 1)#else#pragma pack(1)#endiftypedef struct tagRGBTRIPLE { BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed;} RGBTRIPLE; typedef struct tagBGRAQUAD { BYTE bgraBlue; BYTE bgraGreen; BYTE bgraRed; BYTE bgraAlpha;} BGRAQUAD; struct tagTGAHEADER { BYTE id_length; BYTE color_map_type; BYTE image_type; WORD cm_first_entry; WORD cm_length; BYTE cm_size; WORD is_xorigin; WORD is_yorigin; WORD is_width; WORD is_height; BYTE is_pixel_depth; BYTE is_image_descriptor;};#ifdef WIN32#pragma pack(pop)#else#pragma pack(4)#endif// ==========================================================// Internal functions// ==========================================================static BYTE *Internal_GetScanLine(FreeImage &freeimage, FIBITMAP *dib, int scanline, int flipvert) { //assert ((scanline >= 0) && (scanline < (int)freeimage.get_height_proc(dib))); if (flipvert) { return freeimage.get_scanline_proc(dib, scanline); } else { return freeimage.get_scanline_proc(dib, freeimage.get_height_proc(dib) - scanline - 1); }}// ==========================================================// Plugin Interface// ==========================================================static int s_format_id;// ==========================================================// Plugin Implementation// ==========================================================static const char * DLL_CALLCONVFormat() { return "TARGA";}static const char * DLL_CALLCONVDescription() { return "Truevision Targa";}static const char * DLL_CALLCONVExtension() { return "tga,targa";}static const char * DLL_CALLCONVRegExpr() { return NULL;}// ----------------------------------------------------------static FIBITMAP * DLL_CALLCONVLoad(FreeImage &freeimage, FreeImageIO &io, fi_handle handle, int page, int flags, void *data) { if (handle) { try { // remember the start offset long start_offset = io.tell_proc(handle); // read and process the bitmap's header FIBITMAP *dib = NULL; tagTGAHEADER header; io.read_proc(&header, sizeof(tagTGAHEADER), 1, handle); int line = CalculateLine(header.is_width, header.is_pixel_depth); int pitch = CalculatePitch(line); int alphabits = header.is_image_descriptor & 0x0f; int fliphoriz = (header.is_image_descriptor & 0x10) ? 0 : 1; int flipvert = (header.is_image_descriptor & 0x20) ? 1 : 0; io.seek_proc(handle, header.id_length, SEEK_CUR); switch (header.is_pixel_depth) { case 8 : { dib = freeimage.allocate_proc(header.is_width, header.is_height, 8, 0, 0, 0); if (dib == NULL) { throw "DIB allocation failed"; } // read the palette RGBQUAD *palette = freeimage.get_palette_proc(dib); if (header.color_map_type == 0) for (unsigned i = 0; i < 256; i++) { palette[i].rgbRed = i; palette[i].rgbGreen = i; palette[i].rgbBlue = i; } else if (alphabits) { for (unsigned count = header.cm_first_entry; count < header.cm_length; count++) { BGRAQUAD quad; io.read_proc(&quad, sizeof(RGBTRIPLE), 1, handle); palette[count].rgbBlue = quad.bgraBlue; palette[count].rgbRed = quad.bgraRed; palette[count].rgbGreen = quad.bgraGreen; palette[count].rgbReserved = quad.bgraAlpha; } } else { for (unsigned count = header.cm_first_entry; count < header.cm_length; count++) { RGBTRIPLE triple; io.read_proc(&triple, sizeof(RGBTRIPLE), 1, handle); palette[count].rgbRed = triple.rgbtRed; palette[count].rgbGreen = triple.rgbtGreen; palette[count].rgbBlue = triple.rgbtBlue; } } // read in the bitmap bits switch (header.image_type) { case 1 : case 3 : { if (fliphoriz) { for (unsigned count = header.is_height; count > 0; count--) io.read_proc(Internal_GetScanLine(freeimage, dib, count - 1, flipvert), line, 1, handle); } else { for (unsigned count = 0; count < header.is_height; count++) io.read_proc(Internal_GetScanLine(freeimage, dib, count, flipvert), line, 1, handle); } break; } case 9 : case 11: { int x = 0; int y = 0; BYTE *bits; if (fliphoriz) bits = Internal_GetScanLine(freeimage, dib, header.is_height - y - 1, flipvert); else bits = Internal_GetScanLine(freeimage, dib, y, flipvert); BYTE rle; while(1) { io.read_proc(&rle,1, 1, handle); if (rle>127) { rle -= 127; BYTE triple; io.read_proc(&triple, 1, 1, handle); for (int ix = 0; ix < rle; ix++) { bits[x++] = triple; if (x >= line) { x = 0; y++; if (y >= header.is_height) goto done89; if(fliphoriz) bits = Internal_GetScanLine(freeimage, dib, header.is_height-y-1, flipvert); else bits = Internal_GetScanLine(freeimage, dib, y, flipvert); } } } else { rle++; for (int ix = 0; ix < rle; ix++) { BYTE triple; io.read_proc(&triple, 1, 1, handle); bits[x++] = triple; if (x >= line) { x = 0; y++; if (y >= header.is_height) goto done89; if(fliphoriz) bits = Internal_GetScanLine(freeimage, dib, header.is_height-y-1, flipvert); else bits = Internal_GetScanLine(freeimage, dib, y, flipvert); } } } } done89 : break; } default : freeimage.free_proc(dib); return NULL; } break; } case 15 : case 16 : { int pixel_bits; // allocate the dib if (TARGA_LOAD_RGB888 & flags) { pixel_bits = 24; dib = freeimage.allocate_proc(header.is_width, header.is_height, pixel_bits, 0xFF, 0xFF00, 0xFF0000); } else { pixel_bits = 16; dib = freeimage.allocate_proc(header.is_width, header.is_height, pixel_bits, 0x1F, 0x3E0, 0x7C00); } if (dib == NULL) throw "DIB allocation failed"; int line = CalculateLine(header.is_width, pixel_bits); int pitch = CalculatePitch(line); const unsigned pixel_size = unsigned(pixel_bits) / 8; // note header.cm_size is a misleading name, it should be seen as header.cm_bits // ignore current position in file and set filepointer explicitly from the beginning of the file int garblen = 0; if (header.color_map_type != 0) garblen = (int)((header.cm_size + 7) / 8) * header.cm_length; /* should byte align */ else garblen = 0; io.seek_proc(handle, start_offset, SEEK_SET); io.seek_proc(handle, sizeof(tagTGAHEADER) + header.id_length + garblen, SEEK_SET); // read in the bitmap bits WORD pixel; switch (header.image_type) { case 2 : { for (int y = 0; y < header.is_height; y++) { BYTE *bits; if(fliphoriz) bits = Internal_GetScanLine(freeimage, dib, header.is_height-y-1, flipvert); else bits = Internal_GetScanLine(freeimage, dib, y, flipvert); for (int x = 0; x < line; ) { io.read_proc(&pixel, sizeof(WORD), 1, handle); if (TARGA_LOAD_RGB888 & flags) { bits[x + 0] = ((pixel & 0x1F) * 0xFF) / 0x1F; bits[x + 1] = (((pixel & 0x3E0) >> 5) * 0xFF) / 0x1F; bits[x + 2] = (((pixel & 0x7C00) >> 10) * 0xFF) / 0x1F; } else { *reinterpret_cast<WORD*>(bits + x) = 0x7FFF & pixel; } x += pixel_size; } } break; } case 10 : { int x = 0; int y = 0; BYTE rle; WORD pixel; while(1) { BYTE *bits; if(fliphoriz) bits = Internal_GetScanLine(freeimage, dib, header.is_height-y-1, flipvert); else bits = Internal_GetScanLine(freeimage, dib, y, flipvert); io.read_proc(&rle,1, 1, handle); // compressed block if (rle > 127) { rle -= 127; io.read_proc(&pixel, sizeof(WORD), 1, handle); for (int ix = 0; ix < rle; ix++) { if (TARGA_LOAD_RGB888 & flags) { bits[x + 0] = ((pixel & 0x1F) * 0xFF) / 0x1F; bits[x + 1] = (((pixel & 0x3E0) >> 5) * 0xFF) / 0x1F; bits[x + 2] = (((pixel & 0x7C00) >> 10) * 0xFF) / 0x1F; } else { *reinterpret_cast<WORD *>(bits + x) = 0x7FFF & pixel; } x += pixel_size; if (x >= line) { x = 0; y++; if (y >= header.is_height) goto done2; } } } else { rle++; for (int ix = 0; ix < rle; ix++) { io.read_proc(&pixel, sizeof(WORD), 1, handle); if (TARGA_LOAD_RGB888 & flags) { bits[x + 0] = ((pixel & 0x1F) * 0xFF) / 0x1F; bits[x + 1] = (((pixel & 0x3E0) >> 5) * 0xFF) / 0x1F; bits[x + 2] = (((pixel & 0x7C00) >> 10) * 0xFF) / 0x1F; } else { *reinterpret_cast<WORD*>(bits + x) = 0x7FFF & pixel; } x += pixel_size; if (x >= line) { x = 0; y++; if (y >= header.is_height) goto done2; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -