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