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

Convert.cpp

Go to the documentation of this file.
00001 
00006 #include <map>
00007 #include <utility>
00008 #include "corona.h"
00009 #include "Debug.h"
00010 #include "SimpleImage.h"
00011 #include "Utility.h"
00012 
00013 
00014 namespace corona {
00015 
00016   Image* ExpandPalette(Image* image) {
00017     COR_GUARD("ExpandPalette()");
00018 
00019     // assert isPalettized(image->getFormat())
00020 
00021     const int width                  = image->getWidth();
00022     const int height                 = image->getHeight();
00023     const byte* in                   = (byte*)image->getPixels();
00024     const PixelFormat palette_format = image->getPaletteFormat();
00025     const int pixel_size             = GetPixelSize(palette_format);
00026     const byte* palette              = (byte*)image->getPalette();
00027 
00028     byte* pixels = new byte[width * height * pixel_size];
00029     byte* out = pixels;
00030     for (int i = 0; i < width * height; ++i) {
00031       memcpy(out, palette + (*in) * pixel_size, pixel_size);
00032       out += pixel_size;
00033       ++in;
00034     }
00035     delete image;
00036     return new SimpleImage(width, height, palette_format, pixels);
00037   }
00038 
00039 
00040   struct FormatDesc {
00041     FormatDesc(int r, int g, int b, int a, bool ha) {
00042       r_shift = r;
00043       g_shift = g;
00044       b_shift = b;
00045       a_shift = a;
00046       has_alpha = ha;
00047     }
00048 
00049     // shifts are in bytes from the right
00050     // In the case of RGBA, r_shift is 0, g_shift is 1, ...
00051     int r_shift;
00052     int g_shift;
00053     int b_shift;
00054     int a_shift;
00055     bool has_alpha;
00056   };
00057 
00058 
00059   #define DEFINE_DESC(format, desc)          \
00060     case format: {                           \
00061       COR_LOG(#format);                      \
00062       static FormatDesc format##_desc desc;  \
00063       return &format##_desc;                 \
00064     }
00065 
00066   FormatDesc* GetDescription(PixelFormat format) {
00067     // assert isDirect(image->getFormat())
00068 
00069     switch (format) {
00070       DEFINE_DESC(PF_R8G8B8A8, (0, 1, 2, 3, true));
00071       DEFINE_DESC(PF_R8G8B8,   (0, 1, 2, 0, false));
00072       DEFINE_DESC(PF_B8G8R8A8, (2, 1, 0, 3, true));
00073       DEFINE_DESC(PF_B8G8R8,   (2, 1, 0, 0, false));
00074       default: return 0;
00075     }
00076   }
00077 
00078 
00079   bool ConvertPixels(byte* out, PixelFormat out_format,
00080                      const byte* in,  PixelFormat in_format,
00081                      int pixel_count)
00082   {
00083     const FormatDesc* out_desc = GetDescription(out_format);
00084     const FormatDesc* in_desc  = GetDescription(in_format);
00085     if (!out_desc || !in_desc) {
00086       return false;
00087     }
00088 
00089     const int out_size = GetPixelSize(out_format);
00090     const int in_size  = GetPixelSize(in_format);
00091 
00092     for (int i = 0; i < pixel_count; ++i) {
00093       out[out_desc->r_shift] = in[in_desc->r_shift];
00094       out[out_desc->g_shift] = in[in_desc->g_shift];
00095       out[out_desc->b_shift] = in[in_desc->b_shift];
00096 
00097       if (out_desc->has_alpha) {
00098         if (in_desc->has_alpha) {
00099           out[out_desc->a_shift] = in[in_desc->a_shift];
00100         } else {
00101           out[out_desc->a_shift] = 255;
00102         }
00103       }
00104 
00105       in  += in_size;
00106       out += out_size;
00107     }
00108 
00109     return true;
00110   }
00111 
00112 
00113   Image* DirectConversion(Image* image, PixelFormat target_format) {
00114     COR_GUARD("DirectConversion()");
00115 
00116     // assert isDirect(image->getFormat())
00117 
00118     const int width                 = image->getWidth();
00119     const int height                = image->getHeight();
00120     const PixelFormat source_format = image->getFormat();
00121     const byte* in                  = (byte*)image->getPixels();
00122 
00123     if (source_format == target_format) {
00124         return image;
00125     }
00126 
00127     const int target_size = GetPixelSize(target_format);
00128     byte* out_pixels = new byte[width * height * target_size];
00129     if (!ConvertPixels(out_pixels, target_format,
00130                        in, source_format,
00131                        width * height))
00132     {
00133       delete[] out_pixels;
00134       delete image;
00135       return 0;
00136     }
00137 
00138     delete image;
00139     return new SimpleImage(width, height, target_format, out_pixels);
00140   }
00141 
00142 
00143   namespace hidden {
00144 
00145     COR_EXPORT(Image*) CorConvertImage(
00146       Image* image,
00147       PixelFormat target_format)
00148     {
00149       COR_GUARD("CorConvertImage");
00150 
00151       // if we don't have an image, user doesn't care about format, or
00152       // the formats match, don't do any conversion.
00153       if (!image ||
00154           target_format == PF_DONTCARE ||
00155           target_format == image->getFormat())
00156       {
00157         return image;
00158       }
00159 
00160       COR_LOG("Doing the conversion...");
00161 
00162       // if we have a palettized image, convert it to a direct color
00163       // image and then convert that
00164       if (IsPalettized(image->getFormat())) {
00165         image = ExpandPalette(image);
00166       }
00167 
00168       return DirectConversion(image, target_format);
00169     }
00170 
00171 
00172     COR_EXPORT(Image*) CorConvertPalette(
00173       Image* image,
00174       PixelFormat palette_format)
00175     {
00176       // do we need to convert?
00177       if (!image ||
00178           palette_format == PF_DONTCARE ||
00179           image->getPaletteFormat() == palette_format)
00180       {
00181         return image;
00182       }
00183 
00184       // do we have invalid data?
00185       if (!IsPalettized(image->getFormat()) ||
00186           !IsDirect(palette_format))
00187       {
00188         delete image;
00189         return 0;
00190       }
00191 
00192       const int width  = image->getWidth();
00193       const int height = image->getHeight();
00194       const PixelFormat format = image->getFormat();
00195       const int palette_size = image->getPaletteSize();
00196 
00197       // the palette indices don't change, so just make a copy
00198       const int image_size = width * height * GetPixelSize(format);
00199       byte* pixels = new byte[image_size];
00200       memcpy(pixels, image->getPixels(), image_size);
00201 
00202       byte* new_palette = new byte[
00203         palette_size * GetPixelSize(palette_format)];
00204 
00205       if (!ConvertPixels(new_palette, palette_format,
00206                          (byte*)image->getPalette(), image->getPaletteFormat(),
00207                          palette_size))
00208       {
00209         delete image;
00210         delete[] pixels;
00211         delete[] new_palette;
00212         return 0;
00213       }
00214 
00215       delete image;
00216       return new SimpleImage(
00217         width, height, format, pixels,
00218         new_palette, palette_size, palette_format);
00219     }
00220 
00221     COR_EXPORT(Image*) CorFlipImage(
00222       Image* image,
00223       int coordinate_axis)
00224     {
00225       COR_GUARD("CorFlipImage");
00226 
00227       // if we don't have an image, don't flip.
00228       if (!image) {
00229         return 0;
00230       }
00231 
00232       COR_LOG("Doing the flip...");
00233 
00234       const int width                = image->getWidth();
00235       const int height               = image->getHeight();
00236       byte* pixels                   = (byte*)image->getPixels();
00237       const PixelFormat pixel_format = image->getFormat();
00238       const int pixel_size           = GetPixelSize(pixel_format);
00239 
00240       // flip about the X axis
00241       if (coordinate_axis & CA_X) {
00242 
00243         byte* row = new byte[width * pixel_size];
00244         for (int h = 0; h < height / 2; ++h) {
00245           byte* top = pixels + h                * width * pixel_size;
00246           byte* bot = pixels + (height - h - 1) * width * pixel_size;
00247           memcpy(row, top, width * pixel_size);
00248           memcpy(top, bot, width * pixel_size);
00249           memcpy(bot, row, width * pixel_size);
00250         }
00251         delete[] row;
00252 
00253       }
00254 
00255       // flip about the Y axis
00256       if (coordinate_axis & CA_Y) {
00257 
00258         for (int h = 0; h < height; ++h) {
00259           byte* row = pixels + h * width * pixel_size;
00260           for (int w = 0; w < width / 2; ++w) {
00261             byte* left  = row + w               * pixel_size;
00262             byte* right = row + (width - w - 1) * pixel_size;
00263             for (int b = 0; b < pixel_size; ++b) {
00264               std::swap(left[b], right[b]);
00265             }
00266           }
00267         }
00268 
00269       }
00270 
00271       return image;
00272     }
00273   }
00274 
00275 }

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