Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OpenTGA.cpp

Go to the documentation of this file.
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     // read header
00014     byte header[18];
00015     if (file->read(header, 18) != 18) {
00016       return 0;
00017     }
00018 
00019     // decode header
00020     int id_length        = header[0];
00021     int cm_type          = header[1];
00022     int image_type       = header[2];
00023     //int cm_first         = read16_le(header + 3);
00024     int cm_length        = read16_le(header + 5);
00025     int cm_entry_size    = header[7];  // in bits
00026     //int x_origin         = read16_le(header + 8);
00027     //int y_origin         = read16_le(header + 10);
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;  // left-to-right?
00034     bool flipped  = (image_descriptor & (1 << 5)) == 0;  // bottom-to-top?
00035 
00036     /*
00037      * image types
00038      * 0  = no image data
00039      * 1  = uncompressed, color-mapped
00040      * 2  = uncompressed, true-color
00041      * 3  = uncompressed, black and white
00042      * 9  = RLE, color-mapped
00043      * 10 = RLE, true-color
00044      * 11 = RLE, black and white
00045      */
00046 
00047     // make sure we support the image
00048     if (image_type != 2 || (pixel_depth != 24 && pixel_depth != 32)) {
00049       return 0;
00050     }
00051 
00052     // skip image id
00053     byte unused[255];
00054     if (file->read(unused, id_length) != id_length) {
00055       return 0;
00056     }
00057 
00058     // skip color map
00059     if (cm_type != 0) {
00060       // allocate color map
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     // read image data
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     // reverse each row
00099     if (mirrored) {
00100       COR_LOG("Image is mirrored");
00101 
00102       const int bpp = pixel_depth / 8;  // bytes per pixel
00103       for (int y = 0; y < height; ++y) {
00104 
00105         // points to the first pixel of the row
00106         byte* start = pixels.get() + y * width * bpp;
00107         // points to the last pixel of the row
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     // reverse rows as a whole
00121     if (flipped) {
00122       COR_LOG("Image is flipped");
00123 
00124       const int bpp = pixel_depth / 8;  // bytes per pixel
00125       const int row_size = width * bpp;
00126       auto_array<byte> temp(new byte[row_size]);  // for the swap
00127 
00128       // points to the beginning of the first row
00129       byte* start = pixels.get();
00130 
00131       // points to the beginning of the last row
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 }

Generated on Thu Oct 2 12:59:31 2003 for corona by doxygen1.3-rc1