227 lines
10 KiB
C++
227 lines
10 KiB
C++
// Copyright (C) 2011 Davis E. King (davis@dlib.net), Nils Labugt, Changjiang Yang (yangcha@leidos.com)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_LOAd_IMAGE_Hh_
|
|
#define DLIB_LOAd_IMAGE_Hh_
|
|
|
|
#include "load_image_abstract.h"
|
|
#include "../string.h"
|
|
#include "png_loader.h"
|
|
#include "jpeg_loader.h"
|
|
#include "image_loader.h"
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#ifdef DLIB_GIF_SUPPORT
|
|
#include <gif_lib.h>
|
|
#endif
|
|
|
|
namespace dlib
|
|
{
|
|
namespace image_file_type
|
|
{
|
|
enum type
|
|
{
|
|
BMP,
|
|
JPG,
|
|
PNG,
|
|
DNG,
|
|
GIF,
|
|
UNKNOWN
|
|
};
|
|
|
|
inline type read_type(const std::string& file_name)
|
|
{
|
|
std::ifstream file(file_name.c_str(), std::ios::in|std::ios::binary);
|
|
if (!file)
|
|
throw image_load_error("Unable to open file: " + file_name);
|
|
|
|
char buffer[9];
|
|
file.read((char*)buffer, 8);
|
|
buffer[8] = 0;
|
|
|
|
// Determine the true image type using link:
|
|
// http://en.wikipedia.org/wiki/List_of_file_signatures
|
|
|
|
if (strcmp(buffer, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") == 0)
|
|
return PNG;
|
|
else if(buffer[0]=='\xff' && buffer[1]=='\xd8' && buffer[2]=='\xff')
|
|
return JPG;
|
|
else if(buffer[0]=='B' && buffer[1]=='M')
|
|
return BMP;
|
|
else if(buffer[0]=='D' && buffer[1]=='N' && buffer[2] == 'G')
|
|
return DNG;
|
|
else if(buffer[0]=='G' && buffer[1]=='I' && buffer[2] == 'F')
|
|
return GIF;
|
|
|
|
return UNKNOWN;
|
|
}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
// handle the differences in API between libgif v5 and older.
|
|
#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
|
|
#define DLIB_GIFLIB_HANDLE_DIFF_VERSIONS ,0
|
|
#else
|
|
#define DLIB_GIFLIB_HANDLE_DIFF_VERSIONS
|
|
#endif
|
|
|
|
template <typename image_type>
|
|
void load_image (
|
|
image_type& image,
|
|
const std::string& file_name
|
|
)
|
|
{
|
|
const image_file_type::type im_type = image_file_type::read_type(file_name);
|
|
switch (im_type)
|
|
{
|
|
case image_file_type::BMP: load_bmp(image, file_name); return;
|
|
case image_file_type::DNG: load_dng(image, file_name); return;
|
|
#ifdef DLIB_PNG_SUPPORT
|
|
case image_file_type::PNG: load_png(image, file_name); return;
|
|
#endif
|
|
#ifdef DLIB_JPEG_SUPPORT
|
|
case image_file_type::JPG: load_jpeg(image, file_name); return;
|
|
#endif
|
|
#ifdef DLIB_GIF_SUPPORT
|
|
case image_file_type::GIF:
|
|
{
|
|
image_view<image_type> img(image);
|
|
GifFileType* gif = DGifOpenFileName(file_name.c_str() DLIB_GIFLIB_HANDLE_DIFF_VERSIONS);
|
|
try
|
|
{
|
|
if (gif == 0) throw image_load_error("Couldn't open file " + file_name);
|
|
if (DGifSlurp(gif) != GIF_OK)
|
|
throw image_load_error("Error reading from " + file_name);
|
|
|
|
if (gif->ImageCount != 1) throw image_load_error("Dlib only supports reading GIF files containing one image.");
|
|
if (gif->SavedImages == 0) throw image_load_error("Unsupported GIF format 1.");
|
|
|
|
ColorMapObject* cmo=gif->SColorMap?gif->SColorMap:gif->SavedImages->ImageDesc.ColorMap;
|
|
|
|
if (cmo==0) throw image_load_error("Unsupported GIF format 2.");
|
|
if (cmo->Colors == 0) throw image_load_error("Unsupported GIF format 3.");
|
|
if (gif->SavedImages->ImageDesc.Width != gif->SWidth) throw image_load_error("Unsupported GIF format 4.");
|
|
if (gif->SavedImages->ImageDesc.Height != gif->SHeight) throw image_load_error("Unsupported GIF format 5.");
|
|
if (gif->SavedImages->RasterBits == 0) throw image_load_error("Unsupported GIF format 6.");
|
|
if (gif->Image.Top != 0) throw image_load_error("Unsupported GIF format 7.");
|
|
if (gif->Image.Left != 0) throw image_load_error("Unsupported GIF format 8.");
|
|
|
|
img.set_size(gif->SHeight, gif->SWidth);
|
|
unsigned char* raster = gif->SavedImages->RasterBits;
|
|
GifColorType* colormap = cmo->Colors;
|
|
if (gif->Image.Interlace)
|
|
{
|
|
const long interlaced_offset[] = { 0, 4, 2, 1 };
|
|
const long interlaced_jumps[] = { 8, 8, 4, 2 };
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
for (long r = interlaced_offset[i]; r < img.nr(); r += interlaced_jumps[i])
|
|
{
|
|
for (long c = 0; c < img.nc(); ++c)
|
|
{
|
|
if (*raster >= cmo->ColorCount)
|
|
throw image_load_error("Invalid GIF color value");
|
|
rgb_pixel p;
|
|
p.red = colormap[*raster].Red;
|
|
p.green = colormap[*raster].Green;
|
|
p.blue = colormap[*raster].Blue;
|
|
assign_pixel(img[r][c], p);
|
|
++raster;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long r = 0; r < img.nr(); ++r)
|
|
{
|
|
for (long c = 0; c < img.nc(); ++c)
|
|
{
|
|
if (*raster >= cmo->ColorCount)
|
|
throw image_load_error("Invalid GIF color value");
|
|
rgb_pixel p;
|
|
p.red = colormap[*raster].Red;
|
|
p.green = colormap[*raster].Green;
|
|
p.blue = colormap[*raster].Blue;
|
|
assign_pixel(img[r][c], p);
|
|
++raster;
|
|
}
|
|
}
|
|
}
|
|
DGifCloseFile(gif DLIB_GIFLIB_HANDLE_DIFF_VERSIONS);
|
|
}
|
|
catch(...)
|
|
{
|
|
if (gif)
|
|
DGifCloseFile(gif DLIB_GIFLIB_HANDLE_DIFF_VERSIONS);
|
|
throw;
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
default: ;
|
|
}
|
|
|
|
if (im_type == image_file_type::JPG)
|
|
{
|
|
std::ostringstream sout;
|
|
sout << "Unable to load image in file " + file_name + ".\n" +
|
|
"You must #define DLIB_JPEG_SUPPORT and link to libjpeg to read JPEG files.\n" +
|
|
"Do this by following the instructions at http://dlib.net/compile.html.\n\n";
|
|
#ifdef _MSC_VER
|
|
sout << "Note that you must cause DLIB_JPEG_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, add it to the C/C++->Preprocessor->Preprocessor Definitions\n";
|
|
sout << "field in Visual Studio's Property Pages window so it takes effect for your entire application.";
|
|
#else
|
|
sout << "Note that you must cause DLIB_JPEG_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, use a compiler switch like -DDLIB_JPEG_SUPPORT\n";
|
|
sout << "so it takes effect for your entire application.";
|
|
#endif
|
|
throw image_load_error(sout.str());
|
|
}
|
|
else if (im_type == image_file_type::PNG)
|
|
{
|
|
std::ostringstream sout;
|
|
sout << "Unable to load image in file " + file_name + ".\n" +
|
|
"You must #define DLIB_PNG_SUPPORT and link to libpng to read PNG files.\n" +
|
|
"Do this by following the instructions at http://dlib.net/compile.html.\n\n";
|
|
#ifdef _MSC_VER
|
|
sout << "Note that you must cause DLIB_PNG_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, add it to the C/C++->Preprocessor->Preprocessor Definitions\n";
|
|
sout << "field in Visual Studio's Property Pages window so it takes effect for your entire application.\n";
|
|
#else
|
|
sout << "Note that you must cause DLIB_PNG_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, use a compiler switch like -DDLIB_PNG_SUPPORT\n";
|
|
sout << "so it takes effect for your entire application.";
|
|
#endif
|
|
throw image_load_error(sout.str());
|
|
}
|
|
else if (im_type == image_file_type::GIF)
|
|
{
|
|
std::ostringstream sout;
|
|
sout << "Unable to load image in file " + file_name + ".\n" +
|
|
"You must #define DLIB_GIF_SUPPORT and link to libgif to read GIF files.\n\n";
|
|
#ifdef _MSC_VER
|
|
sout << "Note that you must cause DLIB_GIF_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, add it to the C/C++->Preprocessor->Preprocessor Definitions\n";
|
|
sout << "field in Visual Studio's Property Pages window so it takes effect for your entire application.\n";
|
|
#else
|
|
sout << "Note that you must cause DLIB_GIF_SUPPORT to be defined for your entire project.\n";
|
|
sout << "So don't #define it in one file. Instead, use a compiler switch like -DDLIB_GIF_SUPPORT\n";
|
|
sout << "so it takes effect for your entire application.";
|
|
#endif
|
|
throw image_load_error(sout.str());
|
|
}
|
|
else
|
|
{
|
|
throw image_load_error("Unknown image file format: Unable to load image in file " + file_name);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_LOAd_IMAGE_Hh_
|
|
|