vrshoot
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/image.cc Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,272 @@ 1.4 +#include <string.h> 1.5 + 1.6 +#ifndef _MSC_VER 1.7 +#include <alloca.h> 1.8 +#else 1.9 +#include <malloc.h> 1.10 +#endif 1.11 + 1.12 +#include "imago2.h" 1.13 +#include "image.h" 1.14 +#include "logger.h" 1.15 + 1.16 +static int pixel_elements(Image::Format fmt); 1.17 +static int elem_size(Image::Format fmt); 1.18 +static int pixel_size(Image::Format fmt); 1.19 + 1.20 +Image::Image() 1.21 +{ 1.22 + fmt = FMT_RGBA; 1.23 + width = height = 0; 1.24 + pixels = 0; 1.25 +} 1.26 + 1.27 +Image::~Image() 1.28 +{ 1.29 + delete [] (char*)pixels; 1.30 +} 1.31 + 1.32 +int Image::get_width() const 1.33 +{ 1.34 + return width; 1.35 +} 1.36 + 1.37 +int Image::get_height() const 1.38 +{ 1.39 + return height; 1.40 +} 1.41 + 1.42 +Image::Format Image::get_format() const 1.43 +{ 1.44 + return fmt; 1.45 +} 1.46 + 1.47 +bool Image::create(int x, int y, Format fmt) 1.48 +{ 1.49 + width = x; 1.50 + height = y; 1.51 + this->fmt = fmt; 1.52 + 1.53 + try { 1.54 + pixels = new char[x * y * pixel_size(fmt)]; 1.55 + } 1.56 + catch(...) { 1.57 + return false; 1.58 + } 1.59 + return true; 1.60 +} 1.61 + 1.62 +bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt) 1.63 +{ 1.64 + if(!create(xsz, ysz, fmt)) { 1.65 + return false; 1.66 + } 1.67 + memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt)); 1.68 + return true; 1.69 +} 1.70 + 1.71 +bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt) 1.72 +{ 1.73 + return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt); 1.74 +} 1.75 + 1.76 +bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt) 1.77 +{ 1.78 + if(scan_width <= 0) { 1.79 + scan_width = xsz; 1.80 + } 1.81 + 1.82 + if(!create(xsz, ysz, fmt)) { 1.83 + return false; 1.84 + } 1.85 + 1.86 + int pixsz = pixel_size(fmt); 1.87 + 1.88 + unsigned char *dest = (unsigned char*)this->pixels; 1.89 + unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz; 1.90 + for(int i=0; i<ysz; i++) { 1.91 + memcpy(dest, src, xsz * pixsz); 1.92 + dest += xsz * pixsz; 1.93 + src += scan_width * pixsz; 1.94 + } 1.95 + return true; 1.96 +} 1.97 + 1.98 +void *Image::get_pixels() const 1.99 +{ 1.100 + return pixels; 1.101 +} 1.102 + 1.103 +void Image::flip_horizontal() 1.104 +{ 1.105 + int pixsz = pixel_size(fmt); 1.106 + 1.107 + unsigned char *tmppix = (unsigned char*)alloca(pixsz); 1.108 + 1.109 + unsigned char *scan = (unsigned char*)pixels; 1.110 + for(int i=0; i<height; i++) { 1.111 + unsigned char *dest = scan; 1.112 + unsigned char *src = scan + (width - 1) * pixsz; 1.113 + 1.114 + while(src > dest) { 1.115 + memcpy(tmppix, src, pixsz); 1.116 + memcpy(src, dest, pixsz); 1.117 + memcpy(dest, tmppix, pixsz); 1.118 + dest += pixsz; 1.119 + src -= pixsz; 1.120 + } 1.121 + 1.122 + scan += width * pixsz; 1.123 + } 1.124 +} 1.125 + 1.126 +void Image::flip_vertical() 1.127 +{ 1.128 + int pixsz = pixel_size(fmt); 1.129 + 1.130 + unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz); 1.131 + 1.132 + unsigned char *dest = (unsigned char*)pixels; 1.133 + unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz; 1.134 + 1.135 + while(src > dest) { 1.136 + memcpy(tmpscan, src, width * pixsz); 1.137 + memcpy(src, dest, width * pixsz); 1.138 + memcpy(dest, tmpscan, width * pixsz); 1.139 + dest += width * pixsz; 1.140 + src -= width * pixsz; 1.141 + } 1.142 +} 1.143 + 1.144 +void Image::rotate_180() 1.145 +{ 1.146 + flip_vertical(); 1.147 + flip_horizontal(); 1.148 +} 1.149 + 1.150 +bool Image::load(const char *fname) 1.151 +{ 1.152 + struct img_pixmap pixmap; 1.153 + 1.154 + img_init(&pixmap); 1.155 + if(img_load(&pixmap, fname) == -1) { 1.156 + return false; 1.157 + } 1.158 + 1.159 + Format fmt; 1.160 + switch(pixmap.fmt) { 1.161 + case IMG_FMT_GREY8: 1.162 + fmt = FMT_GREY; 1.163 + break; 1.164 + case IMG_FMT_RGB24: 1.165 + fmt = FMT_RGB; 1.166 + break; 1.167 + case IMG_FMT_RGBA32: 1.168 + fmt = FMT_RGBA; 1.169 + break; 1.170 + case IMG_FMT_GREYF: 1.171 + fmt = FMT_GREY_FLOAT; 1.172 + break; 1.173 + case IMG_FMT_RGBF: 1.174 + fmt = FMT_RGB_FLOAT; 1.175 + break; 1.176 + case IMG_FMT_RGBAF: 1.177 + fmt = FMT_RGBA_FLOAT; 1.178 + break; 1.179 + default: 1.180 + img_destroy(&pixmap); 1.181 + return false; 1.182 + } 1.183 + 1.184 + if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) { 1.185 + img_destroy(&pixmap); 1.186 + return false; 1.187 + } 1.188 + img_destroy(&pixmap); 1.189 + return true; 1.190 +} 1.191 + 1.192 +bool Image::save(const char *fname) const 1.193 +{ 1.194 + struct img_pixmap pixmap; 1.195 + 1.196 + img_init(&pixmap); 1.197 + 1.198 + switch(fmt) { 1.199 + case FMT_GREY: 1.200 + pixmap.fmt = IMG_FMT_GREY8; 1.201 + break; 1.202 + case FMT_GREY_FLOAT: 1.203 + pixmap.fmt = IMG_FMT_GREYF; 1.204 + break; 1.205 + case FMT_RGB: 1.206 + pixmap.fmt = IMG_FMT_RGB24; 1.207 + break; 1.208 + case FMT_RGB_FLOAT: 1.209 + pixmap.fmt = IMG_FMT_RGBF; 1.210 + break; 1.211 + case FMT_RGBA: 1.212 + pixmap.fmt = IMG_FMT_RGBA32; 1.213 + break; 1.214 + case FMT_RGBA_FLOAT: 1.215 + pixmap.fmt = IMG_FMT_RGBAF; 1.216 + break; 1.217 + default: 1.218 + return false; 1.219 + } 1.220 + 1.221 + pixmap.width = width; 1.222 + pixmap.height = height; 1.223 + pixmap.pixels = pixels; 1.224 + pixmap.pixelsz = pixel_size(fmt); 1.225 + 1.226 + if(img_save(&pixmap, fname) == -1) { 1.227 + return false; 1.228 + } 1.229 + return true; 1.230 +} 1.231 + 1.232 +static int pixel_elements(Image::Format fmt) 1.233 +{ 1.234 + switch(fmt) { 1.235 + case Image::FMT_GREY: 1.236 + case Image::FMT_GREY_FLOAT: 1.237 + return 1; 1.238 + 1.239 + case Image::FMT_RGB: 1.240 + case Image::FMT_RGB_FLOAT: 1.241 + return 3; 1.242 + 1.243 + case Image::FMT_RGBA: 1.244 + case Image::FMT_RGBA_FLOAT: 1.245 + return 4; 1.246 + 1.247 + default: 1.248 + break; 1.249 + } 1.250 + return 0; 1.251 +} 1.252 + 1.253 +static int elem_size(Image::Format fmt) 1.254 +{ 1.255 + switch(fmt) { 1.256 + case Image::FMT_GREY: 1.257 + case Image::FMT_RGB: 1.258 + case Image::FMT_RGBA: 1.259 + return 1; 1.260 + 1.261 + case Image::FMT_GREY_FLOAT: 1.262 + case Image::FMT_RGB_FLOAT: 1.263 + case Image::FMT_RGBA_FLOAT: 1.264 + return sizeof(float); 1.265 + 1.266 + default: 1.267 + break; 1.268 + } 1.269 + return 0; 1.270 +} 1.271 + 1.272 +static int pixel_size(Image::Format fmt) 1.273 +{ 1.274 + return elem_size(fmt) * pixel_elements(fmt); 1.275 +}