diff --git a/rtengine/LUT.h b/rtengine/LUT.h new file mode 100644 index 000000000..c63b99112 --- /dev/null +++ b/rtengine/LUT.h @@ -0,0 +1,177 @@ +/* + * LUT.h + * This file is part of RawTherapee. + * + * Copyright (c) 2011 Jan Rinze Peterzon (janrinze@gmail.com) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +/* + * Declaration of flexible Lookup Tables + * + * Usage: + * + * LUT name (size); + * LUT name (size, flags); + * + * creates an array which is valid within the normal C/C++ scope "{ ... }" + * + * access to elements is a simple as: + * + * LUT my_lut (10); + * float value = my_lut[3]; + * float value = my_lut[2.5]; // this will interpolate + * + * when using a float type index it will interpolate the lookup values + * + * extra setting in flags: (clipping is set by default) + * LUT_CLIP_ABOVE + * LUT_CLIP_BELOW + * + * example: + * LUT my_lut (10,LUT_CLIP_BELOW); + * float value = my_lut[22.5]; // this will extrapolate + * float value = my_lut[-22.5]; // this will not extrapolate + * + * LUT my_lut (10,0); // this will extrapolate on either side + * + * shotcuts: + * + * LUTf stands for LUT + * LUTi stands for LUT + * LUTu stands for LUT + */ + +#ifndef LUT_H_ +#define LUT_H_ + +// bit representations of flags +#define LUT_CLIP_BELOW 1 +#define LUT_CLIP_ABOVE 2 + +#define LUTf LUT +#define LUTi LUT +#define LUTu LUT + +template +class LUT { +private: + // list of variables ordered to improve cache speed + unsigned int maxs; + T * data; + unsigned int clip, size, owner; +public: + LUT(int s, int flags = 0xfffffff) { + clip = flags; + data = new T[s]; + owner = 1; + size = s; + maxs=size-2; + } + void operator ()(int s, int flags = 0xfffffff) { + if (owner&&data) + delete[] data; + clip = flags; + data = new T[s]; + owner = 1; + size = s; + maxs=size-2; + } + + LUT(int s, T * source) { + data = new T[s]; + owner = 1; + size = s; + maxs=size-2; + for (int i = 0; i < s; i++) { + data[i] = source[i]; + } + } + + LUT(void) { + data = NULL; + owner = 1; + size = 0; + maxs=0; + } + + ~LUT() { + if (owner) + delete[] data; + } + + LUT & operator=(const LUT &rhs) { + if (this != &rhs) { + if (rhs.size>this->size) + { + delete [] this->data; + this->data=NULL; + } + if (this->data==NULL) this->data=new T[rhs.size]; + this->clip=rhs.clip; + this->owner=1; + memcpy(this->data,rhs.data,rhs.size*sizeof(T)); + this->size=rhs.size; + this->maxs=this->size-2; + } + + return *this; + } + // use with integer indices + T& operator[](int index) { + if (((unsigned int)index) maxs) { + if (idx<0) + { + if (clip & LUT_CLIP_BELOW) + return data[0]; + idx=0; + } + else + { + if (clip & LUT_CLIP_ABOVE) + return data[size - 1]; + idx =maxs; + } + } + float diff = index - (float) idx; + T p1 = data[idx]; + T p2 = data[idx + 1]-p1; + return (p1 + p2*diff); + } + + operator bool (void) + { + return size>0; + } + + void clear(void) { + memset(data, 0, size * sizeof(T)); + } +}; + +#endif /* LUT_H_ */ diff --git a/rtengine/array2D.h b/rtengine/array2D.h new file mode 100644 index 000000000..06ec053b7 --- /dev/null +++ b/rtengine/array2D.h @@ -0,0 +1,265 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2011 Jan Rinze Peterzon (janrinze@gmail.com) + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +/* + * Declaration of flexible 2D arrays + * + * Usage: + * + * array2D name (X-size,Y-size); + * array2D name (X-size,Y-size type ** data); + * + * creates an array which is valid within the normal C/C++ scope "{ ... }" + * + * access to elements is a simple as: + * + * array2D my_array (10,10); // creates 10x10 array of floats + * value = my_array[3][5]; + * my_array[4][6]=value; + * + * or copy an existing 2D array + * + * float ** mydata; + * array2D my_array (10,10,mydata); + * + * + * Useful extra pointers + * + * ** my_array gives access to the pointer for access with [][] + * * my_array gives access to the flat stored data. + * + * Advanced usage: + * array2D my_array ; // empty container. + * my_array(10,10) ; // resize to 10x10 array + * my_array(10,10,ARRAY2D_CLEAR_DATA) ; // resize to 10x10 and clear data + * my_array(10,10,ARRAY2D_CLEAR_DATA|ARRAY2D_LOCK_DATA) ; same but set a lock on changes + * + * !! locked arrays cannot be resized and cannot be unlocked again !! + */ +#ifndef ARRAY2D_H_ +#define ARRAY2D_H_ +#include // for raise() +// flags for use +#define ARRAY2D_LOCK_DATA 1 +#define ARRAY2D_CLEAR_DATA 2 +#define ARRAY2D_BYREFERENCE 4 +#define ARRAY2D_VERBOSE 8 + +template +class array2D { + +private: + int x, y, owner, flags; + T ** ptr; + T * data; + bool lock; // useful lock to ensure data is not changed anymore. + void ar_realloc(int w, int h) { + if ((ptr) && ((h > y) || (4 * h < y))) { + delete[] ptr; + ptr = NULL; + } + if ((data) && (((h * w) > (x * y)) || ((h * w) < ((x * y) / 4)))) { + delete[] data; + data = NULL; + } + if (ptr == NULL) + ptr = new T*[h]; + if (data == NULL) + data = new T[h * w]; + + x = w; + y = h; + for (int i = 0; i < h; i++) + ptr[i] = data + w * i; + owner = 1; + } +public: + + // use as empty declaration, resize before use! + // very useful as a member object + array2D() : + x(0), y(0), owner(0), data(NULL), ptr(NULL), lock(0) { + printf("got empty array2D init\n"); + } + + // creator type1 + array2D(int w, int h, unsigned int flgs = 0) { + flags = flgs; + lock = flags & ARRAY2D_LOCK_DATA; + data = new T[h * w]; + owner = 1; + x = w; + y = h; + ptr = new T*[h]; + for (int i = 0; i < h; i++) + ptr[i] = data + i * w; + if (flags & ARRAY2D_CLEAR_DATA) + memset(data, 0, w * h * sizeof(T)); + } + + // creator type 2 + array2D(int w, int h, T ** source, unsigned int flgs = 0) { + flags = flgs; + //if (lock) { printf("array2D attempt to overwrite data\n");raise(SIGSEGV);} + lock |= flags & ARRAY2D_LOCK_DATA; + // when by reference + // TODO: improve this code with ar_realloc() + owner = (flags & ARRAY2D_BYREFERENCE) ? 0 : 1; + if (owner) + data = new T[h * w]; + else + data = NULL; + x = w; + y = h; + ptr = new T*[h]; + for (int i = 0; i < h; i++) { + if (owner) { + ptr[i] = data + i * w; + for (int j = 0; j < w; j++) + ptr[i][j] = source[i][j]; + } else + ptr[i] = source[i]; + } + } + + // destructor + ~array2D() { + + if (flags & ARRAY2D_VERBOSE) + printf(" deleting array2D size %dx%d \n", x, y); + + if ((owner) && (data)) + delete[] data; + if (ptr) + delete[] ptr; + } + + // use with indices + T * operator[](size_t index) { + return ptr[index]; + } + + // use as pointer to T** + operator T**() { + return ptr; + } + + // use as pointer to data + operator T*() { + // only if owner this will return a valid pointer + return data; + } + + + // useful within init of parent object + // or use as resize of 2D array + void operator()(int w, int h, unsigned int flgs = 0) { + flags = flgs; + if (flags & ARRAY2D_VERBOSE) { + printf("got init request %dx%d flags=%d\n", w, h, flags); + printf("previous was data %p ptr %p \n", data, ptr); + } + if (lock) // our object was locked so don't allow a change. + { + printf("got init request but object was locked!\n"); + raise( SIGSEGV); + } + lock = flags & ARRAY2D_LOCK_DATA; + + ar_realloc(w,h); + if (flags & ARRAY2D_CLEAR_DATA) + memset(data, 0, w * h * sizeof(T)); + } + + // import from flat data + void operator()(int w, int h, T* copy, unsigned int flgs = 0) { + flags = flgs; + if (flags & ARRAY2D_VERBOSE) { + printf("got init request %dx%d flags=%d\n", w, h, flags); + printf("previous was data %p ptr %p \n", data, ptr); + } + if (lock) // our object was locked so don't allow a change. + { + printf("got init request but object was locked!\n"); + raise( SIGSEGV); + } + lock = flags & ARRAY2D_LOCK_DATA; + + ar_realloc(w,h); + memcpy(data, copy, w * h * sizeof(T)); + } + int width() { + return x; + } + int height() { + return y; + } + + operator bool() { + return (x > 0 && y > 0); + } + + array2D & operator=( array2D & rhs) { + if (this != &rhs) + + { + if (!owner) // we can only copy same size data + { + if ((x != rhs.x) || (y != rhs.y)) { + printf(" assignment error in array2D\n"); + printf(" sizes differ and not owner\n"); + raise( SIGSEGV); + } + + } else { + ar_realloc(rhs.x, rhs.y); + } + // we could have been created from a different + // array format where each row is created by 'new' + for (int i=0;i +class multi_array2D { +private: + array2D list[num]; + +public: + multi_array2D(int x, int y, int flags = 0) { + for (int i = 0; i < num; i++) + list[i](x, y, flags | ARRAY2D_VERBOSE); + } + + ~multi_array2D() { + printf("trying to delete the list of array2D objects\n"); + } + + array2D & operator[](size_t index) { + if (index < 0 || index >= num) { + printf("index %d is out of range[0..%d]", index, num - 1); + raise( SIGSEGV); + } + return list[index]; + } +}; +#endif /* array2D_H_ */ diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc new file mode 100644 index 000000000..7e6bf48bd --- /dev/null +++ b/rtengine/imagefloat.cc @@ -0,0 +1,237 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include +#include +#include +#include + +using namespace rtengine; + +Imagefloat::Imagefloat () + : unaligned (NULL), data (NULL), r (NULL), g (NULL), b (NULL){ +} + +Imagefloat::Imagefloat (int w, int h) + : unaligned (NULL), width(w), height (h), data (NULL), r (NULL), g (NULL), b (NULL) { + + allocate (w, h); +} + +Imagefloat::~Imagefloat () { + + if (data!=NULL) { + delete [] data; + delete [] r; + delete [] g; + delete [] b; + } +} + +void Imagefloat::allocate (int W, int H) { + + width=W; + height=H; + + if (data!=NULL) { + delete [] data; + delete [] r; + delete [] g; + delete [] b; + } + + /* + int lsize = width + 8 - width % 8; + unaligned = new unsigned char[16 + 3 * lsize * sizeof(float) * height]; + memset(unaligned, 0, (16 + 3 * lsize * sizeof(float) * height) * sizeof(unsigned char)); + + uintptr_t poin = (uintptr_t)unaligned + 16 - (uintptr_t)unaligned % 16; + data = (float*) (poin); + */ + r = new float*[height]; + g = new float*[height]; + b = new float*[height]; + + data = new float[W*H*3]; + rowstride = W; + planestride = rowstride * H; + + float * redstart = data + 0*planestride; + float * greenstart = data + 1*planestride; + float * bluestart = data + 2*planestride; + + + for (int i=0; ir[i], r[i], width*sizeof(float)); + memcpy (cp->g[i], g[i], width*sizeof(float)); + memcpy (cp->b[i], b[i], width*sizeof(float)); + } + + return cp; +} + +Imagefloat* Imagefloat::rotate (int deg) { + + if (deg==90) { + Imagefloat* result = new Imagefloat (height, width); + for (int i=0; ir[i][j] = r[height-1-j][i]; + result->g[i][j] = g[height-1-j][i]; + result->b[i][j] = b[height-1-j][i]; + } + return result; + } + else if (deg==270) { + Imagefloat* result = new Imagefloat (height, width); + for (int i=0; ir[i][j] = r[j][width-1-i]; + result->g[i][j] = g[j][width-1-i]; + result->b[i][j] = b[j][width-1-i]; + } + return result; + } + else if (deg==180) { + Imagefloat* result = new Imagefloat (width, height); + for (int i=0; ir[i][j] = r[height-1-i][width-1-j]; + result->g[i][j] = g[height-1-i][width-1-j]; + result->b[i][j] = b[height-1-i][width-1-j]; + } + return result; + } + else + return NULL; +} + +Imagefloat* Imagefloat::hflip () { + + Imagefloat* result = new Imagefloat (width, height); + for (int i=0; ir[i][j] = r[i][width-1-j]; + result->g[i][j] = g[i][width-1-j]; + result->b[i][j] = b[i][width-1-j]; + } + return result; + +} + +Imagefloat* Imagefloat::vflip () { + + Imagefloat* result = new Imagefloat (width, height); + for (int i=0; ir[i][j] = r[height-1-i][j]; + result->g[i][j] = g[height-1-i][j]; + result->b[i][j] = b[height-1-i][j]; + } + return result; + +} + +/*Imagefloat* Imagefloat::resize (int nw, int nh, TypeInterpolation interp) { + + if (interp == TI_Nearest) { + Imagefloat* res = new Imagefloat (nw, nh); + for (int i=0; ir[i][j] = r[ri][ci]; + res->g[i][j] = g[ri][ci]; + res->b[i][j] = b[ri][ci]; + } + } + return res; + } + else if (interp == TI_Bilinear) { + Imagefloat* res = new Imagefloat (nw, nh); + for (int i=0; i=height) sy = height-1; + double dy = (double)i*height/nh - sy; + int ny = sy+1; + if (ny>=height) ny = sy; + for (int j=0; j=width) sx = width; + double dx = (double)j*width/nw - sx; + int nx = sx+1; + if (nx>=width) nx = sx; + res->r[i][j] = r[sy][sx]*(1-dx)*(1-dy) + r[sy][nx]*dx*(1-dy) + r[ny][sx]*(1-dx)*dy + r[ny][nx]*dx*dy; + res->g[i][j] = g[sy][sx]*(1-dx)*(1-dy) + g[sy][nx]*dx*(1-dy) + g[ny][sx]*(1-dx)*dy + g[ny][nx]*dx*dy; + res->b[i][j] = b[sy][sx]*(1-dx)*(1-dy) + b[sy][nx]*dx*(1-dy) + b[ny][sx]*(1-dx)*dy + b[ny][nx]*dx*dy; + } + } + return res; + } + return NULL; +}*/ + +Image8* +Imagefloat::to8() const +{ + Image8* img8 = new Image8(width,height); + for ( int h = 0; h < height; ++h ) + { + for ( int w = 0; w < width; ++w ) + { + img8->r(h,w,((int)r[h][w]) >> 8); + img8->g(h,w,((int)g[h][w]) >> 8); + img8->b(h,w,((int)b[h][w]) >> 8); + } + } + return img8; +} + +Image16* +Imagefloat::to16() const +{ + Image16* img16 = new Image16(width,height); + for ( int h = 0; h < height; ++h ) + { + for ( int w = 0; w < width; ++w ) + { + img16->r[h][w] = ((int)r[h][w]) ; + img16->g[h][w] = ((int)g[h][w]) ; + img16->b[h][w] = ((int)b[h][w]) ; + } + } + return img16; +} + + diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h new file mode 100644 index 000000000..8ddf953f6 --- /dev/null +++ b/rtengine/imagefloat.h @@ -0,0 +1,94 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +// +// A class representing a 16 bit rgb image with separate planes and 16 byte aligned data +// +#ifndef _IMAGEFLOAT_ +#define _IMAGEFLOAT_ + +#include +#include +//#include + +namespace rtengine { + +//enum TypeInterpolation { TI_Nearest, TI_Bilinear }; + +class Image8; +class Image16; + +class Imagefloat : public ImageIO, public IImagefloat { + + private: + unsigned char* unaligned; + + public: + int rowstride; + int planestride; + + int width; + int height; + + float* data; + + float** r; + float** g; + float** b; + + + Imagefloat (); + Imagefloat (int width, int height); + ~Imagefloat (); + + Imagefloat* copy (); + + Image8* to8() const; + Image16* to16() const; + + + Imagefloat* rotate (int deg); + Imagefloat* hflip (); + Imagefloat* vflip (); + //Imagefloat* resize (int nw, int nh, TypeInterpolation interp); + + virtual int getW () { return width; } + virtual int getH () { return height; } + virtual void allocate (int width, int height); + virtual int getBPS () { return 8*sizeof(float); } + //virtual void getScanline (int row, unsigned char* buffer, int bps); + //virtual void setScanline (int row, unsigned char* buffer, int bps); + + // functions inherited from IImagefloat: + virtual int getWidth () { return width; } + virtual int getHeight () { return height; } + virtual Glib::Mutex& getMutex () { return mutex (); } + virtual cmsHPROFILE getProfile () { return getEmbeddedProfile (); } + virtual int getBitsPerPixel () { return 16; } + virtual int saveToFile (Glib::ustring fname) { return save (fname); } + virtual int saveAsPNG (Glib::ustring fname, int compression = -1, int bps = -1) { return savePNG (fname, compression, bps); } + virtual int saveAsJPEG (Glib::ustring fname, int quality = 100) { return saveJPEG (fname, quality); } + virtual int saveAsTIFF (Glib::ustring fname, int bps = -1, bool uncompressed = false) { return saveTIFF (fname, bps, uncompressed); } + virtual void setSaveProgressListener (ProgressListener* pl) { return setProgressListener (pl); } + virtual void free () { delete this; } + virtual float** getRPlane () { return r; } + virtual float** getGPlane () { return g; } + virtual float** getBPlane () { return b; } +}; +}; +#endif