7cca511dda884d0cdceb84178aea0030940f76fb
[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 namespace std;
42 using namespace boost;
43
44 /** @param f Our Film.
45  *  @param o Options.
46  *  @param j Job that we are associated with, or 0.
47  */
48 TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j)
49         : Decoder (f, o, j)
50 {
51         string const dir = _film->content_path ();
52         
53         if (!filesystem::is_directory (dir)) {
54                 throw DecodeError ("TIFF content must be in a directory");
55         }
56
57         for (filesystem::directory_iterator i = filesystem::directory_iterator (dir); i != filesystem::directory_iterator(); ++i) {
58                 /* Aah, the sweet smell of progress */
59 #if BOOST_FILESYSTEM_VERSION == 3
60                 string const ext = filesystem::path(*i).extension().string();
61                 string const l = filesystem::path(*i).leaf().generic_string();
62 #else
63                 string const ext = filesystem::path(*i).extension();
64                 string const l = i->leaf ();
65 #endif
66                 if (ext == ".tif" || ext == ".tiff") {
67                         _files.push_back (l);
68                 }
69         }
70
71         _files.sort ();
72
73         _iter = _files.begin ();
74
75 }
76
77 float
78 TIFFDecoder::frames_per_second () const
79 {
80         /* We don't know */
81         return 0;
82 }
83
84 Size
85 TIFFDecoder::native_size () const
86 {
87         if (_files.empty ()) {
88                 throw DecodeError ("no TIFF files found");
89         }
90         
91         TIFF* t = TIFFOpen (file_path (_files.front()).c_str (), "r");
92         if (t == 0) {
93                 throw DecodeError ("could not open TIFF file");
94         }
95
96         uint32_t width;
97         TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width);
98         uint32_t height;
99         TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height);
100
101         return Size (width, height);
102 }
103
104 int
105 TIFFDecoder::audio_channels () const
106 {
107         /* No audio */
108         return 0;
109 }
110
111 int
112 TIFFDecoder::audio_sample_rate () const
113 {
114         return 0;
115 }
116
117 AVSampleFormat
118 TIFFDecoder::audio_sample_format () const
119 {
120         return AV_SAMPLE_FMT_NONE;
121 }
122
123
124 int64_t
125 TIFFDecoder::audio_channel_layout () const
126 {
127         return 0;
128 }
129
130 bool
131 TIFFDecoder::pass ()
132 {
133         if (_iter == _files.end ()) {
134                 return true;
135         }
136
137         TIFF* t = TIFFOpen (file_path (*_iter).c_str (), "r");
138         if (t == 0) {
139                 throw DecodeError ("could not open TIFF file");
140         }
141
142         uint32_t width;
143         TIFFGetField (t, TIFFTAG_IMAGEWIDTH, &width);
144         uint32_t height;
145         TIFFGetField (t, TIFFTAG_IMAGELENGTH, &height);
146
147         int const num_pixels = width * height;
148         uint32_t * raster = (uint32_t *) _TIFFmalloc (num_pixels * sizeof (uint32_t));
149         if (raster == 0) {
150                 throw DecodeError ("could not allocate memory to decode TIFF file");
151         }
152
153         if (TIFFReadRGBAImage (t, width, height, raster, 0) < 0) {
154                 throw DecodeError ("could not read TIFF data");
155         }
156
157         RGBFrameImage image (Size (width, height));
158
159         uint8_t* p = image.data()[0];
160         for (uint32_t y = 0; y < height; ++y) {
161                 for (uint32_t x = 0; x < width; ++x) {
162                         uint32_t const i = (height - y - 1) * width + x;
163                         *p++ = raster[i] & 0xff;
164                         *p++ = (raster[i] & 0xff00) >> 8;
165                         *p++ = (raster[i] & 0xff0000) >> 16;
166                 }
167         }
168
169         _TIFFfree (raster);
170         TIFFClose (t);
171
172         process_video (image.frame ());
173
174         ++_iter;
175         return false;
176 }
177
178 /** @param file name within our content directory
179  *  @return full path to the file
180  */
181 string
182 TIFFDecoder::file_path (string f) const
183 {
184         stringstream s;
185         s << _film->content_path() << "/" << f;
186         return _film->file (s.str ());
187 }
188
189 PixelFormat
190 TIFFDecoder::pixel_format () const
191 {
192         return PIX_FMT_RGB24;
193 }
194
195 int
196 TIFFDecoder::time_base_numerator () const
197 {
198         return dcp_frame_rate(_film->frames_per_second()).frames_per_second;
199 }
200
201
202 int
203 TIFFDecoder::time_base_denominator () const
204 {
205         return 1;
206 }
207
208 int
209 TIFFDecoder::sample_aspect_ratio_numerator () const
210 {
211         /* XXX */
212         return 1;
213 }
214
215 int
216 TIFFDecoder::sample_aspect_ratio_denominator () const
217 {
218         /* XXX */
219         return 1;
220 }