Tests pass again.
[dcpomatic.git] / src / lib / tiff_decoder.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/tiff_decoder.cc
21  *  @brief A decoder which reads a numbered set of TIFF files, one per frame.
22  */
23
24 #include <vector>
25 #include <string>
26 #include <iostream>
27 #include <stdint.h>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/filesystem.hpp>
30 #include <tiffio.h>
31 extern "C" {
32 #include <libavformat/avformat.h>
33 }
34 #include "util.h"
35 #include "tiff_decoder.h"
36 #include "exceptions.h"
37 #include "image.h"
38 #include "options.h"
39 #include "film.h"
40
41 using std::cout;
42 using std::string;
43 using std::stringstream;
44 using boost::shared_ptr;
45
46 /** @param f Our Film.
47  *  @param o Options.
48  *  @param j Job that we are associated with, or 0.
49  */
50 TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j)
51         : Decoder (f, o, j)
52 {
53         string const dir = _film->content_path ();
54         
55         if (!boost::filesystem::is_directory (dir)) {
56                 throw DecodeError ("TIFF content must be in a directory");
57         }
58
59         for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (dir); i != boost::filesystem::directory_iterator(); ++i) {
60                 /* Aah, the sweet smell of progress */
61 #if BOOST_FILESYSTEM_VERSION == 3
62                 string const ext = boost::filesystem::path(*i).extension().string();
63                 string const l = boost::filesystem::path(*i).leaf().generic_string();
64 #else
65                 string const ext = boost::filesystem::path(*i).extension();
66                 string const l = i->leaf ();
67 #endif
68                 if (ext == ".tif" || ext == ".tiff") {
69                         _files.push_back (l);
70                 }
71         }
72
73         _files.sort ();
74
75         _iter = _files.begin ();
76 }
77
78 float
79 TIFFDecoder::frames_per_second () const
80 {
81         /* We don't know */
82         return 0;
83 }
84
85 Size
86 TIFFDecoder::native_size () const
87 {
88         if (_files.empty ()) {
89                 throw DecodeError ("no TIFF files found");
90         }
91         
92         TIFF* t = TIFFOpen (file_path (_files.front()).c_str (), "r");
93         if (t == 0) {
94                 throw DecodeError ("could not open TIFF file");
95         }
96
97         uint32_t width;
98         TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width);
99         uint32_t height;
100         TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height);
101
102         return Size (width, height);
103 }
104
105 int
106 TIFFDecoder::audio_channels () const
107 {
108         /* No audio */
109         return 0;
110 }
111
112 int
113 TIFFDecoder::audio_sample_rate () const
114 {
115         return 0;
116 }
117
118 int64_t
119 TIFFDecoder::audio_channel_layout () const
120 {
121         return 0;
122 }
123
124 bool
125 TIFFDecoder::pass ()
126 {
127         if (_iter == _files.end ()) {
128                 return true;
129         }
130
131         TIFF* t = TIFFOpen (file_path (*_iter).c_str (), "r");
132         if (t == 0) {
133                 throw DecodeError ("could not open TIFF file");
134         }
135
136         uint32_t width;
137         TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width);
138         uint32_t height;
139         TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height);
140
141         int const num_pixels = width * height;
142         uint32_t * raster = (uint32_t *) _TIFFmalloc (num_pixels * sizeof (uint32_t));
143         if (raster == 0) {
144                 throw DecodeError ("could not allocate memory to decode TIFF file");
145         }
146
147         if (TIFFReadRGBAImage (t, width, height, raster, 0) < 0) {
148                 throw DecodeError ("could not read TIFF data");
149         }
150
151         shared_ptr<CompactImage> image (new CompactImage (PIX_FMT_RGB24, Size (width, height)));
152
153         uint8_t* p = image->data()[0];
154         for (uint32_t y = 0; y < height; ++y) {
155                 for (uint32_t x = 0; x < width; ++x) {
156                         uint32_t const i = (height - y - 1) * width + x;
157                         *p++ = raster[i] & 0xff;
158                         *p++ = (raster[i] & 0xff00) >> 8;
159                         *p++ = (raster[i] & 0xff0000) >> 16;
160                 }
161         }
162
163         _TIFFfree (raster);
164         TIFFClose (t);
165
166         emit_video (image);
167
168         ++_iter;
169         return false;
170 }
171
172 /** @param file name within our content directory
173  *  @return full path to the file
174  */
175 string
176 TIFFDecoder::file_path (string f) const
177 {
178         stringstream s;
179         s << _film->content_path() << "/" << f;
180         return _film->file (s.str ());
181 }
182
183 PixelFormat
184 TIFFDecoder::pixel_format () const
185 {
186         return PIX_FMT_RGB24;
187 }
188
189 int
190 TIFFDecoder::time_base_numerator () const
191 {
192         return dcp_frame_rate(_film->frames_per_second()).frames_per_second;
193 }
194
195
196 int
197 TIFFDecoder::time_base_denominator () const
198 {
199         return 1;
200 }
201
202 int
203 TIFFDecoder::sample_aspect_ratio_numerator () const
204 {
205         /* XXX */
206         return 1;
207 }
208
209 int
210 TIFFDecoder::sample_aspect_ratio_denominator () const
211 {
212         /* XXX */
213         return 1;
214 }