62#define RGBE_VALID_PROGRAMTYPE 0x01
63#define RGBE_VALID_GAMMA 0x02
64#define RGBE_VALID_EXPOSURE 0x04
67#define RGBE_RETURN_SUCCESS 0
68#define RGBE_RETURN_FAILURE -1
70#define RGBE_DATA_RED 0
71#define RGBE_DATA_GREEN 1
72#define RGBE_DATA_BLUE 2
74#define RGBE_DATA_SIZE 3
87 switch(rgbe_error_code)
90 perror(
"RGBE read error");
93 perror(
"RGBE write error");
96 fprintf(stderr,
"RGBE bad file format: %s\n", msg);
100 fprintf(stderr,
"RGBE error: %s\n", msg);
109float2rgbe(
unsigned char rgbe[4],
float red,
float green,
float blue)
119 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
123 v = frexp(
v,&e) * 256.0/
v;
124 rgbe[0] = (
unsigned char) (red *
v);
125 rgbe[1] = (
unsigned char) (green *
v);
126 rgbe[2] = (
unsigned char) (blue *
v);
127 rgbe[3] = (
unsigned char) (e + 128);
135static void rgbe2float(
float *red,
float *green,
float *blue,
unsigned char rgbe[4])
139 const float f = ldexpf(1.0f, rgbe[3] - (
int)(128 + 8));
141 *green = rgbe[1] *
f;
145 *red = *green = *blue = 0.0f;
152 char *programtype =
"RGBE";
156 if (fprintf(fp,
"#?%s\n",programtype) < 0)
161 if (fprintf(fp,
"GAMMA=%g\n",info->
gamma) < 0)
166 if (fprintf(fp,
"EXPOSURE=%g\n",info->
exposure) < 0)
169 if (fprintf(fp,
"FORMAT=32-bit_rle_rgbe\n\n") < 0)
171 if (fprintf(fp,
"-Y %d +X %d\n",
height,
width) < 0)
187 static const float default_primaries[] = { 0.640, 0.330, 0.290, 0.600, 0.150, 0.060, 0.333, 0.333 };
191 if((buf[0] !=
'#') || (buf[1] !=
'?'))
202 if((buf[
i + 2] == 0) || isspace(buf[
i + 2]))
break;
208 gboolean format_is_rgbe =
FALSE;
211 if((buf[0] == 0) || (buf[0] ==
'\n'))
213 else if(strcmp(buf,
"FORMAT=32-bit_rle_rgbe\n") == 0)
214 format_is_rgbe =
TRUE;
217 if(g_str_has_prefix(buf,
"GAMMA="))
219 char *startptr = buf + strlen(
"GAMMA="), *endptr;
220 float tmp = g_ascii_strtod(startptr, &endptr);
221 if(startptr != endptr)
227 else if(g_str_has_prefix(buf,
"EXPOSURE="))
229 char *startptr = buf + strlen(
"EXPOSURE="), *endptr;
230 float tmp = g_ascii_strtod(startptr, &endptr);
231 if(startptr != endptr)
237 else if(g_str_has_prefix(buf,
"PRIMARIES="))
240 gboolean all_ok =
TRUE;
241 char *startptr = buf + strlen(
"PRIMARIES="), *endptr;
242 for(
int i = 0;
i < 8;
i++)
244 tmp[
i] = g_ascii_strtod(startptr, &endptr);
245 if(startptr == endptr)
260 while(!strcmp(buf,
"\n"))
271int RGBE_WritePixels(FILE *fp,
float *data,
int numpixels)
273 unsigned char rgbe[4];
275 while (numpixels-- > 0)
280 if (fwrite(rgbe,
sizeof(rgbe), 1, fp) < 1)
290 unsigned char rgbe[4];
292 while(numpixels-- > 0)
307static int RGBE_WriteBytes_RLE(FILE *fp,
unsigned char *data,
int numbytes)
309#define MINRUNLENGTH 4
310 int cur, beg_run, run_count, old_run_count, nonrun_count;
311 unsigned char buf[2];
314 while(cur < numbytes)
318 run_count = old_run_count = 0;
319 while((run_count < MINRUNLENGTH) && (beg_run < numbytes))
321 beg_run += run_count;
322 old_run_count = run_count;
324 while((data[beg_run] == data[beg_run + run_count])
325 && (beg_run + run_count < numbytes) && (run_count < 127))
329 if ((old_run_count > 1)&&(old_run_count == beg_run - cur))
331 buf[0] = 128 + old_run_count;
333 if (fwrite(buf,
sizeof(buf[0])*2,1,fp) < 1)
340 nonrun_count = beg_run - cur;
341 if (nonrun_count > 128)
343 buf[0] = nonrun_count;
344 if (fwrite(buf,
sizeof(buf[0]),1,fp) < 1)
346 if (fwrite(&data[cur],
sizeof(data[0])*nonrun_count,1,fp) < 1)
351 if (run_count >= MINRUNLENGTH)
353 buf[0] = 128 + run_count;
354 buf[1] = data[beg_run];
355 if (fwrite(buf,
sizeof(buf[0])*2,1,fp) < 1)
364int RGBE_WritePixels_RLE(FILE *fp,
float *data,
int scanline_width,
367 unsigned char rgbe[4];
368 unsigned char *buffer;
371 if ((scanline_width < 8)||(scanline_width > 0x7fff))
373 return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
374 buffer = (
unsigned char *)malloc(
sizeof(
unsigned char)*4*scanline_width);
377 return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
378 while(num_scanlines-- > 0)
382 rgbe[2] = scanline_width >> 8;
383 rgbe[3] = scanline_width & 0xFF;
384 if (fwrite(rgbe,
sizeof(rgbe), 1, fp) < 1)
389 for(
i=0;
i<scanline_width;
i++)
394 buffer[
i+scanline_width] = rgbe[1];
395 buffer[
i+2*scanline_width] = rgbe[2];
396 buffer[
i+3*scanline_width] = rgbe[3];
403 if ((err = RGBE_WriteBytes_RLE(fp,&buffer[
i*scanline_width],
418 unsigned char rgbe[4], *scanline_buffer, *ptr_end;
420 unsigned char buf[2];
422 if((scanline_width < 8) || (scanline_width > 0x7fff))
424 scanline_buffer = NULL;
426 while(num_scanlines > 0)
428 if(fread(rgbe,
sizeof(rgbe), 1, fp) < 1)
433 if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80))
436 rgbe2float(&data[0], &data[1], &data[2], rgbe);
441 if((((
int)rgbe[2]) << 8 | rgbe[3]) != scanline_width)
447 scanline_buffer = (
unsigned char *)malloc(
sizeof(
unsigned char) * 4 * scanline_width);
450 unsigned char *ptr = &scanline_buffer[0];
452 for(
int i = 0;
i < 4;
i++)
454 ptr_end = &scanline_buffer[(
i + 1) * scanline_width];
457 if(fread(buf,
sizeof(buf[0]) * 2, 1, fp) < 1)
465 count = buf[0] - 128;
466 if((count == 0) || (count > ptr_end - ptr))
471 while(count-- > 0) *ptr++ = buf[1];
477 if((count == 0) || (count > ptr_end - ptr))
485 if(fread(ptr,
sizeof(*ptr) * count, 1, fp) < 1)
496 for(
int i = 0;
i < scanline_width;
i++)
498 rgbe[0] = scanline_buffer[
i];
499 rgbe[1] = scanline_buffer[
i + scanline_width];
500 rgbe[2] = scanline_buffer[
i + 2 * scanline_width];
501 rgbe[3] = scanline_buffer[
i + 3 * scanline_width];
511#undef RGBE_VALID_PROGRAMTYPE
512#undef RGBE_VALID_GAMMA
513#undef RGBE_VALID_EXPOSURE
515#undef RGBE_RETURN_SUCCESS
516#undef RGBE_RETURN_FAILURE
519#undef RGBE_DATA_GREEN
557static void _xy2matrix(
const float r[2],
const float g[2],
const float b[2],
558 const float w[2],
const float Y,
float M[4][4])
560 float X = w[0] * Y / w[1];
561 float Z = (1 - w[0] - w[1]) * Y / w[1];
566 float d =
r[0] * (b[1] -
g[1]) +
567 b[0] * (
g[1] -
r[1]) +
568 g[0] * (
r[1] - b[1]);
569 float Sr = (X * (b[1] -
g[1]) -
570 g[0] * (Y * (b[1] - 1) +
572 b[0] * (Y * (
g[1] - 1) +
573 g[1] * (X + Z))) /
d;
574 float Sg = (X * (
r[1] - b[1]) +
575 r[0] * (Y * (b[1] - 1) +
577 b[0] * (Y * (
r[1] - 1) +
578 r[1] * (X + Z))) /
d;
579 float Sb = (X * (
g[1] -
r[1]) -
580 r[0] * (Y * (
g[1] - 1) +
582 g[0] * (Y * (
r[1] - 1) +
583 r[1] * (X + Z))) /
d;
588 for(
int i = 0;
i < 4;
i++)
M[
i][3] =
M[3][
i] = 0.0;
592 M[0][2] = Sr * (1 -
r[0] -
r[1]);
595 M[1][2] = Sg * (1 -
g[0] -
g[1]);
598 M[2][2] = Sb * (1 - b[0] - b[1]);
603 const char *ext = filename + strlen(filename);
604 while(*ext !=
'.' && ext > filename) ext--;
605 if(strncmp(ext,
".hdr", 4) && strncmp(ext,
".HDR", 4) && strncmp(ext,
".Hdr", 4))
607 FILE *
f = g_fopen(filename,
"rb");
615 img->
dsc.
bpp = 4 *
sizeof(float);
618 img->
flags &= ~DT_IMAGE_LDR;
619 img->
flags &= ~DT_IMAGE_RAW;
620 img->
flags &= ~DT_IMAGE_S_RAW;
639 for(
int c = 0; c < 3; c++) buf[4 * (
i - 1) + c] = fmaxf(0.0f, fminf(10000.0, buf[3 * (
i - 1) + c]));
647 for(
int i = 0;
i < 3;
i++)
648 for(
int j = 0; j < 3; j++)
int mat3inv(float *const dst, const float *const src)
const dt_aligned_pixel_t f
static const dt_colormatrix_t M
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
@ DT_IMAGEIO_FILE_CORRUPTED
int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width, int num_scanlines)
#define RGBE_RETURN_SUCCESS
static void _xy2matrix(const float r[2], const float g[2], const float b[2], const float w[2], const float Y, float M[4][4])
int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info)
dt_imageio_retval_t dt_imageio_open_rgbe(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
int RGBE_ReadPixels(FILE *fp, float *data, int numpixels)
#define RGBE_VALID_PROGRAMTYPE
static void rgbe2float(float *red, float *green, float *blue, unsigned char rgbe[4])
#define RGBE_RETURN_FAILURE
static int rgbe_error(int rgbe_error_code, char *msg)
#define RGBE_VALID_EXPOSURE
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
float d65_color_matrix[9]
dt_iop_buffer_type_t datatype