forked from bartvdbraak/blender
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.
This commit is contained in:
parent
1f02209957
commit
b9ff5840a6
@ -45,9 +45,6 @@ struct rctf;
|
||||
# define DO_INLINE static inline
|
||||
#endif
|
||||
|
||||
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
|
||||
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
|
||||
|
||||
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
|
||||
void curvemapping_free(struct CurveMapping *cumap);
|
||||
struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
|
||||
|
@ -52,45 +52,6 @@
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
|
||||
void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
|
||||
{
|
||||
int x, y;
|
||||
float *rf= rectf;
|
||||
float srgb[3];
|
||||
unsigned char *rc= rectc;
|
||||
|
||||
for(y=y1; y<y2; y++) {
|
||||
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
|
||||
srgb[0]= linearrgb_to_srgb(rf[0]);
|
||||
srgb[1]= linearrgb_to_srgb(rf[1]);
|
||||
srgb[2]= linearrgb_to_srgb(rf[2]);
|
||||
|
||||
rc[0]= FTOCHAR(srgb[0]);
|
||||
rc[1]= FTOCHAR(srgb[1]);
|
||||
rc[2]= FTOCHAR(srgb[2]);
|
||||
rc[3]= FTOCHAR(rf[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w))
|
||||
{
|
||||
int x, y;
|
||||
float *rf= rectf;
|
||||
unsigned char *rc= rectc;
|
||||
|
||||
for(y=y1; y<y2; y++) {
|
||||
for(x=x1; x<x2; x++, rf+=4, rc+=4) {
|
||||
rc[0]= FTOCHAR(rf[0]);
|
||||
rc[1]= FTOCHAR(rf[1]);
|
||||
rc[2]= FTOCHAR(rf[2]);
|
||||
rc[3]= FTOCHAR(rf[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ********************************* color curve ********************* */
|
||||
|
||||
/* ***************** operations on full struct ************* */
|
||||
|
@ -34,6 +34,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "BLI_math_inline.h"
|
||||
|
||||
/* primaries */
|
||||
#define BLI_XYZ_SMPTE 0
|
||||
#define BLI_XYZ_REC709_SRGB 1
|
||||
@ -48,7 +50,7 @@ extern "C" {
|
||||
#define BLI_YCC_ITU_BT601 0
|
||||
#define BLI_YCC_ITU_BT709 1
|
||||
#define BLI_YCC_JFIF_0_255 2
|
||||
|
||||
|
||||
/******************* Conversion to RGB ********************/
|
||||
|
||||
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
|
||||
@ -70,22 +72,23 @@ unsigned int hsv_to_cpack(float h, float s, float v);
|
||||
float rgb_to_grayscale(float rgb[3]);
|
||||
unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]);
|
||||
|
||||
/***************** Profile Transformations ********************/
|
||||
/**************** Profile Transformations *****************/
|
||||
|
||||
void gamma_correct(float *c, float gamma);
|
||||
float rec709_to_linearrgb(float c);
|
||||
float linearrgb_to_rec709(float c);
|
||||
float srgb_to_linearrgb(float c);
|
||||
float linearrgb_to_srgb(float c);
|
||||
void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from);
|
||||
void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
|
||||
|
||||
/* rgba buffer convenience functions */
|
||||
void srgb_to_linearrgb_rgba_buf(float *col, int tot);
|
||||
void linearrgb_to_srgb_rgba_buf(float *col, int tot);
|
||||
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
|
||||
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
|
||||
|
||||
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]);
|
||||
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]);
|
||||
|
||||
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]);
|
||||
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]);
|
||||
|
||||
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]);
|
||||
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]);
|
||||
|
||||
/************************** Other *************************/
|
||||
|
||||
int constrain_rgb(float *r, float *g, float *b);
|
||||
@ -101,6 +104,10 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o
|
||||
void rgb_byte_to_float(const unsigned char *in, float *out);
|
||||
void rgb_float_to_byte(const float *in, unsigned char *out);
|
||||
|
||||
#ifdef BLI_MATH_INLINE_H
|
||||
#include "intern/math_color_inline.c"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -393,57 +393,6 @@ float linearrgb_to_srgb(float c)
|
||||
return 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from)
|
||||
{
|
||||
col_to[0] = srgb_to_linearrgb(col_from[0]);
|
||||
col_to[1] = srgb_to_linearrgb(col_from[1]);
|
||||
col_to[2] = srgb_to_linearrgb(col_from[2]);
|
||||
}
|
||||
|
||||
void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
|
||||
{
|
||||
col_to[0] = linearrgb_to_srgb(col_from[0]);
|
||||
col_to[1] = linearrgb_to_srgb(col_from[1]);
|
||||
col_to[2] = linearrgb_to_srgb(col_from[2]);
|
||||
}
|
||||
|
||||
/* todo, should these be moved elsewhere?, they dont belong in imbuf */
|
||||
void srgb_to_linearrgb_rgba_buf(float *col, int tot)
|
||||
{
|
||||
while(tot--) {
|
||||
srgb_to_linearrgb_v3_v3(col, col);
|
||||
col += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void linearrgb_to_srgb_rgba_buf(float *col, int tot)
|
||||
{
|
||||
while(tot--) {
|
||||
linearrgb_to_srgb_v3_v3(col, col);
|
||||
col += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
|
||||
{
|
||||
while(tot--) {
|
||||
srgb_to_linearrgb_v3_v3(col_to, col_from);
|
||||
col_to[3]= col_from[3];
|
||||
col_to += 4;
|
||||
col_from += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
|
||||
{
|
||||
while(tot--) {
|
||||
linearrgb_to_srgb_v3_v3(col_to, col_from);
|
||||
col_to[3]= col_from[3];
|
||||
col_to += 4;
|
||||
col_from += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void minmax_rgb(short c[])
|
||||
{
|
||||
if(c[0]>255) c[0]=255;
|
||||
|
109
source/blender/blenlib/intern/math_color_inline.c
Normal file
109
source/blender/blenlib/intern/math_color_inline.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: some of this file.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
* */
|
||||
|
||||
/** \file blender/blenlib/intern/math_color_inline.c
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#ifndef BLI_MATH_COLOR_INLINE_H
|
||||
#define BLI_MATH_COLOR_INLINE_H
|
||||
|
||||
/******************************** Color Space ********************************/
|
||||
|
||||
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
|
||||
{
|
||||
linear[0] = srgb_to_linearrgb(srgb[0]);
|
||||
linear[1] = srgb_to_linearrgb(srgb[1]);
|
||||
linear[2] = srgb_to_linearrgb(srgb[2]);
|
||||
}
|
||||
|
||||
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
|
||||
{
|
||||
srgb[0] = linearrgb_to_srgb(linear[0]);
|
||||
srgb[1] = linearrgb_to_srgb(linear[1]);
|
||||
srgb[2] = linearrgb_to_srgb(linear[2]);
|
||||
}
|
||||
|
||||
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
|
||||
{
|
||||
srgb_to_linearrgb_v3_v3(linear, srgb);
|
||||
linear[3] = srgb[3];
|
||||
}
|
||||
|
||||
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
|
||||
{
|
||||
linearrgb_to_srgb_v3_v3(srgb, linear);
|
||||
srgb[3] = linear[3];
|
||||
}
|
||||
|
||||
/* predivide versions to work on associated/premultipled alpha. if this should
|
||||
be done or not depends on the background the image will be composited over,
|
||||
ideally you would never do color space conversion on an image with alpha
|
||||
because it is ill defined */
|
||||
|
||||
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
|
||||
{
|
||||
float alpha, inv_alpha;
|
||||
|
||||
if(srgb[3] == 1.0f || srgb[3] == 0.0f) {
|
||||
alpha = 1.0f;
|
||||
inv_alpha = 1.0f;
|
||||
}
|
||||
else {
|
||||
alpha = srgb[3];
|
||||
inv_alpha = 1.0f/alpha;
|
||||
}
|
||||
|
||||
linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha;
|
||||
linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha;
|
||||
linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha;
|
||||
linear[3] = srgb[3];
|
||||
}
|
||||
|
||||
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
|
||||
{
|
||||
float alpha, inv_alpha;
|
||||
|
||||
if(linear[3] == 1.0f || linear[3] == 0.0f) {
|
||||
alpha = 1.0f;
|
||||
inv_alpha = 1.0f;
|
||||
}
|
||||
else {
|
||||
alpha = linear[3];
|
||||
inv_alpha = 1.0f/alpha;
|
||||
}
|
||||
|
||||
srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha;
|
||||
srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha;
|
||||
srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha;
|
||||
srgb[3] = linear[3];
|
||||
}
|
||||
|
||||
#endif /* BLI_MATH_COLOR_INLINE_H */
|
||||
|
@ -76,10 +76,10 @@
|
||||
/* called inside thread! */
|
||||
void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
|
||||
{
|
||||
float x1, y1, *rectf= NULL;
|
||||
float *rectf= NULL;
|
||||
int ymin, ymax, xmin, xmax;
|
||||
int rymin, rxmin, do_color_management;
|
||||
char *rectc;
|
||||
int rymin, rxmin, predivide, profile_from;
|
||||
unsigned char *rectc;
|
||||
|
||||
/* if renrect argument, we only refresh scanlines */
|
||||
if(renrect) {
|
||||
@ -136,50 +136,17 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
|
||||
imb_addrectImBuf(ibuf);
|
||||
|
||||
rectf+= 4*(rr->rectx*ymin + xmin);
|
||||
rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
|
||||
rectc= (unsigned char*)(ibuf->rect + ibuf->x*rymin + rxmin);
|
||||
|
||||
do_color_management = (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT));
|
||||
|
||||
/* XXX make nice consistent functions for this */
|
||||
for(y1= 0; y1<ymax; y1++) {
|
||||
float *rf= rectf;
|
||||
float srgb[3];
|
||||
char *rc= rectc;
|
||||
const float dither = ibuf->dither / 255.0f;
|
||||
if(scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT))
|
||||
profile_from= IB_PROFILE_LINEAR_RGB;
|
||||
else
|
||||
profile_from= IB_PROFILE_SRGB;
|
||||
predivide= 0;
|
||||
|
||||
/* XXX temp. because crop offset */
|
||||
if(rectc >= (char *)(ibuf->rect)) {
|
||||
for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
|
||||
/* color management */
|
||||
if(do_color_management) {
|
||||
srgb[0]= linearrgb_to_srgb(rf[0]);
|
||||
srgb[1]= linearrgb_to_srgb(rf[1]);
|
||||
srgb[2]= linearrgb_to_srgb(rf[2]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(srgb, rf);
|
||||
}
|
||||
|
||||
/* dither */
|
||||
if(dither != 0.0f) {
|
||||
const float d = (BLI_frand()-0.5f)*dither;
|
||||
|
||||
srgb[0] += d;
|
||||
srgb[1] += d;
|
||||
srgb[2] += d;
|
||||
}
|
||||
|
||||
/* write */
|
||||
rc[0]= FTOCHAR(srgb[0]);
|
||||
rc[1]= FTOCHAR(srgb[1]);
|
||||
rc[2]= FTOCHAR(srgb[2]);
|
||||
rc[3]= FTOCHAR(rf[3]);
|
||||
}
|
||||
}
|
||||
|
||||
rectf += 4*rr->rectx;
|
||||
rectc += 4*ibuf->x;
|
||||
}
|
||||
IMB_buffer_byte_from_float(rectc, rectf,
|
||||
4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
|
||||
xmax, ymax, ibuf->x, rr->rectx);
|
||||
}
|
||||
|
||||
/* ****************************** render invoking ***************** */
|
||||
|
@ -206,14 +206,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
||||
* float buffer. */
|
||||
|
||||
if(oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
|
||||
float *rctf = rr->rectf;
|
||||
int i;
|
||||
int predivide= 0; /* no alpha */
|
||||
|
||||
for (i = oglrender->sizex * oglrender->sizey; 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]);
|
||||
}
|
||||
IMB_buffer_float_from_float(rr->rectf, rr->rectf,
|
||||
4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
|
||||
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
|
||||
}
|
||||
|
||||
RE_ReleaseResult(oglrender->re);
|
||||
|
@ -45,6 +45,9 @@
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#ifndef GL_CLAMP_TO_EDGE
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#endif
|
||||
@ -563,17 +566,17 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *
|
||||
void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int UNUSED(row_w), float *rectf, int do_gamma_correct)
|
||||
{
|
||||
unsigned char *rect32;
|
||||
int profile_from= (do_gamma_correct)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
|
||||
int predivide= 0;
|
||||
|
||||
/* copy imgw-imgh to a temporal 32 bits rect */
|
||||
if(img_w<1 || img_h<1) return;
|
||||
|
||||
rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits");
|
||||
|
||||
if (do_gamma_correct) {
|
||||
floatbuf_to_srgb_byte(rectf, rect32, 0, img_w, 0, img_h, img_w);
|
||||
} else {
|
||||
floatbuf_to_byte(rectf, rect32, 0, img_w, 0, img_h, img_w);
|
||||
}
|
||||
IMB_buffer_byte_from_float(rect32, rectf,
|
||||
4, 0, IB_PROFILE_SRGB, profile_from, predivide,
|
||||
img_w, img_h, img_w, img_w);
|
||||
|
||||
glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 *************************/
|
||||
|
||||
MINLINE void byte_to_float_v4(float f[4], const uchar b[4])
|
||||
{
|
||||
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(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_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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(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(x = 0; x < width; x++, from+=4, to+=4) {
|
||||
byte_to_float_v4(tmp, from);
|
||||
linearrgb_to_srgb_v4(to, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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];
|
||||
}
|
||||
}
|
||||
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_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_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(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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(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(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 *****************************/
|
||||
|
||||
/* assume converting from linear float to sRGB byte */
|
||||
void IMB_rect_from_float(struct ImBuf *ibuf)
|
||||
{
|
||||
/* 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) {
|
||||
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);
|
||||
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]);
|
||||
}
|
||||
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 == 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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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];
|
||||
/* 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);
|
||||
|
||||
col[0]= d + tof[0];
|
||||
col[1]= d + tof[1];
|
||||
col[2]= d + tof[2];
|
||||
col[3]= d + tof[3];
|
||||
/* 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);
|
||||
|
||||
to[0] = FTOCHAR(col[0]);
|
||||
to[1] = FTOCHAR(col[1]);
|
||||
to[2] = FTOCHAR(col[2]);
|
||||
to[3] = FTOCHAR(col[3]);
|
||||
}
|
||||
} 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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)
|
||||
void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
|
||||
{
|
||||
/* indices to source and destination image pixels */
|
||||
float *srcFloatPxl;
|
||||
unsigned char *dstBytePxl;
|
||||
/* buffer index will fill buffer */
|
||||
float *bufferIndex;
|
||||
float *rect_float;
|
||||
uchar *rect_byte;
|
||||
int predivide= 0, profile_from;
|
||||
|
||||
/* 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)){
|
||||
/* verify we have a float buffer */
|
||||
if(ibuf->rect_float==NULL || buffer==NULL)
|
||||
return;
|
||||
}
|
||||
if(init_dstBytePxl==NULL) {
|
||||
|
||||
/* create byte rect if it didn't exist yet */
|
||||
if(ibuf->rect==NULL)
|
||||
imb_addrectImBuf(ibuf);
|
||||
init_dstBytePxl = (unsigned char *) ibuf->rect;
|
||||
}
|
||||
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 (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 (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 {
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void imb_float_from_rect_nonlinear(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] = ((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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Float bufs should be stored linear */
|
||||
int predivide= 0, profile_from;
|
||||
|
||||
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);
|
||||
}
|
||||
/* verify if we byte and float buffers */
|
||||
if(ibuf->rect==NULL)
|
||||
return;
|
||||
|
||||
if(ibuf->rect_float==NULL)
|
||||
if(imb_addrectfloatImBuf(ibuf) == 0)
|
||||
return;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -606,7 +606,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
|
||||
RenderData *rd= data;
|
||||
bNodePreview *preview= node->preview;
|
||||
int xsize, ysize;
|
||||
int color_manage= rd->color_mgt_flag & R_COLOR_MANAGEMENT;
|
||||
int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
|
||||
int predivide= 0;
|
||||
int dither= 0;
|
||||
unsigned char *rect;
|
||||
|
||||
if(preview && stackbuf) {
|
||||
@ -633,10 +635,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
|
||||
/* convert to byte for preview */
|
||||
rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect");
|
||||
|
||||
if(color_manage)
|
||||
floatbuf_to_srgb_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize);
|
||||
else
|
||||
floatbuf_to_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize);
|
||||
IMB_buffer_byte_from_float(rect, cbuf->rect,
|
||||
4, dither, IB_PROFILE_SRGB, profile_from, predivide,
|
||||
xsize, ysize, xsize, xsize);
|
||||
|
||||
free_compbuf(cbuf);
|
||||
if(stackbuf_use!=stackbuf)
|
||||
|
@ -62,6 +62,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= {
|
||||
float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
|
||||
{
|
||||
float *rect;
|
||||
int predivide= 0;
|
||||
|
||||
*alloc= FALSE;
|
||||
|
||||
@ -71,7 +72,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
|
||||
}
|
||||
else {
|
||||
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
|
||||
srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
|
||||
|
||||
IMB_buffer_float_from_float(rect, ibuf->rect_float,
|
||||
4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
|
||||
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
|
||||
|
||||
*alloc= TRUE;
|
||||
}
|
||||
}
|
||||
@ -81,7 +86,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
|
||||
}
|
||||
else {
|
||||
rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
|
||||
linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y);
|
||||
|
||||
IMB_buffer_float_from_float(rect, ibuf->rect_float,
|
||||
4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
|
||||
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
|
||||
|
||||
*alloc= TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1149,32 +1149,17 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
|
||||
|
||||
RE_AcquireResultImage(re, &rres);
|
||||
|
||||
if(rres.rect32)
|
||||
if(rres.rect32) {
|
||||
memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty);
|
||||
}
|
||||
else if(rres.rectf) {
|
||||
float *fp= rres.rectf;
|
||||
int tot= rres.rectx*rres.recty;
|
||||
char *cp= (char *)rect;
|
||||
|
||||
if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
|
||||
/* Finally convert back to sRGB rendered image */
|
||||
for(;tot>0; tot--, cp+=4, fp+=4) {
|
||||
cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0]));
|
||||
cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1]));
|
||||
cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2]));
|
||||
cp[3] = FTOCHAR(fp[3]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Color management is off : no conversion necessary */
|
||||
for(;tot>0; tot--, cp+=4, fp+=4) {
|
||||
cp[0] = FTOCHAR(fp[0]);
|
||||
cp[1] = FTOCHAR(fp[1]);
|
||||
cp[2] = FTOCHAR(fp[2]);
|
||||
cp[3] = FTOCHAR(fp[3]);
|
||||
}
|
||||
}
|
||||
int profile_from= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
|
||||
int predivide= 0;
|
||||
int dither= 0;
|
||||
|
||||
IMB_buffer_byte_from_float((unsigned char*)rect, rres.rectf,
|
||||
4, dither, IB_PROFILE_SRGB, profile_from, predivide,
|
||||
rres.rectx, rres.recty, rres.rectx, rres.rectx);
|
||||
}
|
||||
else
|
||||
/* else fill with black */
|
||||
@ -2567,24 +2552,18 @@ static void do_render_seq(Render * re)
|
||||
|
||||
if(ibuf) {
|
||||
if(ibuf->rect_float) {
|
||||
/* color management: when off ensure rectf is non-lin, since thats what the internal
|
||||
* render engine delivers */
|
||||
int profile_to= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
|
||||
int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
|
||||
int predivide= 0;
|
||||
|
||||
if (!rr->rectf)
|
||||
rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
|
||||
|
||||
/* color management: when off ensure rectf is non-lin, since thats what the internal
|
||||
* render engine delivers */
|
||||
if(re->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
|
||||
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
|
||||
memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
|
||||
else
|
||||
srgb_to_linearrgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty);
|
||||
|
||||
}
|
||||
else {
|
||||
if(ibuf->profile != IB_PROFILE_LINEAR_RGB)
|
||||
memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
|
||||
else
|
||||
linearrgb_to_srgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty);
|
||||
}
|
||||
IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
|
||||
4, profile_to, profile_from, predivide,
|
||||
rr->rectx, rr->recty, rr->rectx, rr->rectx);
|
||||
|
||||
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
|
||||
can hang around when sequence render has rendered a 32 bits one before */
|
||||
|
Loading…
Reference in New Issue
Block a user