vrshoot

annotate src/image.cc @ 0:b2f14e535253

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