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