Commit 4ec6d607 authored by Manuel Günther's avatar Manuel Günther

Step 1: get image extension based on file content

parent f1a67da0
Pipeline #3620 failed with stage
in 36 minutes and 31 seconds
......@@ -29,12 +29,75 @@
#include <bob.io.image/tiff.h>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <algorithm>
namespace bob { namespace io { namespace image {
inline bool is_color_image(const std::string& filename){
std::string extension = boost::filesystem::path(filename).extension().string();
inline const std::string& get_correct_image_extension(const std::string& image_name){
// global map of known magic numbers
// these numbers are based on: http://stackoverflow.com/questions/26350342/determining-the-extension-type-of-an-image-file-using-binary/26350431#26350431
static std::map<std::string, std::vector<std::vector<std::uint8_t>>> known_magic_numbers;
// initialize list, if not done yet
if (known_magic_numbers.empty()){
// BMP
known_magic_numbers[".bmp"].push_back({ 0x42, 0x4D });
// NetPBM, see https://en.wikipedia.org/wiki/Netpbm_format
known_magic_numbers[".pbm"].push_back({ 0x50, 0x31 });// P1
known_magic_numbers[".pbm"].push_back({ 0x50, 0x34 });// P4
known_magic_numbers[".pgm"].push_back({ 0x50, 0x32 });// P2
known_magic_numbers[".pgm"].push_back({ 0x50, 0x35 });// P5
known_magic_numbers[".ppm"].push_back({ 0x50, 0x33 });// P3
known_magic_numbers[".ppm"].push_back({ 0x50, 0x36 });// P6
// TODO: what about P7?
#ifdef HAVE_GIFLIB
// GIF
known_magic_numbers[".gif"].push_back({ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 });
known_magic_numbers[".gif"].push_back({ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 });
#endif // HAVE_GIFLIB
#ifdef HAVE_LIBPNG
// PNG
known_magic_numbers[".png"].push_back({ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A });
#endif // HAVE_LIB_PNG
#ifdef HAVE_LIBJPEG
// JPEG
known_magic_numbers[".jpg"].push_back({ 0xFF, 0xD8, 0xFF });
known_magic_numbers[".jpg"].push_back({ 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20 });
#endif // HAVE_LIBJPEG
#ifdef HAVE_LIBTIFF
// TIFF
known_magic_numbers[".tiff"].push_back({ 0x0C, 0xED });
known_magic_numbers[".tiff"].push_back({ 0x49, 0x20, 0x49 });
known_magic_numbers[".tiff"].push_back({ 0x49, 0x49, 0x2A, 0x00 });
known_magic_numbers[".tiff"].push_back({ 0x4D, 0x4D, 0x00, 0x2A });
known_magic_numbers[".tiff"].push_back({ 0x4D, 0x4D, 0x00, 0x2B });
#endif // HAVE_LIBTIFF
}
// read first 8 bytes from file
static uint8_t image_bytes[8];
std::ifstream f(image_name);
if (!f) throw std::runtime_error("The given image '" + image_name + "' could not be opened for reading");
f.read(reinterpret_cast<char*>(image_bytes), 8);
// iterate over all extensions
for (auto eit = known_magic_numbers.begin(); eit != known_magic_numbers.end(); ++eit){
// iterate over all magic bytes
for (auto mit = eit->second.begin(); mit != eit->second.end(); ++mit){
// check magic number
if (std::equal(mit->begin(), mit->end(), image_bytes))
return eit->first;
}
}
throw std::runtime_error("The given image '" + image_name + "' does not contain an image of a known type");
}
inline bool is_color_image(const std::string& filename, std::string extension=""){
if (extension.empty())
extension = boost::filesystem::path(filename).extension().string();
boost::algorithm::to_lower(extension);
if (extension == ".bmp") return true;
#ifdef HAVE_GIFLIB
......@@ -55,8 +118,9 @@ inline bool is_color_image(const std::string& filename){
throw std::runtime_error("The filename extension '" + extension + "' is not known");
}
inline blitz::Array<uint8_t,3> read_color_image(const std::string& filename){
std::string extension = boost::filesystem::path(filename).extension().string();
inline blitz::Array<uint8_t,3> read_color_image(const std::string& filename, std::string extension=""){
if (extension.empty())
extension = boost::filesystem::path(filename).extension().string();
boost::algorithm::to_lower(extension);
if (extension == ".bmp") return read_bmp(filename);
#ifdef HAVE_GIFLIB
......@@ -76,8 +140,9 @@ inline blitz::Array<uint8_t,3> read_color_image(const std::string& filename){
throw std::runtime_error("The filename extension '" + extension + "' is not known or not supported for color images");
}
blitz::Array<uint8_t,2> read_gray_image(const std::string& filename){
std::string extension = boost::filesystem::path(filename).extension().string();
blitz::Array<uint8_t,2> read_gray_image(const std::string& filename, std::string extension=""){
if (extension.empty())
extension = boost::filesystem::path(filename).extension().string();
boost::algorithm::to_lower(extension);
#ifdef HAVE_LIBPNG
if (extension == ".png") return read_png<uint8_t,2>(filename);
......@@ -95,8 +160,9 @@ blitz::Array<uint8_t,2> read_gray_image(const std::string& filename){
}
void write_color_image(const blitz::Array<uint8_t,3>& image, const std::string& filename){
std::string extension = boost::filesystem::path(filename).extension().string();
void write_color_image(const blitz::Array<uint8_t,3>& image, const std::string& filename, std::string extension=""){
if (extension.empty())
extension = boost::filesystem::path(filename).extension().string();
boost::algorithm::to_lower(extension);
if (extension == ".bmp") return write_bmp(image, filename); // this will only work for T=uint8_t
#ifdef HAVE_GIFLIB
......@@ -116,8 +182,9 @@ void write_color_image(const blitz::Array<uint8_t,3>& image, const std::string&
throw std::runtime_error("The filename extension '" + extension + "' is not known or not supported for color images");
}
void write_gray_image(const blitz::Array<uint8_t,2>& image, const std::string& filename){
std::string extension = boost::filesystem::path(filename).extension().string();
void write_gray_image(const blitz::Array<uint8_t,2>& image, const std::string& filename, std::string extension=""){
if (extension.empty())
extension = boost::filesystem::path(filename).extension().string();
boost::algorithm::to_lower(extension);
#ifdef HAVE_LIBPNG
if (extension == ".png") return write_png(image, filename);
......
......@@ -59,8 +59,12 @@ BOB_TRY
// BMP; only color images are supported
boost::filesystem::path bmp(tempdir); bmp /= std::string("color.bmp");
bob::io::image::write_color_image(color_image, bmp.string());
if (bob::io::image::get_correct_image_extension(bmp.string()) != ".bmp")
throw std::runtime_error("BMP image type check did not succeed, check " + bmp.string());
if (!bob::io::image::is_color_image(bmp.string()))
throw std::runtime_error("BMP image " + bmp.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_bmp = bob::io::image::read_color_image(bmp.string());
blitz::Array<uint8_t, 3> color_bmp = bob::io::image::read_color_image(bmp.string(), ".bmp");
if (blitz::any(blitz::abs(color_image - color_bmp) > 0))
throw std::runtime_error("BMP image IO did not succeed, check " + bmp.string());
......@@ -69,8 +73,12 @@ BOB_TRY
// GIF; only color images are supported
boost::filesystem::path gif(tempdir); gif /= std::string("color.gif");
bob::io::image::write_color_image(color_image, gif.string());
if (bob::io::image::get_correct_image_extension(gif.string()) != ".gif")
throw std::runtime_error("GIF image type check did not succeed, check " + gif.string());
if (!bob::io::image::is_color_image(gif.string(), ".gif"))
throw std::runtime_error("GIF image " + gif.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_gif = bob::io::image::read_color_image(gif.string());
blitz::Array<uint8_t, 3> color_gif = bob::io::image::read_color_image(gif.string(), ".gif");
if (blitz::any(blitz::abs(color_image - color_gif) > 8)) // TODO: why is GIF not lossless?
throw std::runtime_error("GIF image IO did not succeed, check " + gif.string());
#endif
......@@ -78,19 +86,23 @@ BOB_TRY
// NetPBM
boost::filesystem::path pgm(tempdir); pgm /= std::string("gray.pgm");
bob::io::image::write_gray_image(gray_image, pgm.string());
if (bob::io::image::is_color_p_m(pgm.string()))
if (bob::io::image::get_correct_image_extension(pgm.string()) != ".pgm")
throw std::runtime_error("PGM image type check did not succeed, check " + pgm.string());
if (bob::io::image::is_color_p_m(pgm.string()) || bob::io::image::is_color_image(pgm.string(), ".pgm"))
throw std::runtime_error("PGM image " + pgm.string() + " is not gray as expected");
blitz::Array<uint8_t, 2> gray_pgm = bob::io::image::read_gray_image(pgm.string());
blitz::Array<uint8_t, 2> gray_pgm = bob::io::image::read_gray_image(pgm.string(), ".pgm");
if (blitz::any(blitz::abs(gray_image - gray_pgm) > 0))
throw std::runtime_error("PGM image IO did not succeed, check " + pgm.string());
boost::filesystem::path ppm(tempdir); ppm /= std::string("color.ppm");
bob::io::image::write_color_image(color_image, ppm.string());
if (!bob::io::image::is_color_p_m(ppm.string()))
if (bob::io::image::get_correct_image_extension(ppm.string()) != ".ppm")
throw std::runtime_error("PPM image type check did not succeed, check " + ppm.string());
if (!bob::io::image::is_color_p_m(ppm.string()) || !bob::io::image::is_color_image(ppm.string()))
throw std::runtime_error("PPM image " + ppm.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_ppm = bob::io::image::read_color_image(ppm.string());
blitz::Array<uint8_t, 3> color_ppm = bob::io::image::read_color_image(ppm.string(), ".ppm");
if (blitz::any(blitz::abs(color_image - color_ppm) > 0))
throw std::runtime_error("PPM image IO did not succeed, check " + ppm.string());
......@@ -99,7 +111,9 @@ BOB_TRY
// JPEG
boost::filesystem::path jpeg_gray(tempdir); jpeg_gray /= std::string("gray.jpg");
bob::io::image::write_gray_image(gray_image, jpeg_gray.string());
if (bob::io::image::is_color_image(jpeg_gray.string()))
if (bob::io::image::get_correct_image_extension(jpeg_gray.string()) != ".jpg")
throw std::runtime_error("JPEG image type check did not succeed, check " + jpeg_gray.string());
if (bob::io::image::is_color_image(jpeg_gray.string()) || bob::io::image::is_color_image(jpeg_gray.string()))
throw std::runtime_error("JPEG image " + jpeg_gray.string() + " is not gray as expected");
blitz::Array<uint8_t, 2> gray_jpeg = bob::io::image::read_gray_image(jpeg_gray.string());
......@@ -108,7 +122,9 @@ BOB_TRY
boost::filesystem::path jpeg_color(tempdir); jpeg_color /= std::string("color.jpg");
bob::io::image::write_color_image(color_image, jpeg_color.string());
if (!bob::io::image::is_color_image(jpeg_color.string()))
if (bob::io::image::get_correct_image_extension(jpeg_color.string()) != ".jpg")
throw std::runtime_error("JPEG image type check did not succeed, check " + jpeg_color.string());
if (!bob::io::image::is_color_image(jpeg_color.string()) || !bob::io::image::is_color_image(jpeg_color.string(), ".jpeg"))
throw std::runtime_error("JPEG image " + jpeg_color.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_jpeg = bob::io::image::read_color_image(jpeg_color.string());
......@@ -120,7 +136,9 @@ BOB_TRY
// PNG
boost::filesystem::path png_gray(tempdir); png_gray /= std::string("gray.png");
bob::io::image::write_gray_image(gray_image, png_gray.string());
if (bob::io::image::is_color_image(png_gray.string()))
if (bob::io::image::get_correct_image_extension(png_gray.string()) != ".png")
throw std::runtime_error("PNG image type check did not succeed, check " + png_gray.string());
if (bob::io::image::is_color_image(png_gray.string()) || bob::io::image::is_color_image(png_gray.string(), ".png"))
throw std::runtime_error("PNG image " + png_gray.string() + " is not gray as expected");
blitz::Array<uint8_t, 2> gray_png = bob::io::image::read_gray_image(png_gray.string());
......@@ -129,7 +147,9 @@ BOB_TRY
boost::filesystem::path png_color(tempdir); png_color /= std::string("color.png");
bob::io::image::write_color_image(color_image, png_color.string());
if (!bob::io::image::is_color_png(png_color.string()))
if (bob::io::image::get_correct_image_extension(png_color.string()) != ".png")
throw std::runtime_error("PNG image type check did not succeed, check " + png_color.string());
if (!bob::io::image::is_color_png(png_color.string()) || !bob::io::image::is_color_image(png_color.string()))
throw std::runtime_error("PNG image " + png_color.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_png = bob::io::image::read_color_image(png_color.string());
......@@ -141,7 +161,9 @@ BOB_TRY
// TIFF
boost::filesystem::path tiff_gray(tempdir); tiff_gray /= std::string("gray.tiff");
bob::io::image::write_gray_image(gray_image, tiff_gray.string());
if (bob::io::image::is_color_image(tiff_gray.string()))
if (bob::io::image::get_correct_image_extension(tiff_gray.string()) != ".tiff")
throw std::runtime_error("TIFF image type check did not succeed, check " + tiff_gray.string());
if (bob::io::image::is_color_image(tiff_gray.string()) || bob::io::image::is_color_image(tiff_gray.string(), ".tif"))
throw std::runtime_error("TIFF image " + tiff_gray.string() + " is not gray as expected");
blitz::Array<uint8_t, 2> gray_tiff = bob::io::image::read_gray_image(tiff_gray.string());
......@@ -150,7 +172,9 @@ BOB_TRY
boost::filesystem::path tiff_color(tempdir); tiff_color /= std::string("color.tiff");
bob::io::image::write_color_image(color_image, tiff_color.string());
if (!bob::io::image::is_color_image(tiff_color.string()))
if (bob::io::image::get_correct_image_extension(tiff_color.string()) != ".tiff")
throw std::runtime_error("TIFF image type check did not succeed, check " + tiff_color.string());
if (!bob::io::image::is_color_image(tiff_color.string()) || !bob::io::image::is_color_image(tiff_color.string(), ".tiff"))
throw std::runtime_error("TIFF image " + tiff_color.string() + " is not color as expected");
blitz::Array<uint8_t, 3> color_tiff = bob::io::image::read_color_image(tiff_color.string());
......
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