corona
1.0.2
|
00001 #include <algorithm> 00002 #include <string.h> 00003 #include "Debug.h" 00004 #include "Open.h" 00005 #include "SimpleImage.h" 00006 #include "Utility.h" 00007 00008 00009 namespace corona { 00010 00011 Image* OpenTGA(File* file) { 00012 COR_GUARD("OpenTGA"); 00013 00014 // read header 00015 byte header[18]; 00016 if (file->read(header, 18) != 18) { 00017 return 0; 00018 } 00019 00020 // decode header 00021 int id_length = header[0]; 00022 int cm_type = header[1]; 00023 int image_type = header[2]; 00024 //int cm_first = read16_le(header + 3); 00025 int cm_length = read16_le(header + 5); 00026 int cm_entry_size = header[7]; // in bits 00027 //int x_origin = read16_le(header + 8); 00028 //int y_origin = read16_le(header + 10); 00029 int width = read16_le(header + 12); 00030 int height = read16_le(header + 14); 00031 int pixel_depth = header[16]; 00032 int image_descriptor = header[17]; 00033 00034 bool mirrored = (image_descriptor & (1 << 4)) != 0; // left-to-right? 00035 bool flipped = (image_descriptor & (1 << 5)) == 0; // bottom-to-top? 00036 00037 /* 00038 * image types 00039 * 0 = no image data 00040 * 1 = uncompressed, color-mapped 00041 * 2 = uncompressed, true-color 00042 * 3 = uncompressed, black and white 00043 * 9 = RLE, color-mapped 00044 * 10 = RLE, true-color 00045 * 11 = RLE, black and white 00046 */ 00047 00048 // make sure we support the image 00049 if (image_type != 2 || (pixel_depth != 24 && pixel_depth != 32)) { 00050 return 0; 00051 } 00052 00053 // skip image id 00054 byte unused[255]; 00055 if (file->read(unused, id_length) != id_length) { 00056 return 0; 00057 } 00058 00059 // skip color map 00060 if (cm_type != 0) { 00061 // allocate color map 00062 int cm_entry_bytes = (cm_entry_size + 7) / 8; 00063 int cm_size = cm_entry_bytes * cm_length; 00064 auto_array<byte> color_map(new byte[cm_size]); 00065 if (file->read(color_map, cm_size) != cm_size) { 00066 return 0; 00067 } 00068 } 00069 00070 // read image data 00071 PixelFormat format; 00072 auto_array<byte> pixels; 00073 if (pixel_depth == 24) { 00074 00075 COR_LOG("24-bit image"); 00076 00077 format = PF_B8G8R8; 00078 int image_size = width * height * 3; 00079 pixels = new byte[image_size]; 00080 if (file->read(pixels, image_size) != image_size) { 00081 return 0; 00082 } 00083 00084 } else if (pixel_depth == 32) { 00085 00086 COR_LOG("32-bit image"); 00087 00088 format = PF_B8G8R8A8; 00089 int image_size = width * height * 4; 00090 pixels = new byte[image_size]; 00091 if (file->read(pixels, image_size) != image_size) { 00092 return 0; 00093 } 00094 00095 } else { 00096 return 0; 00097 } 00098 00099 // reverse each row 00100 if (mirrored) { 00101 COR_LOG("Image is mirrored"); 00102 00103 const int bpp = pixel_depth / 8; // bytes per pixel 00104 for (int y = 0; y < height; ++y) { 00105 00106 // points to the first pixel of the row 00107 byte* start = pixels.get() + y * width * bpp; 00108 // points to the last pixel of the row 00109 byte* end = start + (width - 1) * bpp; 00110 00111 while (start < end) { 00112 for (int b = 0; b < bpp; ++b) { 00113 std::swap(start[b], end[b]); 00114 } 00115 start += bpp; 00116 end -= bpp; 00117 } 00118 } 00119 } 00120 00121 // reverse rows as a whole 00122 if (flipped) { 00123 COR_LOG("Image is flipped"); 00124 00125 const int bpp = pixel_depth / 8; // bytes per pixel 00126 const int row_size = width * bpp; 00127 auto_array<byte> temp(new byte[row_size]); // for the swap 00128 00129 // points to the beginning of the first row 00130 byte* start = pixels.get(); 00131 00132 // points to the beginning of the last row 00133 byte* end = start + (height - 1) * width * bpp; 00134 00135 while (start < end) { 00136 memcpy(temp.get(), start, row_size); 00137 memcpy(start, end, row_size); 00138 memcpy(end, temp.get(), row_size); 00139 00140 start += row_size; 00141 end -= row_size; 00142 } 00143 } 00144 00145 return new SimpleImage(width, height, format, pixels.release()); 00146 } 00147 00148 }