goat3dgfx

annotate src/image.cc @ 13:25bf39105c82

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