diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-07-15 00:14:28 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-07-15 00:14:28 +0100 |
| commit | bb767c7e338414beee132af3e96829c1448e214b (patch) | |
| tree | bec2858dcc7225a9bcc2acd8170c25508f6df6cb /src/lib/tiff_decoder.cc | |
| parent | 66c9be6bdb1361e5681e094a0c8170d268aa9518 (diff) | |
Move things round a bit.
Diffstat (limited to 'src/lib/tiff_decoder.cc')
| -rw-r--r-- | src/lib/tiff_decoder.cc | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc new file mode 100644 index 000000000..6738de49b --- /dev/null +++ b/src/lib/tiff_decoder.cc @@ -0,0 +1,224 @@ +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + + 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 <vector> +#include <string> +#include <iostream> +#include <stdint.h> +#include <boost/shared_ptr.hpp> +#include <boost/filesystem.hpp> +#include <tiffio.h> +extern "C" { +#include <libavformat/avformat.h> +} +#include "util.h" +#include "tiff_decoder.h" +#include "film_state.h" +#include "exceptions.h" +#include "image.h" +#include "options.h" + +using namespace std; +using namespace boost; + +/** @param fs FilmState of our Film. + * @param o Options. + * @param j Job that we are associated with, or 0. + * @param l Log that we can write to. + * @param minimal true to do the bare minimum of work; just run through the content. Useful for acquiring + * accurate frame counts as quickly as possible. This generates no video or audio output. + * @param ignore_length Ignore the content's claimed length when computing progress. + */ +TIFFDecoder::TIFFDecoder (boost::shared_ptr<const FilmState> fs, boost::shared_ptr<const Options> o, Job* j, Log* l, bool minimal, bool ignore_length) + : Decoder (fs, o, j, l, minimal, ignore_length) +{ + string const dir = _fs->content_path (); + + if (!filesystem::is_directory (dir)) { + throw DecodeError ("TIFF content must be in a directory"); + } + + for (filesystem::directory_iterator i = filesystem::directory_iterator (dir); i != filesystem::directory_iterator(); ++i) { + /* Aah, the sweet smell of progress */ +#if BOOST_FILESYSTEM_VERSION == 3 + string const ext = filesystem::path(*i).extension().string(); + string const l = filesystem::path(*i).leaf().generic_string(); +#else + string const ext = filesystem::path(*i).extension(); + string const l = i->leaf (); +#endif + if (ext == ".tif" || ext == ".tiff") { + _files.push_back (l); + } + } + + _files.sort (); + + _iter = _files.begin (); + +} + +int +TIFFDecoder::length_in_frames () const +{ + return _files.size (); +} + +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; +} + +AVSampleFormat +TIFFDecoder::audio_sample_format () const +{ + return AV_SAMPLE_FMT_NONE; +} + +bool +TIFFDecoder::do_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"); + } + + RGBFrameImage image (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); + + process_video (image.frame ()); + + ++_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 << _fs->content_path() << "/" << f; + return _fs->file (s.str ()); +} + +PixelFormat +TIFFDecoder::pixel_format () const +{ + return PIX_FMT_RGB24; +} + +int +TIFFDecoder::time_base_numerator () const +{ + return rint (_fs->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; +} + |
