34#include <glib/gstdio.h>
64#define RGBE_VALID_PROGRAMTYPE 0x01
65#define RGBE_VALID_GAMMA 0x02
66#define RGBE_VALID_EXPOSURE 0x04
69#define RGBE_RETURN_SUCCESS 0
70#define RGBE_RETURN_FAILURE -1
72#define RGBE_DATA_RED 0
73#define RGBE_DATA_GREEN 1
74#define RGBE_DATA_BLUE 2
76#define RGBE_DATA_SIZE 3
89 switch(rgbe_error_code)
92 perror(
"RGBE read error");
95 perror(
"RGBE write error");
98 fprintf(stderr,
"RGBE bad file format: %s\n", msg);
102 fprintf(stderr,
"RGBE error: %s\n", msg);
111float2rgbe(
unsigned char rgbe[4],
float red,
float green,
float blue)
121 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
125 v = frexp(
v,&e) * 256.0/
v;
126 rgbe[0] = (
unsigned char) (red *
v);
127 rgbe[1] = (
unsigned char) (green *
v);
128 rgbe[2] = (
unsigned char) (blue *
v);
129 rgbe[3] = (
unsigned char) (e + 128);
137static void rgbe2float(
float *red,
float *green,
float *blue,
unsigned char rgbe[4])
141 const float f = ldexpf(1.0f, rgbe[3] - (
int)(128 + 8));
143 *green = rgbe[1] *
f;
147 *red = *green = *blue = 0.0f;
154 char *programtype =
"RGBE";
158 if (fprintf(fp,
"#?%s\n",programtype) < 0)
163 if (fprintf(fp,
"GAMMA=%g\n",info->
gamma) < 0)
168 if (fprintf(fp,
"EXPOSURE=%g\n",info->
exposure) < 0)
171 if (fprintf(fp,
"FORMAT=32-bit_rle_rgbe\n\n") < 0)
173 if (fprintf(fp,
"-Y %d +X %d\n",
height,
width) < 0)
189 static const float default_primaries[] = { 0.640, 0.330, 0.290, 0.600, 0.150, 0.060, 0.333, 0.333 };
193 if((buf[0] !=
'#') || (buf[1] !=
'?'))
204 if((buf[
i + 2] == 0) || isspace(buf[
i + 2]))
break;
210 gboolean format_is_rgbe =
FALSE;
213 if((buf[0] == 0) || (buf[0] ==
'\n'))
215 else if(strcmp(buf,
"FORMAT=32-bit_rle_rgbe\n") == 0)
216 format_is_rgbe =
TRUE;
219 if(g_str_has_prefix(buf,
"GAMMA="))
221 char *startptr = buf + strlen(
"GAMMA="), *endptr;
222 float tmp = g_ascii_strtod(startptr, &endptr);
223 if(startptr != endptr)
229 else if(g_str_has_prefix(buf,
"EXPOSURE="))
231 char *startptr = buf + strlen(
"EXPOSURE="), *endptr;
232 float tmp = g_ascii_strtod(startptr, &endptr);
233 if(startptr != endptr)
239 else if(g_str_has_prefix(buf,
"PRIMARIES="))
242 gboolean all_ok =
TRUE;
243 char *startptr = buf + strlen(
"PRIMARIES="), *endptr;
244 for(
int i = 0;
i < 8;
i++)
246 tmp[
i] = g_ascii_strtod(startptr, &endptr);
247 if(startptr == endptr)
262 while(!strcmp(buf,
"\n"))
273int RGBE_WritePixels(FILE *fp,
float *data,
int numpixels)
275 unsigned char rgbe[4];
277 while (numpixels-- > 0)
282 if (fwrite(rgbe,
sizeof(rgbe), 1, fp) < 1)
292 unsigned char rgbe[4];
294 while(numpixels-- > 0)
309static int RGBE_WriteBytes_RLE(FILE *fp,
unsigned char *data,
int numbytes)
311#define MINRUNLENGTH 4
312 int cur, beg_run, run_count, old_run_count, nonrun_count;
313 unsigned char buf[2];
316 while(cur < numbytes)
320 run_count = old_run_count = 0;
321 while((run_count < MINRUNLENGTH) && (beg_run < numbytes))
323 beg_run += run_count;
324 old_run_count = run_count;
326 while((data[beg_run] == data[beg_run + run_count])
327 && (beg_run + run_count < numbytes) && (run_count < 127))
331 if ((old_run_count > 1)&&(old_run_count == beg_run - cur))
333 buf[0] = 128 + old_run_count;
335 if (fwrite(buf,
sizeof(buf[0])*2,1,fp) < 1)
342 nonrun_count = beg_run - cur;
343 if (nonrun_count > 128)
345 buf[0] = nonrun_count;
346 if (fwrite(buf,
sizeof(buf[0]),1,fp) < 1)
348 if (fwrite(&data[cur],
sizeof(data[0])*nonrun_count,1,fp) < 1)
353 if (run_count >= MINRUNLENGTH)
355 buf[0] = 128 + run_count;
356 buf[1] = data[beg_run];
357 if (fwrite(buf,
sizeof(buf[0])*2,1,fp) < 1)
366int RGBE_WritePixels_RLE(FILE *fp,
float *data,
int scanline_width,
369 unsigned char rgbe[4];
370 unsigned char *buffer;
373 if ((scanline_width < 8)||(scanline_width > 0x7fff))
375 return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
376 buffer = (
unsigned char *)malloc(
sizeof(
unsigned char)*4*scanline_width);
379 return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
380 while(num_scanlines-- > 0)
384 rgbe[2] = scanline_width >> 8;
385 rgbe[3] = scanline_width & 0xFF;
386 if (fwrite(rgbe,
sizeof(rgbe), 1, fp) < 1)
391 for(
i=0;
i<scanline_width;
i++)
396 buffer[
i+scanline_width] = rgbe[1];
397 buffer[
i+2*scanline_width] = rgbe[2];
398 buffer[
i+3*scanline_width] = rgbe[3];
405 if ((err = RGBE_WriteBytes_RLE(fp,&buffer[
i*scanline_width],
420 unsigned char rgbe[4], *scanline_buffer, *ptr_end;
422 unsigned char buf[2];
424 if((scanline_width < 8) || (scanline_width > 0x7fff))
426 scanline_buffer = NULL;
428 while(num_scanlines > 0)
430 if(fread(rgbe,
sizeof(rgbe), 1, fp) < 1)
435 if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80))
438 rgbe2float(&data[0], &data[1], &data[2], rgbe);
443 if((((
int)rgbe[2]) << 8 | rgbe[3]) != scanline_width)
449 scanline_buffer = (
unsigned char *)malloc(
sizeof(
unsigned char) * 4 * scanline_width);
452 unsigned char *ptr = &scanline_buffer[0];
454 for(
int i = 0;
i < 4;
i++)
456 ptr_end = &scanline_buffer[(
i + 1) * scanline_width];
459 if(fread(buf,
sizeof(buf[0]) * 2, 1, fp) < 1)
467 count = buf[0] - 128;
468 if((count == 0) || (count > ptr_end - ptr))
473 while(count-- > 0) *ptr++ = buf[1];
479 if((count == 0) || (count > ptr_end - ptr))
487 if(fread(ptr,
sizeof(*ptr) * count, 1, fp) < 1)
498 for(
int i = 0;
i < scanline_width;
i++)
500 rgbe[0] = scanline_buffer[
i];
501 rgbe[1] = scanline_buffer[
i + scanline_width];
502 rgbe[2] = scanline_buffer[
i + 2 * scanline_width];
503 rgbe[3] = scanline_buffer[
i + 3 * scanline_width];
513#undef RGBE_VALID_PROGRAMTYPE
514#undef RGBE_VALID_GAMMA
515#undef RGBE_VALID_EXPOSURE
517#undef RGBE_RETURN_SUCCESS
518#undef RGBE_RETURN_FAILURE
521#undef RGBE_DATA_GREEN
559static void _xy2matrix(
const float r[2],
const float g[2],
const float b[2],
560 const float w[2],
const float Y,
float M[4][4])
562 float X = w[0] * Y / w[1];
563 float Z = (1 - w[0] - w[1]) * Y / w[1];
568 float d =
r[0] * (b[1] -
g[1]) +
569 b[0] * (
g[1] -
r[1]) +
570 g[0] * (
r[1] - b[1]);
571 float Sr = (X * (b[1] -
g[1]) -
572 g[0] * (Y * (b[1] - 1) +
574 b[0] * (Y * (
g[1] - 1) +
575 g[1] * (X + Z))) /
d;
576 float Sg = (X * (
r[1] - b[1]) +
577 r[0] * (Y * (b[1] - 1) +
579 b[0] * (Y * (
r[1] - 1) +
580 r[1] * (X + Z))) /
d;
581 float Sb = (X * (
g[1] -
r[1]) -
582 r[0] * (Y * (
g[1] - 1) +
584 g[0] * (Y * (
r[1] - 1) +
585 r[1] * (X + Z))) /
d;
590 for(
int i = 0;
i < 4;
i++)
M[
i][3] =
M[3][
i] = 0.0;
594 M[0][2] = Sr * (1 -
r[0] -
r[1]);
597 M[1][2] = Sg * (1 -
g[0] -
g[1]);
600 M[2][2] = Sb * (1 - b[0] - b[1]);
605 const char *ext = filename + strlen(filename);
606 while(*ext !=
'.' && ext > filename) ext--;
607 if(strncmp(ext,
".hdr", 4) && strncmp(ext,
".HDR", 4) && strncmp(ext,
".Hdr", 4))
609 FILE *
f = g_fopen(filename,
"rb");
617 img->
dsc.
bpp = 4 *
sizeof(float);
620 img->
flags &= ~DT_IMAGE_LDR;
621 img->
flags &= ~DT_IMAGE_RAW;
622 img->
flags &= ~DT_IMAGE_S_RAW;
641 for(
int c = 0; c < 3; c++) buf[4 * (
i - 1) + c] = fmaxf(0.0f, fminf(10000.0, buf[3 * (
i - 1) + c]));
649 for(
int i = 0;
i < 3;
i++)
650 for(
int j = 0; j < 3; j++)
int mat3inv(float *const dst, const float *const src)
Thin alias of mat3inv_float(), same contract.
static const dt_colormatrix_t M
@ 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
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
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