goat3dgfx

annotate src/image.cc @ 20:d9c8cd19c606

fixed the face index loading bug
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 08 Dec 2013 03:00:49 +0200
parents 3d96734fd477
children
rev   line source
nuclear@0 1 #include <string.h>
nuclear@6 2
nuclear@6 3 #ifndef _MSC_VER
nuclear@6 4 #include <alloca.h>
nuclear@6 5 #else
nuclear@6 6 #include <malloc.h>
nuclear@6 7 #endif
nuclear@6 8
nuclear@0 9 #include "imago2.h"
nuclear@0 10 #include "image.h"
nuclear@0 11 #include "logger.h"
nuclear@0 12
nuclear@15 13 using namespace goatgfx;
nuclear@0 14
nuclear@0 15 static int pixel_elements(Image::Format fmt);
nuclear@0 16 static int elem_size(Image::Format fmt);
nuclear@0 17 static int pixel_size(Image::Format fmt);
nuclear@0 18
nuclear@0 19 Image::Image()
nuclear@0 20 {
nuclear@0 21 fmt = FMT_RGBA;
nuclear@0 22 width = height = 0;
nuclear@0 23 pixels = 0;
nuclear@0 24 }
nuclear@0 25
nuclear@0 26 Image::~Image()
nuclear@0 27 {
nuclear@0 28 delete [] (char*)pixels;
nuclear@0 29 }
nuclear@0 30
nuclear@0 31 int Image::get_width() const
nuclear@0 32 {
nuclear@0 33 return width;
nuclear@0 34 }
nuclear@0 35
nuclear@0 36 int Image::get_height() const
nuclear@0 37 {
nuclear@0 38 return height;
nuclear@0 39 }
nuclear@0 40
nuclear@0 41 Image::Format Image::get_format() const
nuclear@0 42 {
nuclear@0 43 return fmt;
nuclear@0 44 }
nuclear@0 45
nuclear@0 46 bool Image::create(int x, int y, Format fmt)
nuclear@0 47 {
nuclear@0 48 width = x;
nuclear@0 49 height = y;
nuclear@0 50 this->fmt = fmt;
nuclear@0 51
nuclear@0 52 try {
nuclear@0 53 pixels = new char[x * y * pixel_size(fmt)];
nuclear@0 54 }
nuclear@0 55 catch(...) {
nuclear@0 56 return false;
nuclear@0 57 }
nuclear@0 58 return true;
nuclear@0 59 }
nuclear@0 60
nuclear@6 61 bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt)
nuclear@0 62 {
nuclear@6 63 if(!create(xsz, ysz, fmt)) {
nuclear@0 64 return false;
nuclear@0 65 }
nuclear@6 66 memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt));
nuclear@6 67 return true;
nuclear@6 68 }
nuclear@6 69
nuclear@6 70 bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt)
nuclear@6 71 {
nuclear@6 72 return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt);
nuclear@6 73 }
nuclear@6 74
nuclear@6 75 bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt)
nuclear@6 76 {
nuclear@6 77 if(scan_width <= 0) {
nuclear@6 78 scan_width = xsz;
nuclear@6 79 }
nuclear@6 80
nuclear@6 81 if(!create(xsz, ysz, fmt)) {
nuclear@6 82 return false;
nuclear@6 83 }
nuclear@6 84
nuclear@6 85 int pixsz = pixel_size(fmt);
nuclear@6 86
nuclear@6 87 unsigned char *dest = (unsigned char*)this->pixels;
nuclear@6 88 unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz;
nuclear@6 89 for(int i=0; i<ysz; i++) {
nuclear@6 90 memcpy(dest, src, xsz * pixsz);
nuclear@6 91 dest += xsz * pixsz;
nuclear@6 92 src += scan_width * pixsz;
nuclear@6 93 }
nuclear@0 94 return true;
nuclear@0 95 }
nuclear@0 96
nuclear@0 97 void *Image::get_pixels() const
nuclear@0 98 {
nuclear@0 99 return pixels;
nuclear@0 100 }
nuclear@0 101
nuclear@6 102 void Image::flip_horizontal()
nuclear@6 103 {
nuclear@6 104 int pixsz = pixel_size(fmt);
nuclear@6 105
nuclear@6 106 unsigned char *tmppix = (unsigned char*)alloca(pixsz);
nuclear@6 107
nuclear@6 108 unsigned char *scan = (unsigned char*)pixels;
nuclear@6 109 for(int i=0; i<height; i++) {
nuclear@6 110 unsigned char *dest = scan;
nuclear@6 111 unsigned char *src = scan + (width - 1) * pixsz;
nuclear@6 112
nuclear@6 113 while(src > dest) {
nuclear@6 114 memcpy(tmppix, src, pixsz);
nuclear@6 115 memcpy(src, dest, pixsz);
nuclear@6 116 memcpy(dest, tmppix, pixsz);
nuclear@6 117 dest += pixsz;
nuclear@6 118 src -= pixsz;
nuclear@6 119 }
nuclear@6 120
nuclear@6 121 scan += width * pixsz;
nuclear@6 122 }
nuclear@6 123 }
nuclear@6 124
nuclear@6 125 void Image::flip_vertical()
nuclear@6 126 {
nuclear@6 127 int pixsz = pixel_size(fmt);
nuclear@6 128
nuclear@6 129 unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz);
nuclear@6 130
nuclear@6 131 unsigned char *dest = (unsigned char*)pixels;
nuclear@6 132 unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz;
nuclear@6 133
nuclear@6 134 while(src > dest) {
nuclear@6 135 memcpy(tmpscan, src, width * pixsz);
nuclear@6 136 memcpy(src, dest, width * pixsz);
nuclear@6 137 memcpy(dest, tmpscan, width * pixsz);
nuclear@6 138 dest += width * pixsz;
nuclear@6 139 src -= width * pixsz;
nuclear@6 140 }
nuclear@6 141 }
nuclear@6 142
nuclear@6 143 void Image::rotate_180()
nuclear@6 144 {
nuclear@6 145 flip_vertical();
nuclear@6 146 flip_horizontal();
nuclear@6 147 }
nuclear@6 148
nuclear@0 149 bool Image::load(const char *fname)
nuclear@0 150 {
nuclear@0 151 struct img_pixmap pixmap;
nuclear@0 152
nuclear@0 153 img_init(&pixmap);
nuclear@0 154 if(img_load(&pixmap, fname) == -1) {
nuclear@0 155 return false;
nuclear@0 156 }
nuclear@0 157
nuclear@0 158 Format fmt;
nuclear@0 159 switch(pixmap.fmt) {
nuclear@0 160 case IMG_FMT_GREY8:
nuclear@0 161 fmt = FMT_GREY;
nuclear@0 162 break;
nuclear@0 163 case IMG_FMT_RGB24:
nuclear@0 164 fmt = FMT_RGB;
nuclear@0 165 break;
nuclear@0 166 case IMG_FMT_RGBA32:
nuclear@0 167 fmt = FMT_RGBA;
nuclear@0 168 break;
nuclear@0 169 case IMG_FMT_GREYF:
nuclear@0 170 fmt = FMT_GREY_FLOAT;
nuclear@0 171 break;
nuclear@0 172 case IMG_FMT_RGBF:
nuclear@0 173 fmt = FMT_RGB_FLOAT;
nuclear@0 174 break;
nuclear@0 175 case IMG_FMT_RGBAF:
nuclear@0 176 fmt = FMT_RGBA_FLOAT;
nuclear@0 177 break;
nuclear@0 178 default:
nuclear@0 179 img_destroy(&pixmap);
nuclear@0 180 return false;
nuclear@0 181 }
nuclear@0 182
nuclear@0 183 if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) {
nuclear@0 184 img_destroy(&pixmap);
nuclear@0 185 return false;
nuclear@0 186 }
nuclear@0 187 img_destroy(&pixmap);
nuclear@0 188 return true;
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 bool Image::save(const char *fname) const
nuclear@0 192 {
nuclear@0 193 struct img_pixmap pixmap;
nuclear@0 194
nuclear@0 195 img_init(&pixmap);
nuclear@0 196
nuclear@0 197 switch(fmt) {
nuclear@0 198 case FMT_GREY:
nuclear@0 199 pixmap.fmt = IMG_FMT_GREY8;
nuclear@0 200 break;
nuclear@0 201 case FMT_GREY_FLOAT:
nuclear@0 202 pixmap.fmt = IMG_FMT_GREYF;
nuclear@0 203 break;
nuclear@0 204 case FMT_RGB:
nuclear@0 205 pixmap.fmt = IMG_FMT_RGB24;
nuclear@0 206 break;
nuclear@0 207 case FMT_RGB_FLOAT:
nuclear@0 208 pixmap.fmt = IMG_FMT_RGBF;
nuclear@0 209 break;
nuclear@0 210 case FMT_RGBA:
nuclear@0 211 pixmap.fmt = IMG_FMT_RGBA32;
nuclear@0 212 break;
nuclear@0 213 case FMT_RGBA_FLOAT:
nuclear@0 214 pixmap.fmt = IMG_FMT_RGBAF;
nuclear@0 215 break;
nuclear@0 216 default:
nuclear@0 217 return false;
nuclear@0 218 }
nuclear@0 219
nuclear@0 220 pixmap.width = width;
nuclear@0 221 pixmap.height = height;
nuclear@0 222 pixmap.pixels = pixels;
nuclear@0 223 pixmap.pixelsz = pixel_size(fmt);
nuclear@0 224
nuclear@0 225 if(img_save(&pixmap, fname) == -1) {
nuclear@0 226 return false;
nuclear@0 227 }
nuclear@0 228 return true;
nuclear@0 229 }
nuclear@0 230
nuclear@0 231 static int pixel_elements(Image::Format fmt)
nuclear@0 232 {
nuclear@0 233 switch(fmt) {
nuclear@0 234 case Image::FMT_GREY:
nuclear@0 235 case Image::FMT_GREY_FLOAT:
nuclear@0 236 return 1;
nuclear@0 237
nuclear@0 238 case Image::FMT_RGB:
nuclear@0 239 case Image::FMT_RGB_FLOAT:
nuclear@0 240 return 3;
nuclear@0 241
nuclear@0 242 case Image::FMT_RGBA:
nuclear@0 243 case Image::FMT_RGBA_FLOAT:
nuclear@0 244 return 4;
nuclear@0 245
nuclear@0 246 default:
nuclear@0 247 break;
nuclear@0 248 }
nuclear@0 249 return 0;
nuclear@0 250 }
nuclear@0 251
nuclear@0 252 static int elem_size(Image::Format fmt)
nuclear@0 253 {
nuclear@0 254 switch(fmt) {
nuclear@0 255 case Image::FMT_GREY:
nuclear@0 256 case Image::FMT_RGB:
nuclear@0 257 case Image::FMT_RGBA:
nuclear@0 258 return 1;
nuclear@0 259
nuclear@0 260 case Image::FMT_GREY_FLOAT:
nuclear@0 261 case Image::FMT_RGB_FLOAT:
nuclear@0 262 case Image::FMT_RGBA_FLOAT:
nuclear@0 263 return sizeof(float);
nuclear@0 264
nuclear@0 265 default:
nuclear@0 266 break;
nuclear@0 267 }
nuclear@0 268 return 0;
nuclear@0 269 }
nuclear@0 270
nuclear@0 271 static int pixel_size(Image::Format fmt)
nuclear@0 272 {
nuclear@0 273 return elem_size(fmt) * pixel_elements(fmt);
nuclear@0 274 }