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
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
00050
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
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
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
00152
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
00163
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
00177 if (!image ||
00178 palette_format == PF_DONTCARE ||
00179 image->getPaletteFormat() == palette_format)
00180 {
00181 return image;
00182 }
00183
00184
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
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
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
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
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 }