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