Fix bad rendering of AV_PIX_FMT_PAL8 (palette-ised) images (#1426).
[dcpomatic.git] / src / lib / image.cc
1 /*
2     Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /** @file src/image.cc
22  *  @brief A class to describe a video image.
23  */
24
25 #include "image.h"
26 #include "exceptions.h"
27 #include "timer.h"
28 #include "rect.h"
29 #include "util.h"
30 #include "compose.hpp"
31 #include "dcpomatic_socket.h"
32 #include <dcp/rgb_xyz.h>
33 #include <dcp/transfer_function.h>
34 extern "C" {
35 #include <libswscale/swscale.h>
36 #include <libavutil/pixfmt.h>
37 #include <libavutil/pixdesc.h>
38 #include <libavutil/frame.h>
39 }
40 #include <png.h>
41 #if HAVE_VALGRIND_MEMCHECK_H
42 #include <valgrind/memcheck.h>
43 #endif
44 #include <iostream>
45
46 #include "i18n.h"
47
48 using std::string;
49 using std::min;
50 using std::max;
51 using std::cout;
52 using std::cerr;
53 using std::list;
54 using std::runtime_error;
55 using boost::shared_ptr;
56 using dcp::Size;
57
58 int
59 Image::vertical_factor (int n) const
60 {
61         if (n == 0) {
62                 return 1;
63         }
64
65         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
66         if (!d) {
67                 throw PixelFormatError ("line_factor()", _pixel_format);
68         }
69
70         return pow (2.0f, d->log2_chroma_h);
71 }
72
73 int
74 Image::horizontal_factor (int n) const
75 {
76         if (n == 0) {
77                 return 1;
78         }
79
80         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
81         if (!d) {
82                 throw PixelFormatError ("sample_size()", _pixel_format);
83         }
84
85         return pow (2.0f, d->log2_chroma_w);
86 }
87
88 /** @param n Component index.
89  *  @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
90  */
91 dcp::Size
92 Image::sample_size (int n) const
93 {
94         return dcp::Size (
95                 lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
96                 lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
97                 );
98 }
99
100 /** @return Number of planes */
101 int
102 Image::planes () const
103 {
104         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
105         if (!d) {
106                 throw PixelFormatError ("planes()", _pixel_format);
107         }
108
109         if (_pixel_format == AV_PIX_FMT_PAL8) {
110                 return 2;
111         }
112
113         if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
114                 return 1;
115         }
116
117         return d->nb_components;
118 }
119
120 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
121  *  @param crop Amount to crop by.
122  *  @param inter_size Size to scale the cropped image to.
123  *  @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
124  *  @param yuv_to_rgb YUV to RGB transformation to use, if required.
125  *  @param out_format Output pixel format.
126  *  @param out_aligned true to make the output image aligned.
127  *  @param fast Try to be fast at the possible expense of quality; at present this means using
128  *  fast bilinear rather than bicubic scaling.
129  */
130 shared_ptr<Image>
131 Image::crop_scale_window (
132         Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
133         ) const
134 {
135         /* Empirical testing suggests that sws_scale() will crash if
136            the input image is not aligned.
137         */
138         DCPOMATIC_ASSERT (aligned ());
139
140         DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
141         DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
142
143         /* Here's an image of out_size.  Below we may write to it starting at an offset so we get some padding.
144            Hence we want to write in the following pattern:
145
146            block start   write start                                  line end
147            |..(padding)..|<------line-size------------->|..(padding)..|
148            |..(padding)..|<------line-size------------->|..(padding)..|
149            |..(padding)..|<------line-size------------->|..(padding)..|
150
151            where line-size is of the smaller (inter_size) image and the full padded line length is that of
152            out_size.  To get things to work we have to tell FFmpeg that the stride is that of out_size.
153            However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
154            specified *stride*.  This does not matter until we get to the last line:
155
156            block start   write start                                  line end
157            |..(padding)..|<------line-size------------->|XXXwrittenXXX|
158            |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
159            |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
160                                                                        ^^^^ out of bounds
161
162            To get around this, we ask Image to overallocate its buffers by the overrun.
163         */
164
165         shared_ptr<Image> out (new Image (out_format, out_size, out_aligned, (out_size.width - inter_size.width) / 2));
166         out->make_black ();
167
168         /* Size of the image after any crop */
169         dcp::Size const cropped_size = crop.apply (size ());
170
171         /* Scale context for a scale from cropped_size to inter_size */
172         struct SwsContext* scale_context = sws_getContext (
173                         cropped_size.width, cropped_size.height, pixel_format(),
174                         inter_size.width, inter_size.height, out_format,
175                         fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
176                 );
177
178         if (!scale_context) {
179                 throw runtime_error (N_("Could not allocate SwsContext"));
180         }
181
182         DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
183         int const lut[dcp::YUV_TO_RGB_COUNT] = {
184                 SWS_CS_ITU601,
185                 SWS_CS_ITU709
186         };
187
188         sws_setColorspaceDetails (
189                 scale_context,
190                 sws_getCoefficients (lut[yuv_to_rgb]), 0,
191                 sws_getCoefficients (lut[yuv_to_rgb]), 0,
192                 0, 1 << 16, 1 << 16
193                 );
194
195         AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
196         if (!in_desc) {
197                 throw PixelFormatError ("crop_scale_window()", _pixel_format);
198         }
199
200         /* Prepare input data pointers with crop */
201         uint8_t* scale_in_data[planes()];
202         for (int c = 0; c < planes(); ++c) {
203                 /* To work out the crop in bytes, start by multiplying
204                    the crop by the (average) bytes per pixel.  Then
205                    round down so that we don't crop a subsampled pixel until
206                    we've cropped all of its Y-channel pixels.
207                 */
208                 int const x = lrintf (bytes_per_pixel(c) * crop.left) & ~ ((int) in_desc->log2_chroma_w);
209                 scale_in_data[c] = data()[c] + x + stride()[c] * (crop.top / vertical_factor(c));
210         }
211
212         /* Corner of the image within out_size */
213         Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
214
215         AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
216         if (!out_desc) {
217                 throw PixelFormatError ("crop_scale_window()", out_format);
218         }
219
220         uint8_t* scale_out_data[out->planes()];
221         for (int c = 0; c < out->planes(); ++c) {
222                 /* See the note in the crop loop above */
223                 int const x = lrintf (out->bytes_per_pixel(c) * corner.x) & ~ ((int) out_desc->log2_chroma_w);
224                 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
225         }
226
227         sws_scale (
228                 scale_context,
229                 scale_in_data, stride(),
230                 0, cropped_size.height,
231                 scale_out_data, out->stride()
232                 );
233
234         sws_freeContext (scale_context);
235
236         return out;
237 }
238
239 shared_ptr<Image>
240 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
241 {
242         return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
243 }
244
245 /** @param out_size Size to scale to.
246  *  @param yuv_to_rgb YUVToRGB transform transform to use, if required.
247  *  @param out_format Output pixel format.
248  *  @param out_aligned true to make an aligned output image.
249  *  @param fast Try to be fast at the possible expense of quality; at present this means using
250  *  fast bilinear rather than bicubic scaling.
251  */
252 shared_ptr<Image>
253 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
254 {
255         /* Empirical testing suggests that sws_scale() will crash if
256            the input image is not aligned.
257         */
258         DCPOMATIC_ASSERT (aligned ());
259
260         shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
261
262         struct SwsContext* scale_context = sws_getContext (
263                 size().width, size().height, pixel_format(),
264                 out_size.width, out_size.height, out_format,
265                 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
266                 );
267
268         DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
269         int const lut[dcp::YUV_TO_RGB_COUNT] = {
270                 SWS_CS_ITU601,
271                 SWS_CS_ITU709
272         };
273
274         sws_setColorspaceDetails (
275                 scale_context,
276                 sws_getCoefficients (lut[yuv_to_rgb]), 0,
277                 sws_getCoefficients (lut[yuv_to_rgb]), 0,
278                 0, 1 << 16, 1 << 16
279                 );
280
281         sws_scale (
282                 scale_context,
283                 data(), stride(),
284                 0, size().height,
285                 scaled->data(), scaled->stride()
286                 );
287
288         sws_freeContext (scale_context);
289
290         return scaled;
291 }
292
293 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
294 void
295 Image::yuv_16_black (uint16_t v, bool alpha)
296 {
297         memset (data()[0], 0, sample_size(0).height * stride()[0]);
298         for (int i = 1; i < 3; ++i) {
299                 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
300                 int const lines = sample_size(i).height;
301                 for (int y = 0; y < lines; ++y) {
302                         /* We divide by 2 here because we are writing 2 bytes at a time */
303                         for (int x = 0; x < line_size()[i] / 2; ++x) {
304                                 p[x] = v;
305                         }
306                         p += stride()[i] / 2;
307                 }
308         }
309
310         if (alpha) {
311                 memset (data()[3], 0, sample_size(3).height * stride()[3]);
312         }
313 }
314
315 uint16_t
316 Image::swap_16 (uint16_t v)
317 {
318         return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
319 }
320
321 void
322 Image::make_black ()
323 {
324         /* U/V black value for 8-bit colour */
325         static uint8_t const eight_bit_uv =     (1 << 7) - 1;
326         /* U/V black value for 9-bit colour */
327         static uint16_t const nine_bit_uv =     (1 << 8) - 1;
328         /* U/V black value for 10-bit colour */
329         static uint16_t const ten_bit_uv =      (1 << 9) - 1;
330         /* U/V black value for 16-bit colour */
331         static uint16_t const sixteen_bit_uv =  (1 << 15) - 1;
332
333         switch (_pixel_format) {
334         case AV_PIX_FMT_YUV420P:
335         case AV_PIX_FMT_YUV422P:
336         case AV_PIX_FMT_YUV444P:
337         case AV_PIX_FMT_YUV411P:
338                 memset (data()[0], 0, sample_size(0).height * stride()[0]);
339                 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
340                 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
341                 break;
342
343         case AV_PIX_FMT_YUVJ420P:
344         case AV_PIX_FMT_YUVJ422P:
345         case AV_PIX_FMT_YUVJ444P:
346                 memset (data()[0], 0, sample_size(0).height * stride()[0]);
347                 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
348                 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
349                 break;
350
351         case AV_PIX_FMT_YUV422P9LE:
352         case AV_PIX_FMT_YUV444P9LE:
353                 yuv_16_black (nine_bit_uv, false);
354                 break;
355
356         case AV_PIX_FMT_YUV422P9BE:
357         case AV_PIX_FMT_YUV444P9BE:
358                 yuv_16_black (swap_16 (nine_bit_uv), false);
359                 break;
360
361         case AV_PIX_FMT_YUV422P10LE:
362         case AV_PIX_FMT_YUV444P10LE:
363                 yuv_16_black (ten_bit_uv, false);
364                 break;
365
366         case AV_PIX_FMT_YUV422P16LE:
367         case AV_PIX_FMT_YUV444P16LE:
368                 yuv_16_black (sixteen_bit_uv, false);
369                 break;
370
371         case AV_PIX_FMT_YUV444P10BE:
372         case AV_PIX_FMT_YUV422P10BE:
373                 yuv_16_black (swap_16 (ten_bit_uv), false);
374                 break;
375
376         case AV_PIX_FMT_YUVA420P9BE:
377         case AV_PIX_FMT_YUVA422P9BE:
378         case AV_PIX_FMT_YUVA444P9BE:
379                 yuv_16_black (swap_16 (nine_bit_uv), true);
380                 break;
381
382         case AV_PIX_FMT_YUVA420P9LE:
383         case AV_PIX_FMT_YUVA422P9LE:
384         case AV_PIX_FMT_YUVA444P9LE:
385                 yuv_16_black (nine_bit_uv, true);
386                 break;
387
388         case AV_PIX_FMT_YUVA420P10BE:
389         case AV_PIX_FMT_YUVA422P10BE:
390         case AV_PIX_FMT_YUVA444P10BE:
391                 yuv_16_black (swap_16 (ten_bit_uv), true);
392                 break;
393
394         case AV_PIX_FMT_YUVA420P10LE:
395         case AV_PIX_FMT_YUVA422P10LE:
396         case AV_PIX_FMT_YUVA444P10LE:
397                 yuv_16_black (ten_bit_uv, true);
398                 break;
399
400         case AV_PIX_FMT_YUVA420P16BE:
401         case AV_PIX_FMT_YUVA422P16BE:
402         case AV_PIX_FMT_YUVA444P16BE:
403                 yuv_16_black (swap_16 (sixteen_bit_uv), true);
404                 break;
405
406         case AV_PIX_FMT_YUVA420P16LE:
407         case AV_PIX_FMT_YUVA422P16LE:
408         case AV_PIX_FMT_YUVA444P16LE:
409                 yuv_16_black (sixteen_bit_uv, true);
410                 break;
411
412         case AV_PIX_FMT_RGB24:
413         case AV_PIX_FMT_ARGB:
414         case AV_PIX_FMT_RGBA:
415         case AV_PIX_FMT_ABGR:
416         case AV_PIX_FMT_BGRA:
417         case AV_PIX_FMT_RGB555LE:
418         case AV_PIX_FMT_RGB48LE:
419         case AV_PIX_FMT_RGB48BE:
420         case AV_PIX_FMT_XYZ12LE:
421                 memset (data()[0], 0, sample_size(0).height * stride()[0]);
422                 break;
423
424         case AV_PIX_FMT_UYVY422:
425         {
426                 int const Y = sample_size(0).height;
427                 int const X = line_size()[0];
428                 uint8_t* p = data()[0];
429                 for (int y = 0; y < Y; ++y) {
430                         for (int x = 0; x < X / 4; ++x) {
431                                 *p++ = eight_bit_uv; // Cb
432                                 *p++ = 0;            // Y0
433                                 *p++ = eight_bit_uv; // Cr
434                                 *p++ = 0;            // Y1
435                         }
436                 }
437                 break;
438         }
439
440         default:
441                 throw PixelFormatError ("make_black()", _pixel_format);
442         }
443 }
444
445 void
446 Image::make_transparent ()
447 {
448         if (_pixel_format != AV_PIX_FMT_BGRA) {
449                 throw PixelFormatError ("make_transparent()", _pixel_format);
450         }
451
452         memset (data()[0], 0, sample_size(0).height * stride()[0]);
453 }
454
455 void
456 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
457 {
458         /* We're blending BGRA images; first byte is blue, second byte is green, third byte red, fourth byte alpha */
459         DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA);
460         int const other_bpp = 4;
461
462         int start_tx = position.x;
463         int start_ox = 0;
464
465         if (start_tx < 0) {
466                 start_ox = -start_tx;
467                 start_tx = 0;
468         }
469
470         int start_ty = position.y;
471         int start_oy = 0;
472
473         if (start_ty < 0) {
474                 start_oy = -start_ty;
475                 start_ty = 0;
476         }
477
478         switch (_pixel_format) {
479         case AV_PIX_FMT_RGB24:
480         {
481                 /* Going onto RGB24.  First byte is red, second green, third blue */
482                 int const this_bpp = 3;
483                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
484                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
485                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
486                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
487                                 float const alpha = float (op[3]) / 255;
488                                 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
489                                 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
490                                 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
491
492                                 tp += this_bpp;
493                                 op += other_bpp;
494                         }
495                 }
496                 break;
497         }
498         case AV_PIX_FMT_BGRA:
499         {
500                 int const this_bpp = 4;
501                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
502                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
503                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
504                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
505                                 float const alpha = float (op[3]) / 255;
506                                 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
507                                 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
508                                 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
509                                 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
510
511                                 tp += this_bpp;
512                                 op += other_bpp;
513                         }
514                 }
515                 break;
516         }
517         case AV_PIX_FMT_RGBA:
518         {
519                 int const this_bpp = 4;
520                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
521                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
522                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
523                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
524                                 float const alpha = float (op[3]) / 255;
525                                 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
526                                 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
527                                 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
528                                 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
529
530                                 tp += this_bpp;
531                                 op += other_bpp;
532                         }
533                 }
534                 break;
535         }
536         case AV_PIX_FMT_RGB48LE:
537         {
538                 int const this_bpp = 6;
539                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
540                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
541                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
542                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
543                                 float const alpha = float (op[3]) / 255;
544                                 /* Blend high bytes */
545                                 tp[1] = op[2] * alpha + tp[1] * (1 - alpha);
546                                 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
547                                 tp[5] = op[0] * alpha + tp[5] * (1 - alpha);
548
549                                 tp += this_bpp;
550                                 op += other_bpp;
551                         }
552                 }
553                 break;
554         }
555         case AV_PIX_FMT_XYZ12LE:
556         {
557                 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
558                 double fast_matrix[9];
559                 dcp::combined_rgb_to_xyz (conv, fast_matrix);
560                 double const * lut_in = conv.in()->lut (8, false);
561                 double const * lut_out = conv.out()->lut (16, true);
562                 int const this_bpp = 6;
563                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
564                         uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
565                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
566                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
567                                 float const alpha = float (op[3]) / 255;
568
569                                 /* Convert sRGB to XYZ; op is BGRA.  First, input gamma LUT */
570                                 double const r = lut_in[op[2]];
571                                 double const g = lut_in[op[1]];
572                                 double const b = lut_in[op[0]];
573
574                                 /* RGB to XYZ, including Bradford transform and DCI companding */
575                                 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
576                                 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
577                                 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
578
579                                 /* Out gamma LUT and blend */
580                                 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
581                                 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
582                                 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
583
584                                 tp += this_bpp / 2;
585                                 op += other_bpp;
586                         }
587                 }
588                 break;
589         }
590         case AV_PIX_FMT_YUV420P:
591         {
592                 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
593                 dcp::Size const ts = size();
594                 dcp::Size const os = yuv->size();
595                 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
596                         int const hty = ty / 2;
597                         int const hoy = oy / 2;
598                         uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
599                         uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
600                         uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
601                         uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
602                         uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
603                         uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
604                         uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
605                         for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
606                                 float const a = float(alpha[3]) / 255;
607                                 *tY = *oY * a + *tY * (1 - a);
608                                 *tU = *oU * a + *tU * (1 - a);
609                                 *tV = *oV * a + *tV * (1 - a);
610                                 ++tY;
611                                 ++oY;
612                                 if (tx % 2) {
613                                         ++tU;
614                                         ++tV;
615                                 }
616                                 if (ox % 2) {
617                                         ++oU;
618                                         ++oV;
619                                 }
620                                 alpha += 4;
621                         }
622                 }
623                 break;
624         }
625         case AV_PIX_FMT_YUV420P10:
626         {
627                 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
628                 dcp::Size const ts = size();
629                 dcp::Size const os = yuv->size();
630                 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
631                         int const hty = ty / 2;
632                         int const hoy = oy / 2;
633                         uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
634                         uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
635                         uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
636                         uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
637                         uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
638                         uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
639                         uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
640                         for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
641                                 float const a = float(alpha[3]) / 255;
642                                 *tY = *oY * a + *tY * (1 - a);
643                                 *tU = *oU * a + *tU * (1 - a);
644                                 *tV = *oV * a + *tV * (1 - a);
645                                 ++tY;
646                                 ++oY;
647                                 if (tx % 2) {
648                                         ++tU;
649                                         ++tV;
650                                 }
651                                 if (ox % 2) {
652                                         ++oU;
653                                         ++oV;
654                                 }
655                                 alpha += 4;
656                         }
657                 }
658                 break;
659         }
660         case AV_PIX_FMT_YUV422P10LE:
661         {
662                 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
663                 dcp::Size const ts = size();
664                 dcp::Size const os = yuv->size();
665                 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
666                         uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
667                         uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
668                         uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
669                         uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
670                         uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
671                         uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
672                         uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
673                         for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
674                                 float const a = float(alpha[3]) / 255;
675                                 *tY = *oY * a + *tY * (1 - a);
676                                 *tU = *oU * a + *tU * (1 - a);
677                                 *tV = *oV * a + *tV * (1 - a);
678                                 ++tY;
679                                 ++oY;
680                                 if (tx % 2) {
681                                         ++tU;
682                                         ++tV;
683                                 }
684                                 if (ox % 2) {
685                                         ++oU;
686                                         ++oV;
687                                 }
688                                 alpha += 4;
689                         }
690                 }
691                 break;
692         }
693         default:
694                 throw PixelFormatError ("alpha_blend()", _pixel_format);
695         }
696 }
697
698 void
699 Image::copy (shared_ptr<const Image> other, Position<int> position)
700 {
701         /* Only implemented for RGB24 onto RGB24 so far */
702         DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
703         DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
704
705         int const N = min (position.x + other->size().width, size().width) - position.x;
706         for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
707                 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
708                 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
709                 memcpy (tp, op, N * 3);
710         }
711 }
712
713 void
714 Image::read_from_socket (shared_ptr<Socket> socket)
715 {
716         for (int i = 0; i < planes(); ++i) {
717                 uint8_t* p = data()[i];
718                 int const lines = sample_size(i).height;
719                 for (int y = 0; y < lines; ++y) {
720                         socket->read (p, line_size()[i]);
721                         p += stride()[i];
722                 }
723         }
724 }
725
726 void
727 Image::write_to_socket (shared_ptr<Socket> socket) const
728 {
729         for (int i = 0; i < planes(); ++i) {
730                 uint8_t* p = data()[i];
731                 int const lines = sample_size(i).height;
732                 for (int y = 0; y < lines; ++y) {
733                         socket->write (p, line_size()[i]);
734                         p += stride()[i];
735                 }
736         }
737 }
738
739 float
740 Image::bytes_per_pixel (int c) const
741 {
742         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
743         if (!d) {
744                 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
745         }
746
747         if (c >= planes()) {
748                 return 0;
749         }
750
751         float bpp[4] = { 0, 0, 0, 0 };
752
753 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
754         bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
755         if (d->nb_components > 1) {
756                 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
757         }
758         if (d->nb_components > 2) {
759                 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
760         }
761         if (d->nb_components > 3) {
762                 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
763         }
764 #else
765         bpp[0] = floor ((d->comp[0].depth + 7) / 8);
766         if (d->nb_components > 1) {
767                 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
768         }
769         if (d->nb_components > 2) {
770                 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
771         }
772         if (d->nb_components > 3) {
773                 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
774         }
775 #endif
776
777         if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
778                 /* Not planar; sum them up */
779                 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
780         }
781
782         return bpp[c];
783 }
784
785 /** Construct a Image of a given size and format, allocating memory
786  *  as required.
787  *
788  *  @param p Pixel format.
789  *  @param s Size in pixels.
790  *  @param aligned true to make each row of this image aligned to a 32-byte boundary.
791  *  @param extra_pixels Amount of extra "run-off" memory to allocate at the end of each plane in pixels.
792  */
793 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned, int extra_pixels)
794         : _size (s)
795         , _pixel_format (p)
796         , _aligned (aligned)
797         , _extra_pixels (extra_pixels)
798 {
799         allocate ();
800 }
801
802 void
803 Image::allocate ()
804 {
805         _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
806         _data[0] = _data[1] = _data[2] = _data[3] = 0;
807
808         _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
809         _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
810
811         _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
812         _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
813
814         for (int i = 0; i < planes(); ++i) {
815                 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
816                 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
817
818                 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
819                    uses a 16-byte fetch to read three bytes (R/G/B) of image data.
820                    Hence on the last pixel of the last line it reads over the end of
821                    the actual data by 1 byte.  If the width of an image is a multiple
822                    of the stride alignment there will be no padding at the end of image lines.
823                    OS X crashes on this illegal read, though other operating systems don't
824                    seem to mind.  The nasty + 1 in this malloc makes sure there is always a byte
825                    for that instruction to read safely.
826
827                    Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
828                    over-reads by more then _avx.  I can't follow the code to work out how much,
829                    so I'll just over-allocate by 32 bytes and have done with it.  Empirical
830                    testing suggests that it works.
831                 */
832                 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
833 #if HAVE_VALGRIND_MEMCHECK_H
834                 /* The data between the end of the line size and the stride is undefined but processed by
835                    libswscale, causing lots of valgrind errors.  Mark it all defined to quell these errors.
836                 */
837                 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
838 #endif
839         }
840 }
841
842 Image::Image (Image const & other)
843         : boost::enable_shared_from_this<Image>(other)
844         , _size (other._size)
845         , _pixel_format (other._pixel_format)
846         , _aligned (other._aligned)
847         , _extra_pixels (other._extra_pixels)
848 {
849         allocate ();
850
851         for (int i = 0; i < planes(); ++i) {
852                 uint8_t* p = _data[i];
853                 uint8_t* q = other._data[i];
854                 int const lines = sample_size(i).height;
855                 for (int j = 0; j < lines; ++j) {
856                         memcpy (p, q, _line_size[i]);
857                         p += stride()[i];
858                         q += other.stride()[i];
859                 }
860         }
861 }
862
863 Image::Image (AVFrame* frame)
864         : _size (frame->width, frame->height)
865         , _pixel_format (static_cast<AVPixelFormat> (frame->format))
866         , _aligned (true)
867         , _extra_pixels (0)
868 {
869         allocate ();
870
871         for (int i = 0; i < planes(); ++i) {
872                 uint8_t* p = _data[i];
873                 uint8_t* q = frame->data[i];
874                 int const lines = sample_size(i).height;
875                 for (int j = 0; j < lines; ++j) {
876                         memcpy (p, q, _line_size[i]);
877                         p += stride()[i];
878                         /* AVFrame's linesize is what we call `stride' */
879                         q += frame->linesize[i];
880                 }
881         }
882 }
883
884 Image::Image (shared_ptr<const Image> other, bool aligned)
885         : _size (other->_size)
886         , _pixel_format (other->_pixel_format)
887         , _aligned (aligned)
888         , _extra_pixels (other->_extra_pixels)
889 {
890         allocate ();
891
892         for (int i = 0; i < planes(); ++i) {
893                 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
894                 uint8_t* p = _data[i];
895                 uint8_t* q = other->data()[i];
896                 int const lines = sample_size(i).height;
897                 for (int j = 0; j < lines; ++j) {
898                         memcpy (p, q, line_size()[i]);
899                         p += stride()[i];
900                         q += other->stride()[i];
901                 }
902         }
903 }
904
905 Image&
906 Image::operator= (Image const & other)
907 {
908         if (this == &other) {
909                 return *this;
910         }
911
912         Image tmp (other);
913         swap (tmp);
914         return *this;
915 }
916
917 void
918 Image::swap (Image & other)
919 {
920         std::swap (_size, other._size);
921         std::swap (_pixel_format, other._pixel_format);
922
923         for (int i = 0; i < 4; ++i) {
924                 std::swap (_data[i], other._data[i]);
925                 std::swap (_line_size[i], other._line_size[i]);
926                 std::swap (_stride[i], other._stride[i]);
927         }
928
929         std::swap (_aligned, other._aligned);
930         std::swap (_extra_pixels, other._extra_pixels);
931 }
932
933 /** Destroy a Image */
934 Image::~Image ()
935 {
936         for (int i = 0; i < planes(); ++i) {
937                 av_free (_data[i]);
938         }
939
940         av_free (_data);
941         av_free (_line_size);
942         av_free (_stride);
943 }
944
945 uint8_t * const *
946 Image::data () const
947 {
948         return _data;
949 }
950
951 int const *
952 Image::line_size () const
953 {
954         return _line_size;
955 }
956
957 int const *
958 Image::stride () const
959 {
960         return _stride;
961 }
962
963 dcp::Size
964 Image::size () const
965 {
966         return _size;
967 }
968
969 bool
970 Image::aligned () const
971 {
972         return _aligned;
973 }
974
975 PositionImage
976 merge (list<PositionImage> images)
977 {
978         if (images.empty ()) {
979                 return PositionImage ();
980         }
981
982         if (images.size() == 1) {
983                 return images.front ();
984         }
985
986         dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
987         for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
988                 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
989         }
990
991         shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
992         merged->make_transparent ();
993         for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
994                 merged->alpha_blend (i->image, i->position - all.position());
995         }
996
997         return PositionImage (merged, all.position ());
998 }
999
1000 bool
1001 operator== (Image const & a, Image const & b)
1002 {
1003         if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1004                 return false;
1005         }
1006
1007         for (int c = 0; c < a.planes(); ++c) {
1008                 if (a.sample_size(c).height != b.sample_size(c).height || a.line_size()[c] != b.line_size()[c] || a.stride()[c] != b.stride()[c]) {
1009                         return false;
1010                 }
1011
1012                 uint8_t* p = a.data()[c];
1013                 uint8_t* q = b.data()[c];
1014                 int const lines = a.sample_size(c).height;
1015                 for (int y = 0; y < lines; ++y) {
1016                         if (memcmp (p, q, a.line_size()[c]) != 0) {
1017                                 return false;
1018                         }
1019
1020                         p += a.stride()[c];
1021                         q += b.stride()[c];
1022                 }
1023         }
1024
1025         return true;
1026 }
1027
1028 /** Fade the image.
1029  *  @param f Amount to fade by; 0 is black, 1 is no fade.
1030  */
1031 void
1032 Image::fade (float f)
1033 {
1034         switch (_pixel_format) {
1035         case AV_PIX_FMT_YUV420P:
1036         case AV_PIX_FMT_YUV422P:
1037         case AV_PIX_FMT_YUV444P:
1038         case AV_PIX_FMT_YUV411P:
1039         case AV_PIX_FMT_YUVJ420P:
1040         case AV_PIX_FMT_YUVJ422P:
1041         case AV_PIX_FMT_YUVJ444P:
1042         case AV_PIX_FMT_RGB24:
1043         case AV_PIX_FMT_ARGB:
1044         case AV_PIX_FMT_RGBA:
1045         case AV_PIX_FMT_ABGR:
1046         case AV_PIX_FMT_BGRA:
1047         case AV_PIX_FMT_RGB555LE:
1048                 /* 8-bit */
1049                 for (int c = 0; c < 3; ++c) {
1050                         uint8_t* p = data()[c];
1051                         int const lines = sample_size(c).height;
1052                         for (int y = 0; y < lines; ++y) {
1053                                 uint8_t* q = p;
1054                                 for (int x = 0; x < line_size()[c]; ++x) {
1055                                         *q = int (float (*q) * f);
1056                                         ++q;
1057                                 }
1058                                 p += stride()[c];
1059                         }
1060                 }
1061                 break;
1062
1063         case AV_PIX_FMT_YUV422P9LE:
1064         case AV_PIX_FMT_YUV444P9LE:
1065         case AV_PIX_FMT_YUV422P10LE:
1066         case AV_PIX_FMT_YUV444P10LE:
1067         case AV_PIX_FMT_YUV422P16LE:
1068         case AV_PIX_FMT_YUV444P16LE:
1069         case AV_PIX_FMT_YUVA420P9LE:
1070         case AV_PIX_FMT_YUVA422P9LE:
1071         case AV_PIX_FMT_YUVA444P9LE:
1072         case AV_PIX_FMT_YUVA420P10LE:
1073         case AV_PIX_FMT_YUVA422P10LE:
1074         case AV_PIX_FMT_YUVA444P10LE:
1075         case AV_PIX_FMT_RGB48LE:
1076         case AV_PIX_FMT_XYZ12LE:
1077                 /* 16-bit little-endian */
1078                 for (int c = 0; c < 3; ++c) {
1079                         int const stride_pixels = stride()[c] / 2;
1080                         int const line_size_pixels = line_size()[c] / 2;
1081                         uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1082                         int const lines = sample_size(c).height;
1083                         for (int y = 0; y < lines; ++y) {
1084                                 uint16_t* q = p;
1085                                 for (int x = 0; x < line_size_pixels; ++x) {
1086                                         *q = int (float (*q) * f);
1087                                         ++q;
1088                                 }
1089                                 p += stride_pixels;
1090                         }
1091                 }
1092                 break;
1093
1094         case AV_PIX_FMT_YUV422P9BE:
1095         case AV_PIX_FMT_YUV444P9BE:
1096         case AV_PIX_FMT_YUV444P10BE:
1097         case AV_PIX_FMT_YUV422P10BE:
1098         case AV_PIX_FMT_YUVA420P9BE:
1099         case AV_PIX_FMT_YUVA422P9BE:
1100         case AV_PIX_FMT_YUVA444P9BE:
1101         case AV_PIX_FMT_YUVA420P10BE:
1102         case AV_PIX_FMT_YUVA422P10BE:
1103         case AV_PIX_FMT_YUVA444P10BE:
1104         case AV_PIX_FMT_YUVA420P16BE:
1105         case AV_PIX_FMT_YUVA422P16BE:
1106         case AV_PIX_FMT_YUVA444P16BE:
1107         case AV_PIX_FMT_RGB48BE:
1108                 /* 16-bit big-endian */
1109                 for (int c = 0; c < 3; ++c) {
1110                         int const stride_pixels = stride()[c] / 2;
1111                         int const line_size_pixels = line_size()[c] / 2;
1112                         uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1113                         int const lines = sample_size(c).height;
1114                         for (int y = 0; y < lines; ++y) {
1115                                 uint16_t* q = p;
1116                                 for (int x = 0; x < line_size_pixels; ++x) {
1117                                         *q = swap_16 (int (float (swap_16 (*q)) * f));
1118                                         ++q;
1119                                 }
1120                                 p += stride_pixels;
1121                         }
1122                 }
1123                 break;
1124
1125         case AV_PIX_FMT_UYVY422:
1126         {
1127                 int const Y = sample_size(0).height;
1128                 int const X = line_size()[0];
1129                 uint8_t* p = data()[0];
1130                 for (int y = 0; y < Y; ++y) {
1131                         for (int x = 0; x < X; ++x) {
1132                                 *p = int (float (*p) * f);
1133                                 ++p;
1134                         }
1135                 }
1136                 break;
1137         }
1138
1139         default:
1140                 throw PixelFormatError ("fade()", _pixel_format);
1141         }
1142 }
1143
1144 shared_ptr<const Image>
1145 Image::ensure_aligned (shared_ptr<const Image> image)
1146 {
1147         if (image->aligned()) {
1148                 return image;
1149         }
1150
1151         return shared_ptr<Image> (new Image (image, true));
1152 }
1153
1154 size_t
1155 Image::memory_used () const
1156 {
1157         size_t m = 0;
1158         for (int i = 0; i < planes(); ++i) {
1159                 m += _stride[i] * sample_size(i).height;
1160         }
1161         return m;
1162 }
1163
1164 class Memory
1165 {
1166 public:
1167         Memory ()
1168                 : data(0)
1169                 , size(0)
1170         {}
1171
1172         ~Memory ()
1173         {
1174                 free (data);
1175         }
1176
1177         uint8_t* data;
1178         size_t size;
1179 };
1180
1181 static void
1182 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1183 {
1184         Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1185         size_t size = mem->size + length;
1186
1187         if (mem->data) {
1188                 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1189         } else {
1190                 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1191         }
1192
1193         if (!mem->data) {
1194                 throw EncodeError (N_("could not allocate memory for PNG"));
1195         }
1196
1197         memcpy (mem->data + mem->size, data, length);
1198         mem->size += length;
1199 }
1200
1201 static void
1202 png_flush (png_structp)
1203 {
1204
1205 }
1206
1207 static void
1208 png_error_fn (png_structp png_ptr, char const * message)
1209 {
1210         reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1211 }
1212
1213 void
1214 Image::png_error (char const * message)
1215 {
1216         throw EncodeError (String::compose ("Error during PNG write: %1", message));
1217 }
1218
1219 dcp::Data
1220 Image::as_png () const
1221 {
1222         DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1223         DCPOMATIC_ASSERT (planes() == 1);
1224         DCPOMATIC_ASSERT (pixel_format() == AV_PIX_FMT_BGRA);
1225
1226         /* error handling? */
1227         png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1228         if (!png_ptr) {
1229                 throw EncodeError (N_("could not create PNG write struct"));
1230         }
1231
1232         Memory state;
1233
1234         png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1235
1236         png_infop info_ptr = png_create_info_struct(png_ptr);
1237         if (!info_ptr) {
1238                 png_destroy_write_struct (&png_ptr, &info_ptr);
1239                 throw EncodeError (N_("could not create PNG info struct"));
1240         }
1241
1242         png_set_IHDR (png_ptr, info_ptr, size().width, size().height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1243
1244         png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1245         for (int i = 0; i < size().height; ++i) {
1246                 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1247         }
1248
1249         png_write_info (png_ptr, info_ptr);
1250         png_write_image (png_ptr, row_pointers);
1251         png_write_end (png_ptr, info_ptr);
1252
1253         png_destroy_write_struct (&png_ptr, &info_ptr);
1254         png_free (png_ptr, row_pointers);
1255
1256         return dcp::Data (state.data, state.size);
1257 }