Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-12-28 17:29:33 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-12-28 17:29:33 +0400
commitb9ff5840a617ec836f2d09bb0f04d60e5c3b8f67 (patch)
tree8a196777f4ee32e3ee089c12b667caa2c82dec75 /source/blender/imbuf
parent1f02209957fc8afde957b48f1be41fc399a725b0 (diff)
Code refactoring: add unified image buffer functions for doing float => byte,
byte => float, float => float, byte => byte conversions with profile, dither and predivide. Previously code for this was spread out too much. There should be no functional changes, this is so the predivide/table/dither patches can work correctly.
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/IMB_imbuf.h14
-rw-r--r--source/blender/imbuf/intern/divers.c750
2 files changed, 465 insertions, 299 deletions
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 39282335f46..7f99fc3ffc7 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -378,6 +378,20 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile);
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
void IMB_color_to_bw(struct ImBuf *ibuf);
+/* converting pixel buffers */
+void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from,
+ int channels_from, int dither, int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from);
+void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from,
+ int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from);
+void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
+ int channels_from, int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from);
+void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from,
+ int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from);
+
/**
* Change the ordering of the color bytes pointed to by rect from
* rgba to abgr. size * 4 color bytes are reordered.
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 8c5f2dcafd6..8a3f6358c5b 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -42,10 +42,10 @@
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
-#include "BKE_colortools.h"
-
#include "MEM_guardedalloc.h"
+/**************************** Interlace/Deinterlace **************************/
+
void IMB_de_interlace(struct ImBuf *ibuf)
{
struct ImBuf * tbuf1, * tbuf2;
@@ -100,347 +100,498 @@ void IMB_interlace(struct ImBuf *ibuf)
}
}
+/************************* Generic Buffer Conversion *************************/
-/* assume converting from linear float to sRGB byte */
-void IMB_rect_from_float(struct ImBuf *ibuf)
+MINLINE void byte_to_float_v4(float f[4], const uchar b[4])
{
- /* quick method to convert floatbuf to byte */
- float *tof = (float *)ibuf->rect_float;
-// int do_dither = ibuf->dither != 0.f;
- float dither= ibuf->dither / 255.0f;
- float srgb[4];
- int i, channels= ibuf->channels;
- short profile= ibuf->profile;
- unsigned char *to = (unsigned char *) ibuf->rect;
-
- if(tof==NULL) return;
- if(to==NULL) {
- imb_addrectImBuf(ibuf);
- to = (unsigned char *) ibuf->rect;
- }
-
- if(channels==1) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++)
- to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]);
+ f[0] = b[0] * (1.0f/255.0f);
+ f[1] = b[1] * (1.0f/255.0f);
+ f[2] = b[2] * (1.0f/255.0f);
+ f[3] = b[3] * (1.0f/255.0f);
+}
+
+MINLINE void float_to_byte_v4(uchar b[4], const float f[4])
+{
+ F4TOCHAR4(f, b);
+}
+
+MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], float dither)
+{
+ float tmp[4] = {f[0]+dither, f[1]+dither, f[2]+dither, f[3]+dither};
+ float_to_byte_v4(b, tmp);
+}
+
+/* float to byte pixels, output 4-channel RGBA */
+void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
+ int channels_from, int dither, int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from)
+{
+ float tmp[4];
+ float dither_fac = dither/255.0f;
+ int x, y;
+
+ /* we need valid profiles */
+ BLI_assert(profile_to != IB_PROFILE_NONE);
+ BLI_assert(profile_from != IB_PROFILE_NONE);
+
+ if(channels_from==1) {
+ /* single channel input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y;
+ uchar *to = rect_to + stride_to*y*4;
+
+ for(x = 0; x < width; x++, from++, to+=4)
+ to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
+ }
}
- else if (profile == IB_PROFILE_LINEAR_RGB) {
- if(channels == 3) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
- srgb[0]= linearrgb_to_srgb(tof[0]);
- srgb[1]= linearrgb_to_srgb(tof[1]);
- srgb[2]= linearrgb_to_srgb(tof[2]);
-
- to[0] = FTOCHAR(srgb[0]);
- to[1] = FTOCHAR(srgb[1]);
- to[2] = FTOCHAR(srgb[2]);
- to[3] = 255;
+ else if(channels_from == 3) {
+ /* RGB input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y*3;
+ uchar *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* no color space conversion */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ F3TOCHAR3(from, to);
+ to[3] = 255;
+ }
+ }
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert from linear to sRGB */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ linearrgb_to_srgb_v3_v3(tmp, from);
+ F3TOCHAR3(tmp, to);
+ to[3] = 255;
+ }
+ }
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert from sRGB to linear */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ srgb_to_linearrgb_v3_v3(tmp, from);
+ F3TOCHAR3(tmp, to);
+ to[3] = 255;
+ }
}
}
- else if (channels == 4) {
- if (dither != 0.f) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
- const float d = (BLI_frand()-0.5f)*dither;
-
- srgb[0]= d + linearrgb_to_srgb(tof[0]);
- srgb[1]= d + linearrgb_to_srgb(tof[1]);
- srgb[2]= d + linearrgb_to_srgb(tof[2]);
- srgb[3]= d + tof[3];
-
- to[0] = FTOCHAR(srgb[0]);
- to[1] = FTOCHAR(srgb[1]);
- to[2] = FTOCHAR(srgb[2]);
- to[3] = FTOCHAR(srgb[3]);
+ }
+ else if(channels_from == 4) {
+ /* RGBA input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y*4;
+ uchar *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* no color space conversion */
+ if(dither) {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ float_to_byte_dither_v4(to, from, (BLI_frand()-0.5f)*dither_fac);
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ float_to_byte_v4(to, from);
+ }
+ }
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert from linear to sRGB */
+ if(dither && predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ linearrgb_to_srgb_predivide_v4(tmp, from);
+ float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
+ }
+ }
+ else if(dither) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ linearrgb_to_srgb_v4(tmp, from);
+ float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
+ }
+ }
+ else if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ linearrgb_to_srgb_predivide_v4(tmp, from);
+ float_to_byte_v4(to, tmp);
+ }
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ linearrgb_to_srgb_v4(tmp, from);
+ float_to_byte_v4(to, tmp);
+ }
+ }
+ }
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert from sRGB to linear */
+ if(dither && predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ srgb_to_linearrgb_predivide_v4(tmp, from);
+ float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
+ }
+ }
+ else if(dither) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ srgb_to_linearrgb_v4(tmp, from);
+ float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac);
+ }
+ }
+ else if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ srgb_to_linearrgb_predivide_v4(tmp, from);
+ float_to_byte_v4(to, tmp);
+ }
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ srgb_to_linearrgb_v4(tmp, from);
+ float_to_byte_v4(to, tmp);
+ }
}
- } else {
- floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x);
}
}
}
- else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
- if(channels==3) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) {
- to[0] = FTOCHAR(tof[0]);
- to[1] = FTOCHAR(tof[1]);
- to[2] = FTOCHAR(tof[2]);
- to[3] = 255;
+}
+
+/* byte to float pixels, input and output 4-channel RGBA */
+void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
+ int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from)
+{
+ float tmp[4];
+ int x, y;
+
+ /* we need valid profiles */
+ BLI_assert(profile_to != IB_PROFILE_NONE);
+ BLI_assert(profile_from != IB_PROFILE_NONE);
+
+ /* RGBA input */
+ for(y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from*y*4;
+ float *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* no color space conversion */
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ byte_to_float_v4(to, from);
+ }
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert sRGB to linear */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ srgb_to_linearrgb_predivide_v4(to, tmp);
+ }
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ srgb_to_linearrgb_v4(to, tmp);
+ }
}
}
- else {
- if (dither != 0.f) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
- const float d = (BLI_frand()-0.5f)*dither;
- float col[4];
-
- col[0]= d + tof[0];
- col[1]= d + tof[1];
- col[2]= d + tof[2];
- col[3]= d + tof[3];
-
- to[0] = FTOCHAR(col[0]);
- to[1] = FTOCHAR(col[1]);
- to[2] = FTOCHAR(col[2]);
- to[3] = FTOCHAR(col[3]);
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert linear to sRGB */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ linearrgb_to_srgb_predivide_v4(to, tmp);
}
- } else {
- for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) {
- to[0] = FTOCHAR(tof[0]);
- to[1] = FTOCHAR(tof[1]);
- to[2] = FTOCHAR(tof[2]);
- to[3] = FTOCHAR(tof[3]);
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ linearrgb_to_srgb_v4(to, tmp);
}
}
}
}
- /* ensure user flag is reset */
- ibuf->userflags &= ~IB_RECT_INVALID;
}
-
-
-/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
-void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h)
+/* float to float pixels, output 4-channel RGBA */
+void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
+ int channels_from, int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from)
{
- /* indices to source and destination image pixels */
- float *srcFloatPxl;
- unsigned char *dstBytePxl;
- /* buffer index will fill buffer */
- float *bufferIndex;
-
- /* convenience pointers to start of image buffers */
- float *init_srcFloatPxl = (float *)ibuf->rect_float;
- unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect;
-
- /* Dithering factor */
- float dither= ibuf->dither / 255.0f;
- /* respective attributes of image */
- short profile= ibuf->profile;
- int channels= ibuf->channels;
-
- int i, j;
-
- /*
- if called -only- from GPU_paint_update_image this test will never fail
- but leaving it here for better or worse
- */
- if(init_srcFloatPxl==NULL || (buffer == NULL)){
- return;
- }
- if(init_dstBytePxl==NULL) {
- imb_addrectImBuf(ibuf);
- init_dstBytePxl = (unsigned char *) ibuf->rect;
+ int x, y;
+
+ /* we need valid profiles */
+ BLI_assert(profile_to != IB_PROFILE_NONE);
+ BLI_assert(profile_from != IB_PROFILE_NONE);
+
+ if(channels_from==1) {
+ /* single channel input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y;
+ float *to = rect_to + stride_to*y*4;
+
+ for(x = 0; x < width; x++, from++, to+=4)
+ to[0] = to[1] = to[2] = to[3] = from[0];
+ }
}
- if(channels==1) {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x);
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) {
- dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]);
- bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0];
+ else if(channels_from == 3) {
+ /* RGB input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y*3;
+ float *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* no color space conversion */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ copy_v3_v3(to, from);
+ to[3] = 1.0f;
}
}
- }
- else if (profile == IB_PROFILE_LINEAR_RGB) {
- if(channels == 3) {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) {
- linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
- F3TOCHAR4(bufferIndex, dstBytePxl);
- bufferIndex[3]= 1.0;
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert from sRGB to linear */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ srgb_to_linearrgb_v3_v3(to, from);
+ to[3] = 1.0f;
+ }
+ }
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert from linear to sRGB */
+ for(x = 0; x < width; x++, from+=3, to+=4) {
+ linearrgb_to_srgb_v3_v3(to, from);
+ to[3] = 1.0f;
}
}
}
- else if (channels == 4) {
- if (dither != 0.f) {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
- const float d = (BLI_frand()-0.5f)*dither;
- linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
- bufferIndex[3] = srcFloatPxl[3];
- add_v4_fl(bufferIndex, d);
- F4TOCHAR4(bufferIndex, dstBytePxl);
- }
+ }
+ else if(channels_from == 4) {
+ /* RGBA input */
+ for(y = 0; y < height; y++) {
+ const float *from = rect_from + stride_from*y*4;
+ float *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* same profile, copy */
+ memcpy(to, from, sizeof(float)*4*width);
+ }
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert to sRGB to linear */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ srgb_to_linearrgb_predivide_v4(to, from);
}
- } else {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
- linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl);
- bufferIndex[3]= srcFloatPxl[3];
- F4TOCHAR4(bufferIndex, dstBytePxl);
- }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ srgb_to_linearrgb_v4(to, from);
+ }
+ }
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert from linear to sRGB */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ linearrgb_to_srgb_predivide_v4(to, from);
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4)
+ linearrgb_to_srgb_v4(to, from);
}
}
}
}
- else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) {
- if(channels==3) {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) {
- copy_v3_v3(bufferIndex, srcFloatPxl);
- F3TOCHAR4(bufferIndex, dstBytePxl);
- bufferIndex[3] = 1.0;
+}
+
+/* byte to byte pixels, input and output 4-channel RGBA */
+void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
+ int profile_to, int profile_from, int predivide,
+ int width, int height, int stride_to, int stride_from)
+{
+ float tmp[4];
+ int x, y;
+
+ /* we need valid profiles */
+ BLI_assert(profile_to != IB_PROFILE_NONE);
+ BLI_assert(profile_from != IB_PROFILE_NONE);
+
+ /* always RGBA input */
+ for(y = 0; y < height; y++) {
+ const uchar *from = rect_from + stride_from*y*4;
+ uchar *to = rect_to + stride_to*y*4;
+
+ if(profile_to == profile_from) {
+ /* same profile, copy */
+ memcpy(to, from, sizeof(uchar)*4*width);
+ }
+ else if(profile_to == IB_PROFILE_LINEAR_RGB) {
+ /* convert to sRGB to linear */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ srgb_to_linearrgb_predivide_v4(tmp, tmp);
+ float_to_byte_v4(to, tmp);
+ }
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ srgb_to_linearrgb_v4(tmp, tmp);
+ float_to_byte_v4(to, tmp);
}
}
}
- else {
- if (dither != 0.f) {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
- const float d = (BLI_frand()-0.5f)*dither;
- copy_v4_v4(bufferIndex, srcFloatPxl);
- add_v4_fl(bufferIndex,d);
- F4TOCHAR4(bufferIndex, dstBytePxl);
- }
+ else if(profile_to == IB_PROFILE_SRGB) {
+ /* convert from linear to sRGB */
+ if(predivide) {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ linearrgb_to_srgb_predivide_v4(tmp, tmp);
+ float_to_byte_v4(to, tmp);
}
- } else {
- for (j = 0; j < h; j++){
- bufferIndex = buffer + w*j*4;
- dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4;
- srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4;
- for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) {
- copy_v4_v4(bufferIndex, srcFloatPxl);
- F4TOCHAR4(bufferIndex, dstBytePxl);
- }
+ }
+ else {
+ for(x = 0; x < width; x++, from+=4, to+=4) {
+ byte_to_float_v4(tmp, from);
+ linearrgb_to_srgb_v4(tmp, tmp);
+ float_to_byte_v4(to, tmp);
}
}
}
}
+}
+
+/****************************** ImBuf Conversion *****************************/
+
+void IMB_rect_from_float(struct ImBuf *ibuf)
+{
+ int predivide= 0, profile_from;
+
+ /* verify we have a float buffer */
+ if(ibuf->rect_float==NULL)
+ return;
+
+ /* create byte rect if it didn't exist yet */
+ if(ibuf->rect==NULL)
+ imb_addrectImBuf(ibuf);
+
+ /* determine profiles */
+ if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ profile_from = IB_PROFILE_LINEAR_RGB;
+ else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
+ profile_from = IB_PROFILE_SRGB;
+ else
+ BLI_assert(0);
+
+ /* do conversion */
+ IMB_buffer_byte_from_float((uchar*)ibuf->rect, ibuf->rect_float,
+ ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+
/* ensure user flag is reset */
ibuf->userflags &= ~IB_RECT_INVALID;
}
-static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf)
+/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
+void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
{
- float *tof = fbuf;
- int i;
- unsigned char *to = (unsigned char *) ibuf->rect;
-
- for (i = ibuf->x * ibuf->y; i > 0; i--)
- {
- tof[0] = ((float)to[0])*(1.0f/255.0f);
- tof[1] = ((float)to[1])*(1.0f/255.0f);
- tof[2] = ((float)to[2])*(1.0f/255.0f);
- tof[3] = ((float)to[3])*(1.0f/255.0f);
- to += 4;
- tof += 4;
- }
-}
+ float *rect_float;
+ uchar *rect_byte;
+ int predivide= 0, profile_from;
+
+ /* verify we have a float buffer */
+ if(ibuf->rect_float==NULL || buffer==NULL)
+ return;
+ /* create byte rect if it didn't exist yet */
+ if(ibuf->rect==NULL)
+ imb_addrectImBuf(ibuf);
-static void imb_float_from_rect_linear(struct ImBuf *ibuf, float *fbuf)
-{
- float *tof = fbuf;
- int i;
- unsigned char *to = (unsigned char *) ibuf->rect;
-
- for (i = ibuf->x * ibuf->y; i > 0; i--)
- {
- tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f));
- tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f));
- tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f));
- tof[3] = ((float)to[3])*(1.0f/255.0f);
- to += 4;
- tof += 4;
- }
+ /* determine profiles */
+ if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ profile_from = IB_PROFILE_LINEAR_RGB;
+ else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
+ profile_from = IB_PROFILE_SRGB;
+ else
+ BLI_assert(0);
+
+ /* do conversion */
+ rect_float= ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
+ rect_byte= (uchar*)ibuf->rect + (x + y*ibuf->x)*4;
+
+ IMB_buffer_float_from_float(buffer, rect_float,
+ ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
+ w, h, w, ibuf->x);
+
+ IMB_buffer_byte_from_float(rect_byte, buffer,
+ 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
+ w, h, ibuf->x, w);
+
+ /* ensure user flag is reset */
+ ibuf->userflags &= ~IB_RECT_INVALID;
}
void IMB_float_from_rect(struct ImBuf *ibuf)
{
- /* quick method to convert byte to floatbuf */
- if(ibuf->rect==NULL) return;
- if(ibuf->rect_float==NULL) {
- if (imb_addrectfloatImBuf(ibuf) == 0) return;
- }
+ int predivide= 0, profile_from;
+
+ /* verify if we byte and float buffers */
+ if(ibuf->rect==NULL)
+ return;
+
+ if(ibuf->rect_float==NULL)
+ if(imb_addrectfloatImBuf(ibuf) == 0)
+ return;
- /* Float bufs should be stored linear */
-
- if (ibuf->profile != IB_PROFILE_NONE) {
- /* if the image has been given a profile then we're working
- * with color management in mind, so convert it to linear space */
- imb_float_from_rect_linear(ibuf, ibuf->rect_float);
- } else {
- imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
- }
+ /* determine profiles */
+ if(ibuf->profile == IB_PROFILE_NONE)
+ profile_from = IB_PROFILE_LINEAR_RGB;
+ else
+ profile_from = IB_PROFILE_SRGB;
+
+ /* do conversion */
+ IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect,
+ IB_PROFILE_LINEAR_RGB, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
/* no profile conversion */
void IMB_float_from_rect_simple(struct ImBuf *ibuf)
{
+ int predivide= 0;
+
if(ibuf->rect_float==NULL)
imb_addrectfloatImBuf(ibuf);
- imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float);
+
+ IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
void IMB_convert_profile(struct ImBuf *ibuf, int profile)
{
- int ok= FALSE;
- int i;
-
- unsigned char *rct= (unsigned char *)ibuf->rect;
- float *rctf= ibuf->rect_float;
+ int predivide= 0, profile_from, profile_to;
if(ibuf->profile == profile)
return;
- if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */
- if(profile == IB_PROFILE_LINEAR_RGB) { /* to */
- if(ibuf->rect_float) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
- rctf[0]= srgb_to_linearrgb(rctf[0]);
- rctf[1]= srgb_to_linearrgb(rctf[1]);
- rctf[2]= srgb_to_linearrgb(rctf[2]);
- }
- }
- if(ibuf->rect) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
- rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
- rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
- rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
- }
- }
- ok= TRUE;
- }
- }
- else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */
- if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */
- if(ibuf->rect_float) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
- rctf[0]= linearrgb_to_srgb(rctf[0]);
- rctf[1]= linearrgb_to_srgb(rctf[1]);
- rctf[2]= linearrgb_to_srgb(rctf[2]);
- }
- }
- if(ibuf->rect) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
- rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f);
- rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f);
- rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f);
- }
- }
- ok= TRUE;
- }
+ /* determine profiles */
+ if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ profile_from = IB_PROFILE_LINEAR_RGB;
+ else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
+ profile_from = IB_PROFILE_SRGB;
+ else
+ BLI_assert(0);
+
+ if(profile == IB_PROFILE_LINEAR_RGB)
+ profile_to = IB_PROFILE_LINEAR_RGB;
+ else if(ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
+ profile_to = IB_PROFILE_SRGB;
+ else
+ BLI_assert(0);
+
+ /* do conversion */
+ if(ibuf->rect_float) {
+ IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float,
+ 4, profile_to, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
- if(ok==FALSE){
- printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile);
- return;
+ if(ibuf->rect) {
+ IMB_buffer_byte_from_byte((uchar*)ibuf->rect, (uchar*)ibuf->rect,
+ profile_to, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
+ /* set new profile */
ibuf->profile= profile;
}
@@ -448,18 +599,25 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile)
* if the return */
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc)
{
- /* stupid but it works like this everywhere now */
- const short is_lin_from= (ibuf->profile != IB_PROFILE_NONE);
- const short is_lin_to= (profile != IB_PROFILE_NONE);
-
+ int predivide= 0, profile_from, profile_to;
+
+ /* determine profiles */
+ if(ibuf->profile == IB_PROFILE_NONE)
+ profile_from = IB_PROFILE_LINEAR_RGB;
+ else
+ profile_from = IB_PROFILE_SRGB;
+
+ if(profile == IB_PROFILE_NONE)
+ profile_to = IB_PROFILE_LINEAR_RGB;
+ else
+ profile_to = IB_PROFILE_SRGB;
- if(is_lin_from == is_lin_to) {
+ if(profile_from == profile_to) {
+ /* simple case, just allocate the buffer and return */
*alloc= 0;
- /* simple case, just allocate the buffer and return */
- if(ibuf->rect_float == NULL) {
+ if(ibuf->rect_float == NULL)
IMB_float_from_rect(ibuf);
- }
return ibuf->rect_float;
}
@@ -469,42 +627,36 @@ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc)
*alloc= 1;
if(ibuf->rect_float == NULL) {
- if(is_lin_to) {
- imb_float_from_rect_linear(ibuf, fbuf);
- }
- else {
- imb_float_from_rect_nonlinear(ibuf, fbuf);
- }
+ IMB_buffer_float_from_byte(fbuf, (uchar*)ibuf->rect,
+ profile_to, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else {
- if(is_lin_to) { /* lin -> nonlin */
- linearrgb_to_srgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
- }
- else { /* nonlin -> lin */
- srgb_to_linearrgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y);
- }
+ IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
+ 4, profile_to, profile_from, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
return fbuf;
}
}
+/**************************** Color to Grayscale *****************************/
/* no profile conversion */
void IMB_color_to_bw(struct ImBuf *ibuf)
{
float *rctf= ibuf->rect_float;
- unsigned char *rct= (unsigned char *)ibuf->rect;
+ uchar *rct= (uchar*)ibuf->rect;
int i;
+
if(rctf) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
+ for(i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4)
rctf[0]= rctf[1]= rctf[2]= rgb_to_grayscale(rctf);
- }
}
if(rct) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
+ for(i = ibuf->x * ibuf->y; i > 0; i--, rct+=4)
rct[0]= rct[1]= rct[2]= rgb_to_grayscale_byte(rct);
- }
}
}