Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ACGL
acgl
Commits
9b28ede5
Commit
9b28ede5
authored
Feb 25, 2013
by
Robert Menzel
Browse files
added read-support for RADIANCE / RGBE files
parent
f853399f
Changes
5
Hide whitespace changes
Inline
Side-by-side
README.TXT
View file @
9b28ede5
...
...
@@ -8,6 +8,7 @@ Included third-party software:
* Includes OpenGL loader code created by a modified glLoadGen by Jason McKesson.
* Includes GLM by Christophe Riccio.
* Includes data type definitions from libspnav header originally by John Tsiombikas (see mini_spnav.h for details).
* Includes RGBE/Radiance image import by Bruce Walter (code provided 'as-is').
See LICENSE.TXT for licensing information.
...
...
include/ACGL/OpenGL/Data/TextureDataLoadStore.hh
View file @
9b28ede5
...
...
@@ -51,6 +51,8 @@ SharedTextureData loadTextureDataFromLodepng(const std::string &_filename);
SharedTextureData
loadTextureDataFromQT
(
const
std
::
string
&
_filename
);
#endif
SharedTextureData
loadTextureDataFromRGBE
(
const
std
::
string
&
_filename
);
///////////////////////////////////////////////////////////////////////////////////////////////////
// library specific save
///////////////////////////////////////////////////////////////////////////////////////////////////
...
...
include/rgbe/rgbe.hh
0 → 100644
View file @
9b28ede5
#ifndef _H_RGBE
#define _H_RGBE
/* THIS CODE CARRIES NO GUARANTEE OF USABILITY OR FITNESS FOR ANY PURPOSE.
* WHILE THE AUTHORS HAVE TRIED TO ENSURE THE PROGRAM WORKS CORRECTLY,
* IT IS STRICTLY USE AT YOUR OWN RISK. */
/* utility for reading and writing Ward's rgbe image format.
See rgbe.txt file for more details.
*/
#include
<stdio.h>
typedef
struct
{
int
valid
;
/* indicate which fields are valid */
char
programtype
[
16
];
/* listed at beginning of file to identify it
* after "#?". defaults to "RGBE" */
float
gamma
;
/* image has already been gamma corrected with
* given gamma. defaults to 1.0 (no correction) */
float
exposure
;
/* a value of 1.0 in an image corresponds to
* <exposure> watts/steradian/m^2.
* defaults to 1.0 */
}
rgbe_header_info
;
/* flags indicating which fields in an rgbe_header_info are valid */
#define RGBE_VALID_PROGRAMTYPE 0x01
#define RGBE_VALID_GAMMA 0x02
#define RGBE_VALID_EXPOSURE 0x04
/* return codes for rgbe routines */
#define RGBE_RETURN_SUCCESS 0
#define RGBE_RETURN_FAILURE -1
/* read or write headers */
/* you may set rgbe_header_info to null if you want to */
int
RGBE_WriteHeader
(
FILE
*
fp
,
int
width
,
int
height
,
rgbe_header_info
*
info
);
int
RGBE_ReadHeader
(
FILE
*
fp
,
int
*
width
,
int
*
height
,
rgbe_header_info
*
info
);
/* read or write pixels */
/* can read or write pixels in chunks of any size including single pixels*/
int
RGBE_WritePixels
(
FILE
*
fp
,
float
*
data
,
int
numpixels
);
int
RGBE_ReadPixels
(
FILE
*
fp
,
float
*
data
,
int
numpixels
);
/* read or write run length encoded files */
/* must be called to read or write whole scanlines */
int
RGBE_WritePixels_RLE
(
FILE
*
fp
,
float
*
data
,
int
scanline_width
,
int
num_scanlines
);
int
RGBE_ReadPixels_RLE
(
FILE
*
fp
,
float
*
data
,
int
scanline_width
,
int
num_scanlines
);
#endif
/* _H_RGBE */
src/ACGL/OpenGL/Data/TextureDataLoadStore.cc
View file @
9b28ede5
...
...
@@ -16,6 +16,7 @@
#include
<fstream>
#include
"lodepng/lodepng.h"
#include
"rgbe/rgbe.hh"
#ifdef ACGL_COMPILE_WITH_QT
#include
<QImage>
...
...
@@ -42,6 +43,8 @@ SharedTextureData loadTextureData(const std::string &_filename)
if
(
fileEnding
==
"png"
)
{
return
loadTextureDataFromLodepng
(
_filename
);
}
else
if
(
fileEnding
==
"hdr"
)
{
return
loadTextureDataFromRGBE
(
_filename
);
}
#ifdef ACGL_COMPILE_WITH_QT
else
if
(
fileEnding
==
"bmp"
||
fileEnding
==
"jpg"
||
fileEnding
==
"jpeg"
...
...
@@ -209,6 +212,27 @@ SharedTextureData loadTextureDataFromQT(const std::string &_filename)
}
#endif
SharedTextureData
loadTextureDataFromRGBE
(
const
std
::
string
&
_filename
)
{
SharedTextureData
data
=
SharedTextureData
(
new
TextureData
()
);
FILE
*
f
=
fopen
(
_filename
.
c_str
(),
"rb"
);
int
texWidth
,
texHeight
;
RGBE_ReadHeader
(
f
,
&
texWidth
,
&
texHeight
,
NULL
);
GLubyte
*
tempdata
=
new
GLubyte
[
sizeof
(
GL_FLOAT
)
*
3
*
texWidth
*
texHeight
];
RGBE_ReadPixels_RLE
(
f
,
(
float
*
)
tempdata
,
texWidth
,
texHeight
);
fclose
(
f
);
data
->
setData
(
tempdata
);
data
->
setHeight
(
texHeight
);
data
->
setWidth
(
texWidth
);
data
->
setFormat
(
GL_RGB
);
data
->
setType
(
GL_FLOAT
);
return
data
;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// library specific save
///////////////////////////////////////////////////////////////////////////////////////////////////
...
...
src/rgbe/rgbe.cc
0 → 100644
View file @
9b28ede5
/* THIS CODE CARRIES NO GUARANTEE OF USABILITY OR FITNESS FOR ANY PURPOSE.
* WHILE THE AUTHORS HAVE TRIED TO ENSURE THE PROGRAM WORKS CORRECTLY,
* IT IS STRICTLY USE AT YOUR OWN RISK. */
/* Copyright (c) 1995 Bruce Walter <bjw@graphics.cornell.edu>
The license of these files has been clarified by Bruce Walter during
a private email conversation. These files are public domain. */
#include
"rgbe/rgbe.hh"
#include
<math.h>
#include
<stdlib.h>
#include
<string.h>
#include
<ctype.h>
/* This file contains code to read and write four byte rgbe file format
developed by Greg Ward. It handles the conversions between rgbe and
pixels consisting of floats. The data is assumed to be an array of floats.
By default there are three floats per pixel in the order red, green, blue.
(RGBE_DATA_??? values control this.) Only the mimimal header reading and
writing is implemented. Each routine does error checking and will return
a status value as defined below. This code is intended as a skeleton so
feel free to modify it to suit your needs.
(Place notice here if you modified the code.)
posted to http://www.graphics.cornell.edu/~bjw/
written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95
based on code written by Greg Ward
*/
/* offsets to red, green, and blue components in a data (float) pixel */
#define RGBE_DATA_RED 0
#define RGBE_DATA_GREEN 1
#define RGBE_DATA_BLUE 2
/* number of floats per pixel */
#define RGBE_DATA_SIZE 3
#define INLINE inline
enum
rgbe_error_codes
{
rgbe_read_error
,
rgbe_write_error
,
rgbe_format_error
,
rgbe_memory_error
};
/* default error routine. change this to change error handling */
static
int
rgbe_error
(
int
rgbe_error_code
,
char
*
msg
)
{
switch
(
rgbe_error_code
)
{
case
rgbe_read_error
:
perror
(
"RGBE read error"
);
break
;
case
rgbe_write_error
:
perror
(
"RGBE write error"
);
break
;
case
rgbe_format_error
:
fprintf
(
stderr
,
"RGBE bad file format: %s
\n
"
,
msg
);
break
;
default:
case
rgbe_memory_error
:
fprintf
(
stderr
,
"RGBE error: %s
\n
"
,
msg
);
}
return
RGBE_RETURN_FAILURE
;
}
/* standard conversion from float pixels to rgbe pixels */
/* note: you can remove the "inline"s if your compiler complains about it */
INLINE
void
float2rgbe
(
unsigned
char
rgbe
[
4
],
float
red
,
float
green
,
float
blue
)
{
float
v
;
int
e
;
v
=
red
;
if
(
green
>
v
)
v
=
green
;
if
(
blue
>
v
)
v
=
blue
;
if
(
v
<
1e-32
)
{
rgbe
[
0
]
=
rgbe
[
1
]
=
rgbe
[
2
]
=
rgbe
[
3
]
=
0
;
}
else
{
v
=
(
float
)
(
frexp
(
v
,
&
e
)
*
256.0
/
v
);
rgbe
[
0
]
=
(
unsigned
char
)
(
red
*
v
);
rgbe
[
1
]
=
(
unsigned
char
)
(
green
*
v
);
rgbe
[
2
]
=
(
unsigned
char
)
(
blue
*
v
);
rgbe
[
3
]
=
(
unsigned
char
)
(
e
+
128
);
}
}
/* standard conversion from rgbe to float pixels */
/* note: Ward uses ldexp(col+0.5,exp-(128+8)). However we wanted pixels */
/* in the range [0,1] to map back into the range [0,1]. */
INLINE
void
rgbe2float
(
float
*
red
,
float
*
green
,
float
*
blue
,
unsigned
char
rgbe
[
4
])
{
float
f
;
if
(
rgbe
[
3
])
{
/*nonzero pixel*/
f
=
(
float
)(
ldexp
(
1.0
,
rgbe
[
3
]
-
(
int
)(
128
+
8
)));
*
red
=
rgbe
[
0
]
*
f
;
*
green
=
rgbe
[
1
]
*
f
;
*
blue
=
rgbe
[
2
]
*
f
;
}
else
*
red
=
*
green
=
*
blue
=
0.0
;
}
/* default minimal header. modify if you want more information in header */
int
RGBE_WriteHeader
(
FILE
*
fp
,
int
width
,
int
height
,
rgbe_header_info
*
info
)
{
char
*
programtype
=
"RGBE"
;
if
(
info
&&
(
info
->
valid
&
RGBE_VALID_PROGRAMTYPE
))
programtype
=
info
->
programtype
;
if
(
fprintf
(
fp
,
"#?%s
\n
"
,
programtype
)
<
0
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
/* The #? is to identify file type, the programtype is optional. */
if
(
info
&&
(
info
->
valid
&
RGBE_VALID_GAMMA
))
{
if
(
fprintf
(
fp
,
"GAMMA=%g
\n
"
,
info
->
gamma
)
<
0
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
}
if
(
info
&&
(
info
->
valid
&
RGBE_VALID_EXPOSURE
))
{
if
(
fprintf
(
fp
,
"EXPOSURE=%g
\n
"
,
info
->
exposure
)
<
0
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
}
if
(
fprintf
(
fp
,
"FORMAT=32-bit_rle_rgbe
\n\n
"
)
<
0
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
if
(
fprintf
(
fp
,
"-Y %d +X %d
\n
"
,
height
,
width
)
<
0
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
return
RGBE_RETURN_SUCCESS
;
}
/* minimal header reading. modify if you want to parse more information */
int
RGBE_ReadHeader
(
FILE
*
fp
,
int
*
width
,
int
*
height
,
rgbe_header_info
*
info
)
{
char
buf
[
128
];
int
found_format
;
float
tempf
;
int
i
;
found_format
=
0
;
if
(
info
)
{
info
->
valid
=
0
;
info
->
programtype
[
0
]
=
0
;
info
->
gamma
=
info
->
exposure
=
1.0
;
}
if
(
fgets
(
buf
,
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]),
fp
)
==
NULL
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
if
((
buf
[
0
]
!=
'#'
)
||
(
buf
[
1
]
!=
'?'
))
{
/* if you want to require the magic token then uncomment the next line */
/*return rgbe_error(rgbe_format_error,"bad initial token"); */
}
else
if
(
info
)
{
info
->
valid
|=
RGBE_VALID_PROGRAMTYPE
;
for
(
i
=
0
;
i
<
sizeof
(
info
->
programtype
)
-
1
;
i
++
)
{
if
((
buf
[
i
+
2
]
==
0
)
||
isspace
(
buf
[
i
+
2
]))
break
;
info
->
programtype
[
i
]
=
buf
[
i
+
2
];
}
info
->
programtype
[
i
]
=
0
;
if
(
fgets
(
buf
,
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]),
fp
)
==
0
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
for
(;;)
{
if
((
buf
[
0
]
==
0
)
||
(
buf
[
0
]
==
'\n'
))
return
rgbe_error
(
rgbe_format_error
,
"no FORMAT specifier found"
);
else
if
(
strcmp
(
buf
,
"FORMAT=32-bit_rle_rgbe
\n
"
)
==
0
)
break
;
/* format found so break out of loop */
else
if
(
info
&&
(
sscanf
(
buf
,
"GAMMA=%g"
,
&
tempf
)
==
1
))
{
info
->
gamma
=
tempf
;
info
->
valid
|=
RGBE_VALID_GAMMA
;
}
else
if
(
info
&&
(
sscanf
(
buf
,
"EXPOSURE=%g"
,
&
tempf
)
==
1
))
{
info
->
exposure
=
tempf
;
info
->
valid
|=
RGBE_VALID_EXPOSURE
;
}
if
(
fgets
(
buf
,
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]),
fp
)
==
0
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
#if 0
if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
return rgbe_error(rgbe_read_error,NULL);
if (strcmp(buf,"\n") != 0)
return rgbe_error(rgbe_format_error,
"missing blank line after FORMAT specifier");
#endif
for
(;;)
{
if
(
fgets
(
buf
,
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]),
fp
)
==
0
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
if
(
sscanf
(
buf
,
"-Y %d +X %d"
,
height
,
width
)
==
2
)
break
;
}
return
RGBE_RETURN_SUCCESS
;
}
/* simple write routine that does not use run length encoding */
/* These routines can be made faster by allocating a larger buffer and
fread-ing and fwrite-ing the data in larger chunks */
int
RGBE_WritePixels
(
FILE
*
fp
,
float
*
data
,
int
numpixels
)
{
unsigned
char
rgbe
[
4
];
while
(
numpixels
--
>
0
)
{
float2rgbe
(
rgbe
,
data
[
RGBE_DATA_RED
],
data
[
RGBE_DATA_GREEN
],
data
[
RGBE_DATA_BLUE
]);
data
+=
RGBE_DATA_SIZE
;
if
(
fwrite
(
rgbe
,
sizeof
(
rgbe
),
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
}
return
RGBE_RETURN_SUCCESS
;
}
/* simple read routine. will not correctly handle run length encoding */
int
RGBE_ReadPixels
(
FILE
*
fp
,
float
*
data
,
int
numpixels
)
{
unsigned
char
rgbe
[
4
];
while
(
numpixels
--
>
0
)
{
if
(
fread
(
rgbe
,
sizeof
(
rgbe
),
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
rgbe2float
(
&
data
[
RGBE_DATA_RED
],
&
data
[
RGBE_DATA_GREEN
],
&
data
[
RGBE_DATA_BLUE
],
rgbe
);
data
+=
RGBE_DATA_SIZE
;
}
return
RGBE_RETURN_SUCCESS
;
}
int
RGBE_ReadPixels_Raw
(
FILE
*
fp
,
unsigned
char
*
data
,
size_t
numpixels
)
{
if
(
fread
(
data
,
4
,
numpixels
,
fp
)
<
numpixels
)
return
rgbe_error
(
rgbe_read_error
,
NULL
);
return
RGBE_RETURN_SUCCESS
;
}
/* The code below is only needed for the run-length encoded files. */
/* Run length encoding adds considerable complexity but does */
/* save some space. For each scanline, each channel (r,g,b,e) is */
/* encoded separately for better compression. */
static
int
RGBE_WriteBytes_RLE
(
FILE
*
fp
,
unsigned
char
*
data
,
int
numbytes
)
{
#define MINRUNLENGTH 4
int
cur
,
beg_run
,
run_count
,
old_run_count
,
nonrun_count
;
unsigned
char
buf
[
2
];
cur
=
0
;
while
(
cur
<
numbytes
)
{
beg_run
=
cur
;
/* find next run of length at least 4 if one exists */
run_count
=
old_run_count
=
0
;
while
((
run_count
<
MINRUNLENGTH
)
&&
(
beg_run
<
numbytes
))
{
beg_run
+=
run_count
;
old_run_count
=
run_count
;
run_count
=
1
;
while
(
(
beg_run
+
run_count
<
numbytes
)
&&
(
run_count
<
127
)
&&
(
data
[
beg_run
]
==
data
[
beg_run
+
run_count
]))
run_count
++
;
}
/* if data before next big run is a short run then write it as such */
if
((
old_run_count
>
1
)
&&
(
old_run_count
==
beg_run
-
cur
))
{
buf
[
0
]
=
128
+
old_run_count
;
/*write short run*/
buf
[
1
]
=
data
[
cur
];
if
(
fwrite
(
buf
,
sizeof
(
buf
[
0
])
*
2
,
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
cur
=
beg_run
;
}
/* write out bytes until we reach the start of the next run */
while
(
cur
<
beg_run
)
{
nonrun_count
=
beg_run
-
cur
;
if
(
nonrun_count
>
128
)
nonrun_count
=
128
;
buf
[
0
]
=
nonrun_count
;
if
(
fwrite
(
buf
,
sizeof
(
buf
[
0
]),
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
if
(
fwrite
(
&
data
[
cur
],
sizeof
(
data
[
0
])
*
nonrun_count
,
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
cur
+=
nonrun_count
;
}
/* write out next run if one was found */
if
(
run_count
>=
MINRUNLENGTH
)
{
buf
[
0
]
=
128
+
run_count
;
buf
[
1
]
=
data
[
beg_run
];
if
(
fwrite
(
buf
,
sizeof
(
buf
[
0
])
*
2
,
1
,
fp
)
<
1
)
return
rgbe_error
(
rgbe_write_error
,
NULL
);
cur
+=
run_count
;
}
}
return
RGBE_RETURN_SUCCESS
;
#undef MINRUNLENGTH
}
int
RGBE_WritePixels_RLE
(
FILE
*
fp
,
float
*
data
,
int
scanline_width
,
int
num_scanlines
)
{
unsigned
char
rgbe
[
4
];
unsigned
char
*
buffer
;
int
i
,
err
;
if
((
scanline_width
<
8
)
||
(
scanline_width
>
0x7fff
))
/* run length encoding is not allowed so write flat*/
return
RGBE_WritePixels
(
fp
,
data
,
scanline_width
*
num_scanlines
);
buffer
=
(
unsigned
char
*
)
malloc
(
sizeof
(
unsigned
char
)
*
4
*
scanline_width
);
if
(
buffer
==
NULL
)
/* no buffer space so write flat */
return
RGBE_WritePixels
(
fp
,
data
,
scanline_width
*
num_scanlines
);
while
(
num_scanlines
--
>
0
)
{
rgbe
[
0
]
=
2
;
rgbe
[
1
]
=
2
;
rgbe
[
2
]
=
scanline_width
>>
8
;
rgbe
[
3
]
=
scanline_width
&
0xFF
;
if
(
fwrite
(
rgbe
,
sizeof
(
rgbe
),
1
,
fp
)
<
1
)
{
free
(
buffer
);
return
rgbe_error
(
rgbe_write_error
,
NULL
);
}
for
(
i
=
0
;
i
<
scanline_width
;
i
++
)
{
float2rgbe
(
rgbe
,
data
[
RGBE_DATA_RED
],
data
[
RGBE_DATA_GREEN
],
data
[
RGBE_DATA_BLUE
]);
buffer
[
i
]
=
rgbe
[
0
];
buffer
[
i
+
scanline_width
]
=
rgbe
[
1
];
buffer
[
i
+
2
*
scanline_width
]
=
rgbe
[
2
];
buffer
[
i
+
3
*
scanline_width
]
=
rgbe
[
3
];
data
+=
RGBE_DATA_SIZE
;
}
/* write out each of the four channels separately run length encoded */
/* first red, then green, then blue, then exponent */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
((
err
=
RGBE_WriteBytes_RLE
(
fp
,
&
buffer
[
i
*
scanline_width
],
scanline_width
))
!=
RGBE_RETURN_SUCCESS
)
{
free
(
buffer
);
return
err
;
}
}
}
free
(
buffer
);
return
RGBE_RETURN_SUCCESS
;
}
int
RGBE_ReadPixels_RLE
(
FILE
*
fp
,
float
*
data
,
int
scanline_width
,
int
num_scanlines
)
{
unsigned
char
rgbe
[
4
],
*
scanline_buffer
,
*
ptr
,
*
ptr_end
;
int
i
,
count
;
unsigned
char
buf
[
2
];
if
((
scanline_width
<
8
)
||
(
scanline_width
>
0x7fff
))
/* run length encoding is not allowed so read flat*/
return
RGBE_ReadPixels
(
fp
,
data
,
scanline_width
*
num_scanlines
);
scanline_buffer
=
NULL
;
/* read in each successive scanline */
while
(
num_scanlines
>
0
)
{
if
(
fread
(
rgbe
,
sizeof
(
rgbe
),
1
,
fp
)
<
1
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
if
((
rgbe
[
0
]
!=
2
)
||
(
rgbe
[
1
]
!=
2
)
||
(
rgbe
[
2
]
&
0x80
))
{
/* this file is not run length encoded */
rgbe2float
(
&
data
[
0
],
&
data
[
1
],
&
data
[
2
],
rgbe
);
data
+=
RGBE_DATA_SIZE
;
free
(
scanline_buffer
);
return
RGBE_ReadPixels
(
fp
,
data
,
scanline_width
*
num_scanlines
-
1
);
}
if
((((
int
)
rgbe
[
2
])
<<
8
|
rgbe
[
3
])
!=
scanline_width
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_format_error
,
"wrong scanline width"
);
}
if
(
scanline_buffer
==
NULL
)
scanline_buffer
=
(
unsigned
char
*
)
malloc
(
sizeof
(
unsigned
char
)
*
4
*
scanline_width
);
if
(
scanline_buffer
==
NULL
)
return
rgbe_error
(
rgbe_memory_error
,
"unable to allocate buffer space"
);
ptr
=
&
scanline_buffer
[
0
];
/* read each of the four channels for the scanline into the buffer */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
ptr_end
=
&
scanline_buffer
[(
i
+
1
)
*
scanline_width
];
while
(
ptr
<
ptr_end
)
{
if
(
fread
(
buf
,
sizeof
(
buf
[
0
])
*
2
,
1
,
fp
)
<
1
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
if
(
buf
[
0
]
>
128
)
{
/* a run of the same value */
count
=
buf
[
0
]
-
128
;
if
((
count
==
0
)
||
(
count
>
ptr_end
-
ptr
))
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_format_error
,
"bad scanline data"
);
}
while
(
count
--
>
0
)
*
ptr
++
=
buf
[
1
];
}
else
{
/* a non-run */
count
=
buf
[
0
];
if
((
count
==
0
)
||
(
count
>
ptr_end
-
ptr
))
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_format_error
,
"bad scanline data"
);
}
*
ptr
++
=
buf
[
1
];
if
(
--
count
>
0
)
{
if
(
fread
(
ptr
,
sizeof
(
*
ptr
)
*
count
,
1
,
fp
)
<
1
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
ptr
+=
count
;
}
}
}
}
/* now convert data from buffer into floats */
for
(
i
=
0
;
i
<
scanline_width
;
i
++
)
{
rgbe
[
0
]
=
scanline_buffer
[
i
];
rgbe
[
1
]
=
scanline_buffer
[
i
+
scanline_width
];
rgbe
[
2
]
=
scanline_buffer
[
i
+
2
*
scanline_width
];
rgbe
[
3
]
=
scanline_buffer
[
i
+
3
*
scanline_width
];
rgbe2float
(
&
data
[
RGBE_DATA_RED
],
&
data
[
RGBE_DATA_GREEN
],
&
data
[
RGBE_DATA_BLUE
],
rgbe
);
data
+=
RGBE_DATA_SIZE
;
}
num_scanlines
--
;
}
free
(
scanline_buffer
);
return
RGBE_RETURN_SUCCESS
;
}
int
RGBE_ReadPixels_Raw_RLE
(
FILE
*
fp
,
unsigned
char
*
data
,
int
scanline_width
,
size_t
num_scanlines
)
{
unsigned
char
rgbe
[
4
],
*
scanline_buffer
,
*
ptr
,
*
ptr_end
;
int
i
,
count
;
unsigned
char
buf
[
2
];
if
((
scanline_width
<
8
)
||
(
scanline_width
>
0x7fff
))
/* run length encoding is not allowed so read flat*/
return
RGBE_ReadPixels_Raw
(
fp
,
data
,
scanline_width
*
num_scanlines
);
scanline_buffer
=
NULL
;
/* read in each successive scanline */
while
(
num_scanlines
>
0
)
{
if
(
fread
(
rgbe
,
sizeof
(
rgbe
),
1
,
fp
)
<
1
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
if
((
rgbe
[
0
]
!=
2
)
||
(
rgbe
[
1
]
!=
2
)
||
(
rgbe
[
2
]
&
0x80
))
{
/* this file is not run length encoded */
data
[
0
]
=
rgbe
[
0
];
data
[
1
]
=
rgbe
[
1
];
data
[
2
]
=
rgbe
[
2
];
data
[
3
]
=
rgbe
[
3
];
data
+=
RGBE_DATA_SIZE
;
free
(
scanline_buffer
);
return
RGBE_ReadPixels_Raw
(
fp
,
data
,
scanline_width
*
num_scanlines
-
1
);
}
if
((((
int
)
rgbe
[
2
])
<<
8
|
rgbe
[
3
])
!=
scanline_width
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_format_error
,
"wrong scanline width"
);
}
if
(
scanline_buffer
==
NULL
)
scanline_buffer
=
(
unsigned
char
*
)
malloc
(
sizeof
(
unsigned
char
)
*
4
*
scanline_width
);
if
(
scanline_buffer
==
NULL
)
return
rgbe_error
(
rgbe_memory_error
,
"unable to allocate buffer space"
);
ptr
=
&
scanline_buffer
[
0
];
/* read each of the four channels for the scanline into the buffer */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
ptr_end
=
&
scanline_buffer
[(
i
+
1
)
*
scanline_width
];
while
(
ptr
<
ptr_end
)
{
if
(
fread
(
buf
,
sizeof
(
buf
[
0
])
*
2
,
1
,
fp
)
<
1
)
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_read_error
,
NULL
);
}
if
(
buf
[
0
]
>
128
)
{
/* a run of the same value */
count
=
buf
[
0
]
-
128
;
if
((
count
==
0
)
||
(
count
>
ptr_end
-
ptr
))
{
free
(
scanline_buffer
);
return
rgbe_error
(
rgbe_format_error
,
"bad scanline data"
);
}
while
(
count
--
>
0
)
*
ptr
++
=
buf
[
1
];
}
else
{