From b9ff5840a617ec836f2d09bb0f04d60e5c3b8f67 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 28 Dec 2011 13:29:33 +0000 Subject: 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. --- source/blender/imbuf/IMB_imbuf.h | 14 + source/blender/imbuf/intern/divers.c | 750 +++++++++++++++++++++-------------- 2 files changed, 465 insertions(+), 299 deletions(-) (limited to 'source/blender/imbuf') 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); - } } } -- cgit v1.2.3