diff options
Diffstat (limited to 'ml/dlib/dlib/image_saver')
-rw-r--r-- | ml/dlib/dlib/image_saver/dng_shared.h | 288 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/image_saver.h | 688 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/image_saver_abstract.h | 129 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_jpeg.cpp | 175 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_jpeg.h | 82 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_jpeg_abstract.h | 52 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_png.cpp | 124 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_png.h | 162 | ||||
-rw-r--r-- | ml/dlib/dlib/image_saver/save_png_abstract.h | 50 |
9 files changed, 1750 insertions, 0 deletions
diff --git a/ml/dlib/dlib/image_saver/dng_shared.h b/ml/dlib/dlib/image_saver/dng_shared.h new file mode 100644 index 000000000..d098851b3 --- /dev/null +++ b/ml/dlib/dlib/image_saver/dng_shared.h @@ -0,0 +1,288 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_DNG_SHAREd_ +#define DLIB_DNG_SHAREd_ + +#include "../pixel.h" +#include <cmath> +#include "../uintn.h" + +namespace dlib +{ + + namespace dng_helpers_namespace + { + enum + { + grayscale = 1, + rgb, + hsi, + rgb_paeth, + rgb_alpha, + rgb_alpha_paeth, + grayscale_16bit, + grayscale_float + }; + + const unsigned long dng_magic_byte = 100; + + template <typename T> + rgb_pixel predictor_rgb_paeth (const T& img, long row, long col) + /* + This is similar to the Paeth filter from the PNG image format. + */ + { + // a = left, b = above, c = upper left + rgb_pixel a(0,0,0), b(0,0,0), c(0,0,0); + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + else + assign_pixel(a,(unsigned char)0); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + else + assign_pixel(c,(unsigned char)0); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + else + assign_pixel(b,(unsigned char)0); + + + rgb_pixel p; + p.red = a.red + b.red - c.red; + p.green = a.green + b.green - c.green; + p.blue = a.blue + b.blue - c.blue; + + short pa = std::abs((short)p.red - (short)a.red) + + std::abs((short)p.green - (short)a.green) + + std::abs((short)p.blue - (short)a.blue); + short pb = std::abs((short)p.red - (short)b.red) + + std::abs((short)p.green - (short)b.green) + + std::abs((short)p.blue - (short)b.blue); + short pc = std::abs((short)p.red - (short)c.red) + + std::abs((short)p.green - (short)c.green) + + std::abs((short)p.blue - (short)c.blue); + + if (pa <= pb && pa <= pc) + return a; + else if (pb <= pc) + return b; + else + return c; + } + + + template <typename T> + rgb_pixel predictor_rgb (const T& img, long row, long col) + { + // a = left, b = above, c = upper left + rgb_pixel a(0,0,0), b(0,0,0), c(0,0,0); + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + else + assign_pixel(a,(unsigned char)0); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + else + assign_pixel(c,(unsigned char)0); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + else + assign_pixel(b,(unsigned char)0); + + + rgb_pixel p; + p.red = a.red + b.red - c.red; + p.green = a.green + b.green - c.green; + p.blue = a.blue + b.blue - c.blue; + return p; + } + + template <typename T> + rgb_alpha_pixel predictor_rgb_alpha_paeth (const T& img, long row, long col) + /* + This is similar to the Paeth filter from the PNG image format. + */ + { + // a = left, b = above, c = upper left + rgb_alpha_pixel a, b, c; + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + else + assign_pixel(a,(unsigned char)0); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + else + assign_pixel(c,(unsigned char)0); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + else + assign_pixel(b,(unsigned char)0); + + + rgb_alpha_pixel p; + p.red = a.red + b.red - c.red; + p.green = a.green + b.green - c.green; + p.blue = a.blue + b.blue - c.blue; + + short pa = std::abs((short)p.red - (short)a.red) + + std::abs((short)p.green - (short)a.green) + + std::abs((short)p.blue - (short)a.blue); + short pb = std::abs((short)p.red - (short)b.red) + + std::abs((short)p.green - (short)b.green) + + std::abs((short)p.blue - (short)b.blue); + short pc = std::abs((short)p.red - (short)c.red) + + std::abs((short)p.green - (short)c.green) + + std::abs((short)p.blue - (short)c.blue); + + if (pa <= pb && pa <= pc) + return a; + else if (pb <= pc) + return b; + else + return c; + } + + + template <typename T> + rgb_alpha_pixel predictor_rgb_alpha (const T& img, long row, long col) + { + // a = left, b = above, c = upper left + rgb_alpha_pixel a, b, c; + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + else + assign_pixel(a,(unsigned char)0); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + else + assign_pixel(c,(unsigned char)0); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + else + assign_pixel(b,(unsigned char)0); + + + rgb_alpha_pixel p; + p.red = a.red + b.red - c.red; + p.green = a.green + b.green - c.green; + p.blue = a.blue + b.blue - c.blue; + p.alpha = a.alpha + b.alpha - c.alpha; + return p; + } + + + template <typename T> + hsi_pixel predictor_hsi (const T& img, long row, long col) + { + // a = left, b = above, c = upper left + hsi_pixel a(0,0,0), b(0,0,0), c(0,0,0); + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + else + assign_pixel(a,(unsigned char)0); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + else + assign_pixel(c,(unsigned char)0); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + else + assign_pixel(b,(unsigned char)0); + + + hsi_pixel p; + p.h = a.h + b.h - c.h; + p.s = a.s + b.s - c.s; + p.i = a.i + b.i - c.i; + return p; + } + + template <typename T> + unsigned char predictor_grayscale (const T& img, long row, long col) + { + // a = left, b = above, c = upper left + unsigned char a = 0, b = 0, c = 0; + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + + + unsigned char p = a + b - c; + return p; + } + + template <typename T> + uint16 predictor_grayscale_16 (const T& img, long row, long col) + { + // a = left, b = above, c = upper left + uint16 a = 0, b = 0, c = 0; + + + const long c1 = col-1; + const long r1 = row-1; + + if (c1 >= 0) + assign_pixel(a, img[row][c1]); + + if (c1 >= 0 && r1 >= 0) + assign_pixel(c, img[r1][c1]); + + if (r1 >= 0) + assign_pixel(b, img[r1][col]); + + + uint16 p = a + b - c; + return p; + } + + } +} + +#endif // DLIB_DNG_SHAREd_ + diff --git a/ml/dlib/dlib/image_saver/image_saver.h b/ml/dlib/dlib/image_saver/image_saver.h new file mode 100644 index 000000000..43a2717af --- /dev/null +++ b/ml/dlib/dlib/image_saver/image_saver.h @@ -0,0 +1,688 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_IMAGE_SAVEr_ +#define DLIB_IMAGE_SAVEr_ + +#include "image_saver_abstract.h" +#include <iostream> +#include <fstream> +#include <sstream> +#include "../algs.h" +#include "../pixel.h" +#include "../byte_orderer.h" +#include "../entropy_encoder.h" +#include "../entropy_encoder_model.h" +#include "dng_shared.h" +#include "../uintn.h" +#include "../dir_nav.h" +#include "../float_details.h" +#include "../vectorstream.h" +#include "../matrix/matrix_exp.h" +#include "../image_transforms/assign_image.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class image_save_error : public dlib::error { + public: image_save_error(const std::string& str) : error(EIMAGE_SAVE,str){} + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type, + bool grayscale = pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale + > + struct save_bmp_helper; + + + template <typename image_type> + struct save_bmp_helper<image_type,false> + { + static void save_bmp ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + // we are going to write out a 24bit color image. + byte_orderer::kernel_1a bo; + + out.write("BM",2); + + if (!out) + throw image_save_error("error writing image to output stream"); + + + unsigned long pad = 4 - (image.nc()*3)%4; + if (pad == 4) + pad = 0; + + unsigned long bfSize = 14 + 40 + (image.nc()*3 + pad)*image.nr(); + unsigned long bfReserved = 0; + unsigned long bfOffBits = 14 + 40; + unsigned long biSize = 40; + unsigned long biWidth = image.nc(); + unsigned long biHeight = image.nr(); + unsigned short biPlanes = 1; + unsigned short biBitCount = 24; + unsigned long biCompression = 0; + unsigned long biSizeImage = 0; + unsigned long biXPelsPerMeter = 0; + unsigned long biYPelsPerMeter = 0; + unsigned long biClrUsed = 0; + unsigned long biClrImportant = 0; + + bo.host_to_little(bfSize); + bo.host_to_little(bfOffBits); + bo.host_to_little(biSize); + bo.host_to_little(biWidth); + bo.host_to_little(biHeight); + bo.host_to_little(biPlanes); + bo.host_to_little(biBitCount); + + out.write((char*)&bfSize,4); + out.write((char*)&bfReserved,4); + out.write((char*)&bfOffBits,4); + out.write((char*)&biSize,4); + out.write((char*)&biWidth,4); + out.write((char*)&biHeight,4); + out.write((char*)&biPlanes,2); + out.write((char*)&biBitCount,2); + out.write((char*)&biCompression,4); + out.write((char*)&biSizeImage,4); + out.write((char*)&biXPelsPerMeter,4); + out.write((char*)&biYPelsPerMeter,4); + out.write((char*)&biClrUsed,4); + out.write((char*)&biClrImportant,4); + + + if (!out) + throw image_save_error("error writing image to output stream"); + + // now we write out the pixel data + for (long row = image.nr()-1; row >= 0; --row) + { + for (long col = 0; col < image.nc(); ++col) + { + rgb_pixel p; + p.red = 0; + p.green = 0; + p.blue = 0; + assign_pixel(p,image[row][col]); + out.write((char*)&p.blue,1); + out.write((char*)&p.green,1); + out.write((char*)&p.red,1); + } + + // write out some zeros so that this line is a multiple of 4 bytes + for (unsigned long i = 0; i < pad; ++i) + { + unsigned char p = 0; + out.write((char*)&p,1); + } + } + + if (!out) + throw image_save_error("error writing image to output stream"); + } + }; + + template <typename image_type> + struct save_bmp_helper<image_type,true> + { + static void save_bmp ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + // we are going to write out an 8bit color image. + byte_orderer::kernel_1a bo; + + out.write("BM",2); + + if (!out) + throw image_save_error("error writing image to output stream"); + + unsigned long pad = 4 - image.nc()%4; + if (pad == 4) + pad = 0; + + unsigned long bfSize = 14 + 40 + (image.nc() + pad)*image.nr() + 256*4; + unsigned long bfReserved = 0; + unsigned long bfOffBits = 14 + 40 + 256*4; + unsigned long biSize = 40; + unsigned long biWidth = image.nc(); + unsigned long biHeight = image.nr(); + unsigned short biPlanes = 1; + unsigned short biBitCount = 8; + unsigned long biCompression = 0; + unsigned long biSizeImage = 0; + unsigned long biXPelsPerMeter = 0; + unsigned long biYPelsPerMeter = 0; + unsigned long biClrUsed = 0; + unsigned long biClrImportant = 0; + + bo.host_to_little(bfSize); + bo.host_to_little(bfOffBits); + bo.host_to_little(biSize); + bo.host_to_little(biWidth); + bo.host_to_little(biHeight); + bo.host_to_little(biPlanes); + bo.host_to_little(biBitCount); + + out.write((char*)&bfSize,4); + out.write((char*)&bfReserved,4); + out.write((char*)&bfOffBits,4); + out.write((char*)&biSize,4); + out.write((char*)&biWidth,4); + out.write((char*)&biHeight,4); + out.write((char*)&biPlanes,2); + out.write((char*)&biBitCount,2); + out.write((char*)&biCompression,4); + out.write((char*)&biSizeImage,4); + out.write((char*)&biXPelsPerMeter,4); + out.write((char*)&biYPelsPerMeter,4); + out.write((char*)&biClrUsed,4); + out.write((char*)&biClrImportant,4); + + + // write out the color palette + for (unsigned int i = 0; i <= 255; ++i) + { + unsigned char ch = static_cast<unsigned char>(i); + out.write((char*)&ch,1); + out.write((char*)&ch,1); + out.write((char*)&ch,1); + ch = 0; + out.write((char*)&ch,1); + } + + if (!out) + throw image_save_error("error writing image to output stream"); + + // now we write out the pixel data + for (long row = image.nr()-1; row >= 0; --row) + { + for (long col = 0; col < image.nc(); ++col) + { + unsigned char p = 0; + assign_pixel(p,image[row][col]); + out.write((char*)&p,1); + } + + // write out some zeros so that this line is a multiple of 4 bytes + for (unsigned long i = 0; i < pad; ++i) + { + unsigned char p = 0; + out.write((char*)&p,1); + } + } + + if (!out) + throw image_save_error("error writing image to output stream"); + + } + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + inline typename disable_if<is_matrix<image_type> >::type save_bmp ( + const image_type& image, + std::ostream& out + ) + { + save_bmp_helper<image_type>::save_bmp(image,out); + } + + template < + typename EXP + > + inline void save_bmp ( + const matrix_exp<EXP>& image, + std::ostream& out + ) + { + array2d<typename EXP::type> temp; + assign_image(temp, image); + save_bmp_helper<array2d<typename EXP::type> >::save_bmp(temp,out); + } + +// ---------------------------------------------------------------------------------------- + + namespace dng_helpers_namespace + { + template < + typename image_type, + typename enabled = void + > + struct save_dng_helper; + + 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, typename enable_if<is_float_type<typename image_traits<image_type>::pixel_type> >::type > + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + 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 is_non_float_non8bit_grayscale + { + typedef typename image_traits<image_type>::pixel_type pixel_type; + const static bool value = pixel_traits<pixel_type>::grayscale && + sizeof(pixel_type) != 1 && + !is_float_type<pixel_type>::value; + }; + + template <typename image_type > + struct save_dng_helper<image_type, typename enable_if<is_non_float_non8bit_grayscale<image_type> >::type> + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + out.write("DNG",3); + unsigned long version = 1; + serialize(version,out); + unsigned long type = grayscale_16bit; + serialize(type,out); + serialize(image.nc(),out); + serialize(image.nr(),out); + + encoder_type encoder; + encoder.set_stream(out); + + eem_type eem(encoder); + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + uint16 cur; + assign_pixel(cur, image[r][c]); + cur -= predictor_grayscale_16(image,r,c); + unsigned char byte1 = cur&0xFF; + unsigned char byte2 = cur>>8; + eem.encode(byte2); + eem.encode(byte1); + } + } + // write out the magic byte to mark the end of the data + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + } + }; + + template <typename image_type> + struct is_8bit_grayscale + { + typedef typename image_traits<image_type>::pixel_type pixel_type; + const static bool value = pixel_traits<pixel_type>::grayscale && sizeof(pixel_type) == 1; + }; + + template <typename image_type> + struct save_dng_helper<image_type, typename enable_if<is_8bit_grayscale<image_type> >::type> + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + out.write("DNG",3); + unsigned long version = 1; + serialize(version,out); + unsigned long type = grayscale; + serialize(type,out); + serialize(image.nc(),out); + serialize(image.nr(),out); + + encoder_type encoder; + encoder.set_stream(out); + + eem_type eem(encoder); + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + unsigned char cur; + assign_pixel(cur, image[r][c]); + cur -= predictor_grayscale(image,r,c); + eem.encode(cur); + } + } + // write out the magic byte to mark the end of the data + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + } + }; + + template <typename image_type> + struct is_rgb_image + { + typedef typename image_traits<image_type>::pixel_type pixel_type; + const static bool value = pixel_traits<pixel_type>::rgb; + }; + + template <typename image_type> + struct save_dng_helper<image_type,typename enable_if<is_rgb_image<image_type> >::type> + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + out.write("DNG",3); + unsigned long version = 1; + serialize(version,out); + + unsigned long type = rgb; + // if this is a small image then we will use a different predictor + if (image.size() < 4000) + type = rgb_paeth; + + serialize(type,out); + serialize(image.nc(),out); + serialize(image.nr(),out); + + encoder_type encoder; + encoder.set_stream(out); + + rgb_pixel pre, cur; + eem_type eem(encoder); + + if (type == rgb) + { + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + pre = predictor_rgb(image,r,c); + assign_pixel(cur, image[r][c]); + + eem.encode((unsigned char)(cur.red - pre.red)); + eem.encode((unsigned char)(cur.green - pre.green)); + eem.encode((unsigned char)(cur.blue - pre.blue)); + } + } + } + else + { + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + pre = predictor_rgb_paeth(image,r,c); + assign_pixel(cur, image[r][c]); + + eem.encode((unsigned char)(cur.red - pre.red)); + eem.encode((unsigned char)(cur.green - pre.green)); + eem.encode((unsigned char)(cur.blue - pre.blue)); + } + } + } + // write out the magic byte to mark the end of the data + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + } + }; + + template <typename image_type> + struct is_rgb_alpha_image + { + typedef typename image_traits<image_type>::pixel_type pixel_type; + const static bool value = pixel_traits<pixel_type>::rgb_alpha; + }; + + template <typename image_type> + struct save_dng_helper<image_type,typename enable_if<is_rgb_alpha_image<image_type> >::type> + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + out.write("DNG",3); + unsigned long version = 1; + serialize(version,out); + + unsigned long type = rgb_alpha; + // if this is a small image then we will use a different predictor + if (image.size() < 4000) + type = rgb_alpha_paeth; + + serialize(type,out); + serialize(image.nc(),out); + serialize(image.nr(),out); + + encoder_type encoder; + encoder.set_stream(out); + + rgb_alpha_pixel pre, cur; + eem_type eem(encoder); + + if (type == rgb_alpha) + { + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + pre = predictor_rgb_alpha(image,r,c); + assign_pixel(cur, image[r][c]); + + eem.encode((unsigned char)(cur.red - pre.red)); + eem.encode((unsigned char)(cur.green - pre.green)); + eem.encode((unsigned char)(cur.blue - pre.blue)); + eem.encode((unsigned char)(cur.alpha - pre.alpha)); + } + } + } + else + { + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + pre = predictor_rgb_alpha_paeth(image,r,c); + assign_pixel(cur, image[r][c]); + + eem.encode((unsigned char)(cur.red - pre.red)); + eem.encode((unsigned char)(cur.green - pre.green)); + eem.encode((unsigned char)(cur.blue - pre.blue)); + eem.encode((unsigned char)(cur.alpha - pre.alpha)); + } + } + } + // write out the magic byte to mark the end of the data + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + } + }; + + template <typename image_type> + struct is_hsi_image + { + typedef typename image_traits<image_type>::pixel_type pixel_type; + const static bool value = pixel_traits<pixel_type>::hsi; + }; + + template <typename image_type> + struct save_dng_helper<image_type,typename enable_if<is_hsi_image<image_type> >::type> + { + static void save_dng ( + const image_type& image_, + std::ostream& out + ) + { + const_image_view<image_type> image(image_); + out.write("DNG",3); + unsigned long version = 1; + serialize(version,out); + unsigned long type = hsi; + serialize(type,out); + serialize(image.nc(),out); + serialize(image.nr(),out); + + encoder_type encoder; + encoder.set_stream(out); + + hsi_pixel pre, cur; + eem_type eem(encoder); + for (long r = 0; r < image.nr(); ++r) + { + for (long c = 0; c < image.nc(); ++c) + { + pre = predictor_hsi(image,r,c); + assign_pixel(cur, image[r][c]); + + eem.encode((unsigned char)(cur.h - pre.h)); + eem.encode((unsigned char)(cur.s - pre.s)); + eem.encode((unsigned char)(cur.i - pre.i)); + } + } + // write out the magic byte to mark the end of the data + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + eem.encode(dng_magic_byte); + } + }; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + inline typename disable_if<is_matrix<image_type> >::type save_dng ( + const image_type& image, + std::ostream& out + ) + { + using namespace dng_helpers_namespace; + save_dng_helper<image_type>::save_dng(image,out); + } + + template < + typename EXP + > + inline void save_dng ( + const matrix_exp<EXP>& image, + std::ostream& out + ) + { + array2d<typename EXP::type> temp; + assign_image(temp, image); + using namespace dng_helpers_namespace; + save_dng_helper<array2d<typename EXP::type> >::save_dng(temp,out); + } + +// ---------------------------------------------------------------------------------------- + + template <typename image_type> + void save_dng ( + const image_type& image, + const std::string& file_name + ) + { + std::ofstream fout(file_name.c_str(), std::ios::binary); + if (!fout) + throw image_save_error("Unable to open " + file_name + " for writing."); + save_dng(image, fout); + } + +// ---------------------------------------------------------------------------------------- + + template <typename image_type> + void save_bmp ( + const image_type& image, + const std::string& file_name + ) + { + std::ofstream fout(file_name.c_str(), std::ios::binary); + if (!fout) + throw image_save_error("Unable to open " + file_name + " for writing."); + save_bmp(image, fout); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_IMAGE_SAVEr_ + + + + diff --git a/ml/dlib/dlib/image_saver/image_saver_abstract.h b/ml/dlib/dlib/image_saver/image_saver_abstract.h new file mode 100644 index 000000000..82f91ed45 --- /dev/null +++ b/ml/dlib/dlib/image_saver/image_saver_abstract.h @@ -0,0 +1,129 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_IMAGE_SAVEr_ABSTRACT_ +#ifdef DLIB_IMAGE_SAVEr_ABSTRACT_ + +#include <iosfwd> +#include "../algs.h" +#include "../pixel.h" +#include "../image_processing/generic_image.h" + +namespace dlib +{ + class image_save_error : public dlib::error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an exception used to indicate a failure to save an image. + Its type member variable will be set to EIMAGE_SAVE. + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + void save_bmp ( + const image_type& image, + std::ostream& out + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or any kind of matrix expression. + ensures + - writes the image to the out stream in the Microsoft Windows BMP format. + - 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, it + will convert all color pixels into rgb_pixel and grayscale pixels into + uint8 type before saving to disk. + throws + - image_save_error + This exception is thrown if there is an error that prevents us + from saving the image. + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + void save_bmp ( + const image_type& image, + const std::string& file_name + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or any kind of matrix expression. + ensures + - opens the file indicated by file_name with an output file stream named fout + and performs: + save_bmp(image,fout); + !*/ + +// ---------------------------------------------------------------------------------------- + + /*! + dlib dng file format: + This is a file format I created for this library. It is a lossless + compressed image format that is similar to the PNG format but uses + the dlib PPM compression algorithms instead of the DEFLATE algorithm. + !*/ + + template < + typename image_type + > + void save_dng ( + const image_type& image, + std::ostream& out + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or any kind of matrix expression. + ensures + - writes the image to the out stream in the dlib dng format. + - 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, uint16, float, and 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 + from saving the image. + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + template <typename image_type> + void save_dng ( + const image_type& image, + const std::string& file_name + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or any kind of matrix expression. + ensures + - opens the file indicated by file_name with an output file stream named fout + and performs: + save_dng(image,fout); + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_IMAGE_SAVEr_ABSTRACT_ + + diff --git a/ml/dlib/dlib/image_saver/save_jpeg.cpp b/ml/dlib/dlib/image_saver/save_jpeg.cpp new file mode 100644 index 000000000..ef637fa7a --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_jpeg.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net), Nils Labugt +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_JPEG_SAVER_CPp_ +#define DLIB_JPEG_SAVER_CPp_ + +// only do anything with this file if DLIB_JPEG_SUPPORT is defined +#ifdef DLIB_JPEG_SUPPORT + +#include "../array2d.h" +#include "../pixel.h" +#include "save_jpeg.h" +#include <stdio.h> +#include <sstream> +#include <setjmp.h> +#include "image_saver.h" + +#ifdef DLIB_JPEG_STATIC +# include "../external/libjpeg/jpeglib.h" +#else +# include <jpeglib.h> +#endif + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct jpeg_saver_error_mgr + { + jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ + }; + + void jpeg_saver_error_exit (j_common_ptr cinfo) + { + /* cinfo->err really points to a jpeg_saver_error_mgr struct, so coerce pointer */ + jpeg_saver_error_mgr* myerr = (jpeg_saver_error_mgr*) cinfo->err; + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); + } + +// ---------------------------------------------------------------------------------------- + + void save_jpeg ( + const array2d<rgb_pixel>& img, + const std::string& filename, + int quality + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(img.size() != 0, + "\t save_jpeg()" + << "\n\t You can't save an empty image as a JPEG." + ); + DLIB_CASSERT(0 <= quality && quality <= 100, + "\t save_jpeg()" + << "\n\t Invalid quality value." + << "\n\t quality: " << quality + ); + + FILE* outfile = fopen(filename.c_str(), "wb"); + if (!outfile) + throw image_save_error("Can't open file " + filename + " for writing."); + + jpeg_compress_struct cinfo; + + jpeg_saver_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeg_saver_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_compress(&cinfo); + fclose(outfile); + throw image_save_error("save_jpeg: error while writing " + filename); + } + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile); + + cinfo.image_width = img.nc(); + cinfo.image_height = img.nr(); + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + jpeg_set_defaults(&cinfo); + jpeg_set_quality (&cinfo, quality, TRUE); + jpeg_start_compress(&cinfo, TRUE); + + // now write out the rows one at a time + while (cinfo.next_scanline < cinfo.image_height) { + JSAMPROW row_pointer = (JSAMPROW) &img[cinfo.next_scanline][0]; + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + fclose( outfile ); + } + +// ---------------------------------------------------------------------------------------- + + void save_jpeg ( + const array2d<unsigned char>& img, + const std::string& filename, + int quality + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(img.size() != 0, + "\t save_jpeg()" + << "\n\t You can't save an empty image as a JPEG." + ); + DLIB_CASSERT(0 <= quality && quality <= 100, + "\t save_jpeg()" + << "\n\t Invalid quality value." + << "\n\t quality: " << quality + ); + + + FILE* outfile = fopen(filename.c_str(), "wb"); + if (!outfile) + throw image_save_error("Can't open file " + filename + " for writing."); + + jpeg_compress_struct cinfo; + + jpeg_saver_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeg_saver_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_compress(&cinfo); + fclose(outfile); + throw image_save_error("save_jpeg: error while writing " + filename); + } + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile); + + cinfo.image_width = img.nc(); + cinfo.image_height = img.nr(); + cinfo.input_components = 1; + cinfo.in_color_space = JCS_GRAYSCALE; + jpeg_set_defaults(&cinfo); + jpeg_set_quality (&cinfo, quality, TRUE); + jpeg_start_compress(&cinfo, TRUE); + + // now write out the rows one at a time + while (cinfo.next_scanline < cinfo.image_height) { + JSAMPROW row_pointer = (JSAMPROW) &img[cinfo.next_scanline][0]; + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + fclose( outfile ); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_JPEG_SUPPORT + +#endif // DLIB_JPEG_SAVER_CPp_ + + + diff --git a/ml/dlib/dlib/image_saver/save_jpeg.h b/ml/dlib/dlib/image_saver/save_jpeg.h new file mode 100644 index 000000000..fb1808c44 --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_jpeg.h @@ -0,0 +1,82 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SAVE_JPEG_Hh_ +#define DLIB_SAVE_JPEG_Hh_ + +#include "save_jpeg_abstract.h" + +#include "../enable_if.h" +#include "../matrix.h" +#include "../array2d.h" +#include "../pixel.h" +#include "../image_processing/generic_image.h" +#include <string> + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + void save_jpeg ( + const array2d<rgb_pixel>& img, + const std::string& filename, + int quality = 75 + ); + +// ---------------------------------------------------------------------------------------- + + void save_jpeg ( + const array2d<unsigned char>& img, + const std::string& filename, + int quality = 75 + ); + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + typename disable_if<is_matrix<image_type> >::type save_jpeg( + const image_type& img, + const std::string& filename, + int quality = 75 + ) + { + // Convert any kind of grayscale image to an unsigned char image + if (pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale) + { + array2d<unsigned char> temp; + assign_image(temp, img); + save_jpeg(temp, filename, quality); + } + else + { + // This is some other kind of color image so just save it as an RGB image. + array2d<rgb_pixel> temp; + assign_image(temp, img); + save_jpeg(temp, filename, quality); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + void save_jpeg( + const matrix_exp<EXP>& img, + const std::string& file_name, + int quality = 75 + ) + { + array2d<typename EXP::type> temp; + assign_image(temp, img); + save_jpeg(temp, file_name, quality); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SAVE_JPEG_Hh_ + diff --git a/ml/dlib/dlib/image_saver/save_jpeg_abstract.h b/ml/dlib/dlib/image_saver/save_jpeg_abstract.h new file mode 100644 index 000000000..f441339b9 --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_jpeg_abstract.h @@ -0,0 +1,52 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SAVE_JPEG_ABSTRACT_Hh_ +#ifdef DLIB_SAVE_JPEG_ABSTRACT_Hh_ + +#include "../image_processing/generic_image.h" +#include "../pixel.h" +#include <string> + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + void save_jpeg ( + const image_type& img, + const std::string& filename, + int quality = 75 + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or a matrix expression + - image.size() != 0 + - 0 <= quality <= 100 + ensures + - writes the image to the file indicated by file_name in the JPEG format. + - 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, + save_jpeg() can only natively store rgb_pixel and uint8 pixel types. All + other pixel types will be converted into one of these types as appropriate + before being saved to disk. + - The quality value determines how lossy the compression is. Larger quality + values result in larger output images but the images will look better. + throws + - image_save_error + This exception is thrown if there is an error that prevents us from saving + the image. + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SAVE_JPEG_ABSTRACT_Hh_ + diff --git a/ml/dlib/dlib/image_saver/save_png.cpp b/ml/dlib/dlib/image_saver/save_png.cpp new file mode 100644 index 000000000..1c96b929c --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_png.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SAVE_PnG_CPPh_ +#define DLIB_SAVE_PnG_CPPh_ + +// only do anything with this file if DLIB_PNG_SUPPORT is defined +#ifdef DLIB_PNG_SUPPORT + +#include "save_png.h" +#include <cstdio> +#include <png.h> +#include "../byte_orderer.h" + +namespace dlib +{ + // Don't do anything when libpng calls us to tell us about an error. Just return to + // our own code and throw an exception (at the long jump target). + void png_reader_user_error_fn_silent(png_structp png_struct, png_const_charp ) + { + longjmp(png_jmpbuf(png_struct),1); + } + void png_reader_user_warning_fn_silent(png_structp , png_const_charp ) + { + } + + namespace impl + { + void impl_save_png ( + const std::string& file_name, + std::vector<unsigned char*>& row_pointers, + const long width, + const png_type type, + const int bit_depth + ) + { + + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + + /* Open the file */ + fp = fopen(file_name.c_str(), "wb"); + if (fp == NULL) + throw image_save_error("Unable to open " + file_name + " for writing."); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_reader_user_error_fn_silent, &png_reader_user_warning_fn_silent); + + if (png_ptr == NULL) + { + fclose(fp); + throw image_save_error("Error while writing PNG file " + file_name); + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + throw image_save_error("Error while writing PNG file " + file_name); + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + throw image_save_error("Error while writing PNG file " + file_name); + } + + int color_type = 0; + switch(type) + { + case png_type_rgb: color_type = PNG_COLOR_TYPE_RGB; break; + case png_type_rgb_alpha: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; + case png_type_gray: color_type = PNG_COLOR_TYPE_GRAY; break; + default: + { + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + throw image_save_error("Invalid color type"); + } + } + + + /* Set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + + + int png_transforms = PNG_TRANSFORM_IDENTITY; + byte_orderer bo; + if (bo.host_is_little_endian()) + png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN; + + const long height = row_pointers.size(); + + + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_set_rows(png_ptr, info_ptr, &row_pointers[0]); + png_write_png(png_ptr, info_ptr, png_transforms, NULL); + + /* Clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file */ + fclose(fp); + } + } +} + +#endif // DLIB_PNG_SUPPORT + +#endif // DLIB_SAVE_PnG_CPPh_ + + diff --git a/ml/dlib/dlib/image_saver/save_png.h b/ml/dlib/dlib/image_saver/save_png.h new file mode 100644 index 000000000..cddf03ff6 --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_png.h @@ -0,0 +1,162 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SAVE_PnG_Hh_ +#define DLIB_SAVE_PnG_Hh_ + +#include "save_png_abstract.h" +#include "image_saver.h" +#include "../array2d.h" +#include <vector> +#include <string> +#include "../pixel.h" +#include "../matrix/matrix_exp.h" +#include "../image_transforms/assign_image.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + enum png_type + { + png_type_rgb, + png_type_rgb_alpha, + png_type_gray, + }; + + void impl_save_png ( + const std::string& file_name, + std::vector<unsigned char*>& row_pointers, + const long width, + const png_type type, + const int bit_depth + ); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + typename disable_if<is_matrix<image_type> >::type save_png( + const image_type& img_, + const std::string& file_name + ) + { + const_image_view<image_type> img(img_); + + // make sure requires clause is not broken + DLIB_CASSERT(img.size() != 0, + "\t save_png()" + << "\n\t You can't save an empty image as a PNG" + ); + + +#ifndef DLIB_PNG_SUPPORT + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + You are getting this error because you are trying to use save_png() + but you haven't defined DLIB_PNG_SUPPORT. You must do so to use + this function. You must also make sure you set your build environment + to link against the libpng library. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + COMPILE_TIME_ASSERT(sizeof(image_type) == 0); +#else + std::vector<unsigned char*> row_pointers(img.nr()); + typedef typename image_traits<image_type>::pixel_type pixel_type; + + if (is_same_type<rgb_pixel,pixel_type>::value) + { + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_rgb, 8); + } + else if (is_same_type<rgb_alpha_pixel,pixel_type>::value) + { + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_rgb_alpha, 8); + } + else if (pixel_traits<pixel_type>::lab || pixel_traits<pixel_type>::hsi || pixel_traits<pixel_type>::rgb) + { + // convert from Lab or HSI to RGB (Or potentially RGB pixels that aren't laid out as R G B) + array2d<rgb_pixel> temp_img; + assign_image(temp_img, img_); + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&temp_img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_rgb, 8); + } + else if (pixel_traits<pixel_type>::rgb_alpha) + { + // convert from RGBA pixels that aren't laid out as R G B A + array2d<rgb_alpha_pixel> temp_img; + assign_image(temp_img, img_); + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&temp_img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_rgb_alpha, 8); + } + else // this is supposed to be grayscale + { + DLIB_CASSERT(pixel_traits<pixel_type>::grayscale, "impossible condition detected"); + + if (pixel_traits<pixel_type>::is_unsigned && sizeof(pixel_type) == 1) + { + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_gray, 8); + } + else if (pixel_traits<pixel_type>::is_unsigned && sizeof(pixel_type) == 2) + { + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_gray, 16); + } + else + { + // convert from whatever this is to 16bit grayscale + array2d<dlib::uint16> temp_img; + assign_image(temp_img, img_); + for (unsigned long i = 0; i < row_pointers.size(); ++i) + row_pointers[i] = (unsigned char*)(&temp_img[i][0]); + + impl::impl_save_png(file_name, row_pointers, img.nc(), impl::png_type_gray, 16); + } + } + + +#endif + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + void save_png( + const matrix_exp<EXP>& img, + const std::string& file_name + ) + { + array2d<typename EXP::type> temp; + assign_image(temp, img); + save_png(temp, file_name); + } + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "save_png.cpp" +#endif + +#endif // DLIB_SAVE_PnG_Hh_ + diff --git a/ml/dlib/dlib/image_saver/save_png_abstract.h b/ml/dlib/dlib/image_saver/save_png_abstract.h new file mode 100644 index 000000000..ae495d1f2 --- /dev/null +++ b/ml/dlib/dlib/image_saver/save_png_abstract.h @@ -0,0 +1,50 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SAVE_PnG_ABSTRACT_ +#ifdef DLIB_SAVE_PnG_ABSTRACT_ + +#include "../pixel.h" +#include "../image_processing/generic_image.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + void save_png ( + const image_type& image, + const std::string& file_name + ); + /*! + requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or a matrix expression + - image.size() != 0 + ensures + - writes the image to the file indicated by file_name in the PNG (Portable Network Graphics) + format. + - 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, save_png() can + only natively store the following pixel types: rgb_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. + throws + - image_save_error + This exception is thrown if there is an error that prevents us from saving + the image. + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SAVE_PnG_ABSTRACT_ + + + |