Commit 01074177 authored by Davis King's avatar Davis King

Upgraded the dng image format so it can natively store floating point

pixel types without any information loss.
parent 90668383
......@@ -14,6 +14,7 @@
#include "../uintn.h"
#include "../image_transforms/assign_image.h"
#include <algorithm>
#include "../vectorstream.h"
namespace dlib
{
......@@ -576,6 +577,8 @@ namespace dlib
else
image.clear();
if (type != grayscale_float)
{
typedef entropy_decoder::kernel_2a decoder_type;
decoder_type decoder;
decoder.set_stream(in);
......@@ -751,6 +754,67 @@ namespace dlib
if (symbol != dng_magic_byte)
throw image_load_error("corruption detected in the dng file");
}
else // if this is a grayscale_float type image
{
std::vector<int64> man(image.size());
std::vector<char> expbuf;
// get the mantissa data
for (unsigned long i = 0; i < man.size(); ++i)
deserialize(man[i], in);
// get the compressed exponent data
deserialize(expbuf, in);
typedef entropy_decoder::kernel_2a decoder_type;
typedef entropy_decoder_model<256,decoder_type>::kernel_4a edm_exp_type;
vectorstream inexp(expbuf);
decoder_type decoder;
decoder.set_stream(inexp);
edm_exp_type edm_exp(decoder);
float_details prev;
unsigned long i = 0;
// fill out the image
for (long r = 0; r < image.nr(); ++r)
{
for (long c = 0; c < image.nc(); ++c)
{
unsigned long exp1, exp2;
edm_exp.decode(exp1);
edm_exp.decode(exp2);
float_details cur(man[i++],(exp2<<8) | exp1);
cur.exponent += prev.exponent;
cur.mantissa += prev.mantissa;
prev = cur;
// Only use long double precision if the target image contains long
// doubles because it's slower to use those.
if (!is_same_type<typename image_type::type,long double>::value)
{
double temp = cur;
assign_pixel(image[r][c],temp);
}
else
{
long double temp = cur;
assign_pixel(image[r][c],temp);
}
}
}
unsigned long symbol;
edm_exp.decode(symbol);
if (symbol != dng_magic_byte)
throw image_load_error("corruption detected in the dng file");
edm_exp.decode(symbol);
if (symbol != dng_magic_byte)
throw image_load_error("corruption detected in the dng file");
edm_exp.decode(symbol);
if (symbol != dng_magic_byte)
throw image_load_error("corruption detected in the dng file");
edm_exp.decode(symbol);
if (symbol != dng_magic_byte)
throw image_load_error("corruption detected in the dng file");
}
}
catch (...)
{
image.clear();
......
......@@ -20,7 +20,8 @@ namespace dlib
rgb_paeth,
rgb_alpha,
rgb_alpha_paeth,
grayscale_16bit
grayscale_16bit,
grayscale_float
};
const unsigned long dng_magic_byte = 100;
......
......@@ -15,6 +15,8 @@
#include "dng_shared.h"
#include "../uintn.h"
#include "../dir_nav.h"
#include "../float_details.h"
#include "../vectorstream.h"
namespace dlib
{
......@@ -249,7 +251,9 @@ namespace dlib
false,
pixel_traits<typename image_type::type>::rgb_alpha,
false,
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) != 1
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) != 1 &&
!is_float_type<typename image_type::type>::value,
is_float_type<typename image_type::type>::value
>::value
>
struct save_dng_helper;
......@@ -257,6 +261,64 @@ namespace dlib
typedef entropy_encoder::kernel_2a encoder_type;
typedef entropy_encoder_model<256,encoder_type>::kernel_5a eem_type;
typedef entropy_encoder_model<256,encoder_type>::kernel_4a eem_exp_type;
template <typename image_type >
struct save_dng_helper<image_type, grayscale_float>
{
static void save_dng (
const image_type& image,
std::ostream& out
)
{
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
unsigned long type = grayscale_float;
serialize(type,out);
serialize(image.nc(),out);
serialize(image.nr(),out);
// Write the compressed exponent data into expbuf. We will append it
// to the stream at the end of the loops.
std::vector<char> expbuf;
expbuf.reserve(image.size()*2);
vectorstream outexp(expbuf);
encoder_type encoder;
encoder.set_stream(outexp);
eem_exp_type eem_exp(encoder);
float_details prev;
for (long r = 0; r < image.nr(); ++r)
{
for (long c = 0; c < image.nc(); ++c)
{
float_details cur = image[r][c];
int16 exp = cur.exponent-prev.exponent;
int64 man = cur.mantissa-prev.mantissa;
prev = cur;
unsigned char ebyte1 = exp&0xFF;
unsigned char ebyte2 = exp>>8;
eem_exp.encode(ebyte1);
eem_exp.encode(ebyte2);
serialize(man, out);
}
}
// write out the magic byte to mark the end of the compressed data.
eem_exp.encode(dng_magic_byte);
eem_exp.encode(dng_magic_byte);
eem_exp.encode(dng_magic_byte);
eem_exp.encode(dng_magic_byte);
encoder.clear();
serialize(expbuf, out);
}
};
template <typename image_type >
struct save_dng_helper<image_type, grayscale_16bit>
{
......
......@@ -90,11 +90,11 @@ namespace dlib
- image[0][0] will be in the upper left corner of the image.
- image[image.nr()-1][image.nc()-1] will be in the lower right
corner of the image.
- This routine can save images containing any type of pixel. However, the
DNG format can natively store only the following pixel types: rgb_pixel,
hsi_pixel, rgb_alpha_pixel, uint8, and uint16. All other pixel types
will be converted into one of these types as appropriate before being
saved to disk.
- This routine can save images containing any type of pixel. However, the DNG
format can natively store only the following pixel types: rgb_pixel,
hsi_pixel, rgb_alpha_pixel, uint8, uint16, float, double, and long double.
All other pixel types will be converted into one of these types as
appropriate before being saved to disk.
throws
- image_save_error
This exception is thrown if there is an error that prevents us
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment