From 967dc3f4461d4b8caf809ebce7bdcb6e818809f0 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 14 Nov 2012 21:58:47 +0000 Subject: [PATCH] Use ImageMagick for tiff decoding too. --- src/lib/decoder_factory.cc | 9 +- src/lib/film.cc | 13 +- src/lib/imagemagick_decoder.cc | 47 ++++++-- src/lib/imagemagick_decoder.h | 11 +- src/lib/j2k_still_encoder.cc | 2 +- src/lib/make_dcp_job.cc | 2 +- src/lib/tiff_decoder.cc | 214 --------------------------------- src/lib/tiff_decoder.h | 70 ----------- src/lib/util.cc | 15 +++ src/lib/util.h | 1 + src/lib/wscript | 1 - wscript | 1 - 12 files changed, 67 insertions(+), 319 deletions(-) delete mode 100644 src/lib/tiff_decoder.cc delete mode 100644 src/lib/tiff_decoder.h diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc index d4a91d8d9..bb6eff971 100644 --- a/src/lib/decoder_factory.cc +++ b/src/lib/decoder_factory.cc @@ -23,7 +23,6 @@ #include #include "ffmpeg_decoder.h" -#include "tiff_decoder.h" #include "imagemagick_decoder.h" #include "film.h" @@ -35,12 +34,8 @@ decoder_factory ( shared_ptr f, shared_ptr o, Job* j ) { - if (boost::filesystem::is_directory (f->content_path ())) { - /* Assume a directory contains TIFFs */ - return shared_ptr (new TIFFDecoder (f, o, j)); - } - - if (f->content_type() == STILL) { + if (boost::filesystem::is_directory (f->content_path()) || f->content_type() == STILL) { + /* A single image file, or a directory of them */ return shared_ptr (new ImageMagickDecoder (f, o, j)); } diff --git a/src/lib/film.cc b/src/lib/film.cc index c38b59d9e..ac5b43a98 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -686,15 +686,12 @@ Film::content_path () const ContentType Film::content_type () const { -#if BOOST_FILESYSTEM_VERSION == 3 - string ext = boost::filesystem::path(_content).extension().string(); -#else - string ext = boost::filesystem::path(_content).extension(); -#endif + if (boost::filesystem::is_directory (_content)) { + /* Directory of images, we assume */ + return VIDEO; + } - transform (ext.begin(), ext.end(), ext.begin(), ::tolower); - - if (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png") { + if (still_image_file (_content)) { return STILL; } diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 53e1db879..7faf74c61 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -18,10 +18,12 @@ */ #include +#include #include #include "imagemagick_decoder.h" #include "image.h" #include "film.h" +#include "exceptions.h" using std::cout; using boost::shared_ptr; @@ -29,49 +31,76 @@ using boost::shared_ptr; ImageMagickDecoder::ImageMagickDecoder ( boost::shared_ptr f, boost::shared_ptr o, Job* j) : Decoder (f, o, j) - , _done (false) { - _magick_image = new Magick::Image (_film->content_path ()); + if (boost::filesystem::is_directory (_film->content_path())) { + for ( + boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (_film->content_path()); + i != boost::filesystem::directory_iterator(); + ++i) { + + if (still_image_file (i->path().string())) { + _files.push_back (i->path().string()); + } + } + } else { + _files.push_back (_film->content_path ()); + } + + _iter = _files.begin (); } Size ImageMagickDecoder::native_size () const { - return Size (_magick_image->columns(), _magick_image->rows()); + if (_files.empty ()) { + throw DecodeError ("no still image files found"); + } + + /* Look at the first file and assume its size holds for all */ + using namespace MagickCore; + Magick::Image* image = new Magick::Image (_film->content_path ()); + Size const s = Size (image->columns(), image->rows()); + delete image; + + return s; } bool ImageMagickDecoder::pass () { - using namespace MagickCore; - - if (_done) { + if (_iter == _files.end()) { return true; } + + using namespace MagickCore; + Magick::Image* magick_image = new Magick::Image (_film->content_path ()); + Size size = native_size (); shared_ptr image (new CompactImage (PIX_FMT_RGB24, size)); uint8_t* p = image->data()[0]; for (int y = 0; y < size.height; ++y) { for (int x = 0; x < size.width; ++x) { - Magick::Color c = _magick_image->pixelColor (x, y); + Magick::Color c = magick_image->pixelColor (x, y); *p++ = c.redQuantum() * 255 / QuantumRange; *p++ = c.greenQuantum() * 255 / QuantumRange; *p++ = c.blueQuantum() * 255 / QuantumRange; } - } + + delete magick_image; emit_video (image); - _done = true; + ++_iter; return false; } PixelFormat ImageMagickDecoder::pixel_format () const { + /* XXX: always true? */ return PIX_FMT_RGB24; } diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 1bf50378b..6506d0177 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -29,7 +29,8 @@ public: ImageMagickDecoder (boost::shared_ptr, boost::shared_ptr, Job *); float frames_per_second () const { - return static_frames_per_second (); + /* We don't know */ + return 0; } Size native_size () const; @@ -50,10 +51,6 @@ public: return false; } - static float static_frames_per_second () { - return 24; - } - protected: bool pass (); PixelFormat pixel_format () const; @@ -77,6 +74,6 @@ protected: } private: - Magick::Image* _magick_image; - bool _done; + std::list _files; + std::list::iterator _iter; }; diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc index a4ac54e7a..dd6ef49b2 100644 --- a/src/lib/j2k_still_encoder.cc +++ b/src/lib/j2k_still_encoder.cc @@ -64,7 +64,7 @@ J2KStillEncoder::do_process_video (shared_ptr yuv, shared_ptr s } string const real = _opt->frame_out_path (0, false); - for (int i = 1; i < (_film->still_duration() * ImageMagickDecoder::static_frames_per_second()); ++i) { + for (int i = 1; i < (_film->still_duration() * 24); ++i) { if (!boost::filesystem::exists (_opt->frame_out_path (i, false))) { string const link = _opt->frame_out_path (i, false); #ifdef DVDOMATIC_POSIX diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index a1ffd9672..026724806 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -90,7 +90,7 @@ MakeDCPJob::run () frames = _film->dcp_length().get() / dfr.skip; break; case STILL: - frames = _film->still_duration() * ImageMagickDecoder::static_frames_per_second (); + frames = _film->still_duration() * 24; break; } diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc deleted file mode 100644 index a58ea9974..000000000 --- a/src/lib/tiff_decoder.cc +++ /dev/null @@ -1,214 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/tiff_decoder.cc - * @brief A decoder which reads a numbered set of TIFF files, one per frame. - */ - -#include -#include -#include -#include -#include -#include -#include -extern "C" { -#include -} -#include "util.h" -#include "tiff_decoder.h" -#include "exceptions.h" -#include "image.h" -#include "options.h" -#include "film.h" - -using std::cout; -using std::string; -using std::stringstream; -using boost::shared_ptr; - -/** @param f Our Film. - * @param o Options. - * @param j Job that we are associated with, or 0. - */ -TIFFDecoder::TIFFDecoder (boost::shared_ptr f, boost::shared_ptr o, Job* j) - : Decoder (f, o, j) -{ - string const dir = _film->content_path (); - - if (!boost::filesystem::is_directory (dir)) { - throw DecodeError ("TIFF content must be in a directory"); - } - - for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (dir); i != boost::filesystem::directory_iterator(); ++i) { - /* Aah, the sweet smell of progress */ -#if BOOST_FILESYSTEM_VERSION == 3 - string const ext = boost::filesystem::path(*i).extension().string(); - string const l = boost::filesystem::path(*i).leaf().generic_string(); -#else - string const ext = boost::filesystem::path(*i).extension(); - string const l = i->leaf (); -#endif - if (ext == ".tif" || ext == ".tiff") { - _files.push_back (l); - } - } - - _files.sort (); - - _iter = _files.begin (); -} - -float -TIFFDecoder::frames_per_second () const -{ - /* We don't know */ - return 0; -} - -Size -TIFFDecoder::native_size () const -{ - if (_files.empty ()) { - throw DecodeError ("no TIFF files found"); - } - - TIFF* t = TIFFOpen (file_path (_files.front()).c_str (), "r"); - if (t == 0) { - throw DecodeError ("could not open TIFF file"); - } - - uint32_t width; - TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width); - uint32_t height; - TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height); - - return Size (width, height); -} - -int -TIFFDecoder::audio_channels () const -{ - /* No audio */ - return 0; -} - -int -TIFFDecoder::audio_sample_rate () const -{ - return 0; -} - -int64_t -TIFFDecoder::audio_channel_layout () const -{ - return 0; -} - -bool -TIFFDecoder::pass () -{ - if (_iter == _files.end ()) { - return true; - } - - TIFF* t = TIFFOpen (file_path (*_iter).c_str (), "r"); - if (t == 0) { - throw DecodeError ("could not open TIFF file"); - } - - uint32_t width; - TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width); - uint32_t height; - TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height); - - int const num_pixels = width * height; - uint32_t * raster = (uint32_t *) _TIFFmalloc (num_pixels * sizeof (uint32_t)); - if (raster == 0) { - throw DecodeError ("could not allocate memory to decode TIFF file"); - } - - if (TIFFReadRGBAImage (t, width, height, raster, 0) < 0) { - throw DecodeError ("could not read TIFF data"); - } - - shared_ptr image (new CompactImage (PIX_FMT_RGB24, Size (width, height))); - - uint8_t* p = image->data()[0]; - for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; ++x) { - uint32_t const i = (height - y - 1) * width + x; - *p++ = raster[i] & 0xff; - *p++ = (raster[i] & 0xff00) >> 8; - *p++ = (raster[i] & 0xff0000) >> 16; - } - } - - _TIFFfree (raster); - TIFFClose (t); - - emit_video (image); - - ++_iter; - return false; -} - -/** @param file name within our content directory - * @return full path to the file - */ -string -TIFFDecoder::file_path (string f) const -{ - stringstream s; - s << _film->content_path() << "/" << f; - return _film->file (s.str ()); -} - -PixelFormat -TIFFDecoder::pixel_format () const -{ - return PIX_FMT_RGB24; -} - -int -TIFFDecoder::time_base_numerator () const -{ - return dcp_frame_rate(_film->frames_per_second()).frames_per_second; -} - - -int -TIFFDecoder::time_base_denominator () const -{ - return 1; -} - -int -TIFFDecoder::sample_aspect_ratio_numerator () const -{ - /* XXX */ - return 1; -} - -int -TIFFDecoder::sample_aspect_ratio_denominator () const -{ - /* XXX */ - return 1; -} diff --git a/src/lib/tiff_decoder.h b/src/lib/tiff_decoder.h deleted file mode 100644 index e6821eec6..000000000 --- a/src/lib/tiff_decoder.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/tiff_decoder.h - * @brief A decoder which reads a numbered set of TIFF files, one per frame. - */ - -#ifndef DVDOMATIC_TIFF_DECODER_H -#define DVDOMATIC_TIFF_DECODER_H - -#include -#include -#include -#include -#include "util.h" -#include "decoder.h" - -class Job; -class FilmState; -class Options; -class Image; - -/** @class TIFFDecoder. - * @brief A decoder which reads a numbered set of TIFF files, one per frame. - */ -class TIFFDecoder : public Decoder -{ -public: - TIFFDecoder (boost::shared_ptr, boost::shared_ptr, Job *); - - /* Methods to query our input video */ - float frames_per_second () const; - Size native_size () const; - int audio_channels () const; - int audio_sample_rate () const; - int64_t audio_channel_layout () const; - bool has_subtitles () const { - return false; - } - -private: - bool pass (); - PixelFormat pixel_format () const; - int time_base_numerator () const; - int time_base_denominator () const; - int sample_aspect_ratio_numerator () const; - int sample_aspect_ratio_denominator () const; - - std::string file_path (std::string) const; - std::list _files; - std::list::iterator _iter; -}; - -#endif diff --git a/src/lib/util.cc b/src/lib/util.cc index 5e82650a5..862ddc111 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -827,3 +828,17 @@ video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float fram { return ((int64_t) v * audio_sample_rate / frames_per_second); } + +bool +still_image_file (string f) +{ +#if BOOST_FILESYSTEM_VERSION == 3 + string ext = boost::filesystem::path(f).extension().string(); +#else + string ext = boost::filesystem::path(f).extension(); +#endif + + transform (ext.begin(), ext.end(), ext.begin(), ::tolower); + + return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png"); +} diff --git a/src/lib/util.h b/src/lib/util.h index bb68b6273..301a8bc4e 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -255,6 +255,7 @@ private: }; extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second); +extern bool still_image_file (std::string); #endif diff --git a/src/lib/wscript b/src/lib/wscript index ef4011c5f..6d006f559 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -48,7 +48,6 @@ def build(bld): sound_processor.cc stream.cc subtitle.cc - tiff_decoder.cc timer.cc transcode_job.cc transcoder.cc diff --git a/wscript b/wscript index d6cfd45c6..3b43f3aec 100644 --- a/wscript +++ b/wscript @@ -63,7 +63,6 @@ def configure(conf): conf.check_cfg(package = 'libdcp', atleast_version = '0.24', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True) conf.check_cfg(package = 'glib-2.0', args = '--cflags --libs', uselib_store = 'GLIB', mandatory = True) conf.check_cfg(package = '', path = 'Magick++-config', args = '--cppflags --cxxflags --libs', uselib_store = 'MAGICK', mandatory = True) - conf.check_cc(msg = 'Checking for library libtiff', function_name = 'TIFFOpen', header_name = 'tiffio.h', lib = 'tiff', uselib_store = 'TIFF') conf.check_cc(fragment = """ #include \n #include \n -- 2.30.2