Alpha blending fix from 1.x.
[dcpomatic.git] / src / lib / image.cc
1 /*
2     Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/image.cc
21  *  @brief A class to describe a video image.
22  */
23
24 #include <iostream>
25 extern "C" {
26 #include <libswscale/swscale.h>
27 #include <libavutil/pixfmt.h>
28 #include <libavutil/pixdesc.h>
29 }
30 #include "image.h"
31 #include "exceptions.h"
32 #include "scaler.h"
33 #include "timer.h"
34 #include "rect.h"
35 #include "md5_digester.h"
36
37 #include "i18n.h"
38
39 using std::string;
40 using std::min;
41 using std::cout;
42 using std::cerr;
43 using std::list;
44 using boost::shared_ptr;
45 using dcp::Size;
46
47 int
48 Image::line_factor (int n) const
49 {
50         if (n == 0) {
51                 return 1;
52         }
53
54         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
55         if (!d) {
56                 throw PixelFormatError ("lines()", _pixel_format);
57         }
58         
59         return pow (2.0f, d->log2_chroma_h);
60 }
61
62 /** @param n Component index.
63  *  @return Number of lines in the image for the given component.
64  */
65 int
66 Image::lines (int n) const
67 {
68         return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
69 }
70
71 /** @return Number of components */
72 int
73 Image::components () const
74 {
75         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
76         if (!d) {
77                 throw PixelFormatError ("components()", _pixel_format);
78         }
79
80         if ((d->flags & PIX_FMT_PLANAR) == 0) {
81                 return 1;
82         }
83         
84         return d->nb_components;
85 }
86
87 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
88 shared_ptr<Image>
89 Image::crop_scale_window (Crop crop, dcp::Size inter_size, dcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
90 {
91         DCPOMATIC_ASSERT (scaler);
92         /* Empirical testing suggests that sws_scale() will crash if
93            the input image is not aligned.
94         */
95         DCPOMATIC_ASSERT (aligned ());
96
97         DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
98         DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
99
100         /* Here's an image of out_size */
101         shared_ptr<Image> out (new Image (out_format, out_size, out_aligned));
102         out->make_black ();
103
104         /* Size of the image after any crop */
105         dcp::Size const cropped_size = crop.apply (size ());
106
107         /* Scale context for a scale from cropped_size to inter_size */
108         struct SwsContext* scale_context = sws_getContext (
109                         cropped_size.width, cropped_size.height, pixel_format(),
110                         inter_size.width, inter_size.height, out_format,
111                         scaler->ffmpeg_id (), 0, 0, 0
112                 );
113
114         if (!scale_context) {
115                 throw StringError (N_("Could not allocate SwsContext"));
116         }
117
118         /* Prepare input data pointers with crop */
119         uint8_t* scale_in_data[components()];
120         for (int c = 0; c < components(); ++c) {
121                 scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c));
122         }
123
124         /* Corner of the image within out_size */
125         Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
126
127         uint8_t* scale_out_data[out->components()];
128         for (int c = 0; c < out->components(); ++c) {
129                 scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y;
130         }
131
132         sws_scale (
133                 scale_context,
134                 scale_in_data, stride(),
135                 0, cropped_size.height,
136                 scale_out_data, out->stride()
137                 );
138
139         sws_freeContext (scale_context);
140
141         return out;     
142 }
143
144 shared_ptr<Image>
145 Image::scale (dcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
146 {
147         DCPOMATIC_ASSERT (scaler);
148         /* Empirical testing suggests that sws_scale() will crash if
149            the input image is not aligned.
150         */
151         DCPOMATIC_ASSERT (aligned ());
152
153         shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
154
155         struct SwsContext* scale_context = sws_getContext (
156                 size().width, size().height, pixel_format(),
157                 out_size.width, out_size.height, out_format,
158                 scaler->ffmpeg_id (), 0, 0, 0
159                 );
160
161         sws_scale (
162                 scale_context,
163                 data(), stride(),
164                 0, size().height,
165                 scaled->data(), scaled->stride()
166                 );
167
168         sws_freeContext (scale_context);
169
170         return scaled;
171 }
172
173 shared_ptr<Image>
174 Image::crop (Crop crop, bool aligned) const
175 {
176         dcp::Size cropped_size = crop.apply (size ());
177         shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
178
179         for (int c = 0; c < components(); ++c) {
180                 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
181                 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
182                    up, and we need to make sure that we copy over the width (up to the stride)
183                    rather than short of the width; hence the ceil() here.
184                 */
185                 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
186
187                 /* Start of the source line, cropped from the top but not the left */
188                 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
189                 uint8_t* out_p = out->data()[c];
190
191                 for (int y = 0; y < out->lines(c); ++y) {
192                         memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
193                         in_p += stride()[c];
194                         out_p += out->stride()[c];
195                 }
196         }
197
198         return out;
199 }
200
201 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
202 void
203 Image::yuv_16_black (uint16_t v, bool alpha)
204 {
205         memset (data()[0], 0, lines(0) * stride()[0]);
206         for (int i = 1; i < 3; ++i) {
207                 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
208                 for (int y = 0; y < lines(i); ++y) {
209                         /* We divide by 2 here because we are writing 2 bytes at a time */
210                         for (int x = 0; x < line_size()[i] / 2; ++x) {
211                                 p[x] = v;
212                         }
213                         p += stride()[i] / 2;
214                 }
215         }
216
217         if (alpha) {
218                 memset (data()[3], 0, lines(3) * stride()[3]);
219         }
220 }
221
222 uint16_t
223 Image::swap_16 (uint16_t v)
224 {
225         return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
226 }
227
228 void
229 Image::make_black ()
230 {
231         /* U/V black value for 8-bit colour */
232         static uint8_t const eight_bit_uv =     (1 << 7) - 1;
233         /* U/V black value for 9-bit colour */
234         static uint16_t const nine_bit_uv =     (1 << 8) - 1;
235         /* U/V black value for 10-bit colour */
236         static uint16_t const ten_bit_uv =      (1 << 9) - 1;
237         /* U/V black value for 16-bit colour */
238         static uint16_t const sixteen_bit_uv =  (1 << 15) - 1;
239         
240         switch (_pixel_format) {
241         case PIX_FMT_YUV420P:
242         case PIX_FMT_YUV422P:
243         case PIX_FMT_YUV444P:
244         case PIX_FMT_YUV411P:
245                 memset (data()[0], 0, lines(0) * stride()[0]);
246                 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
247                 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
248                 break;
249
250         case PIX_FMT_YUVJ420P:
251         case PIX_FMT_YUVJ422P:
252         case PIX_FMT_YUVJ444P:
253                 memset (data()[0], 0, lines(0) * stride()[0]);
254                 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
255                 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
256                 break;
257
258         case PIX_FMT_YUV422P9LE:
259         case PIX_FMT_YUV444P9LE:
260                 yuv_16_black (nine_bit_uv, false);
261                 break;
262
263         case PIX_FMT_YUV422P9BE:
264         case PIX_FMT_YUV444P9BE:
265                 yuv_16_black (swap_16 (nine_bit_uv), false);
266                 break;
267                 
268         case PIX_FMT_YUV422P10LE:
269         case PIX_FMT_YUV444P10LE:
270                 yuv_16_black (ten_bit_uv, false);
271                 break;
272
273         case PIX_FMT_YUV422P16LE:
274         case PIX_FMT_YUV444P16LE:
275                 yuv_16_black (sixteen_bit_uv, false);
276                 break;
277                 
278         case PIX_FMT_YUV444P10BE:
279         case PIX_FMT_YUV422P10BE:
280                 yuv_16_black (swap_16 (ten_bit_uv), false);
281                 break;
282
283         case AV_PIX_FMT_YUVA420P9BE:
284         case AV_PIX_FMT_YUVA422P9BE:
285         case AV_PIX_FMT_YUVA444P9BE:
286                 yuv_16_black (swap_16 (nine_bit_uv), true);
287                 break;
288                 
289         case AV_PIX_FMT_YUVA420P9LE:
290         case AV_PIX_FMT_YUVA422P9LE:
291         case AV_PIX_FMT_YUVA444P9LE:
292                 yuv_16_black (nine_bit_uv, true);
293                 break;
294                 
295         case AV_PIX_FMT_YUVA420P10BE:
296         case AV_PIX_FMT_YUVA422P10BE:
297         case AV_PIX_FMT_YUVA444P10BE:
298                 yuv_16_black (swap_16 (ten_bit_uv), true);
299                 break;
300                 
301         case AV_PIX_FMT_YUVA420P10LE:
302         case AV_PIX_FMT_YUVA422P10LE:
303         case AV_PIX_FMT_YUVA444P10LE:
304                 yuv_16_black (ten_bit_uv, true);
305                 break;
306                 
307         case AV_PIX_FMT_YUVA420P16BE:
308         case AV_PIX_FMT_YUVA422P16BE:
309         case AV_PIX_FMT_YUVA444P16BE:
310                 yuv_16_black (swap_16 (sixteen_bit_uv), true);
311                 break;
312                 
313         case AV_PIX_FMT_YUVA420P16LE:
314         case AV_PIX_FMT_YUVA422P16LE:
315         case AV_PIX_FMT_YUVA444P16LE:
316                 yuv_16_black (sixteen_bit_uv, true);
317                 break;
318
319         case PIX_FMT_RGB24:
320         case PIX_FMT_ARGB:
321         case PIX_FMT_RGBA:
322         case PIX_FMT_ABGR:
323         case PIX_FMT_BGRA:
324         case PIX_FMT_RGB555LE:
325         case PIX_FMT_RGB48LE:
326         case PIX_FMT_RGB48BE:
327                 memset (data()[0], 0, lines(0) * stride()[0]);
328                 break;
329
330         case PIX_FMT_UYVY422:
331         {
332                 int const Y = lines(0);
333                 int const X = line_size()[0];
334                 uint8_t* p = data()[0];
335                 for (int y = 0; y < Y; ++y) {
336                         for (int x = 0; x < X / 4; ++x) {
337                                 *p++ = eight_bit_uv; // Cb
338                                 *p++ = 0;            // Y0
339                                 *p++ = eight_bit_uv; // Cr
340                                 *p++ = 0;            // Y1
341                         }
342                 }
343                 break;
344         }
345
346         default:
347                 throw PixelFormatError ("make_black()", _pixel_format);
348         }
349 }
350
351 void
352 Image::make_transparent ()
353 {
354         if (_pixel_format != PIX_FMT_RGBA) {
355                 throw PixelFormatError ("make_transparent()", _pixel_format);
356         }
357
358         memset (data()[0], 0, lines(0) * stride()[0]);
359 }
360
361 void
362 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
363 {
364         DCPOMATIC_ASSERT (other->pixel_format() == PIX_FMT_RGBA);
365         int const other_bpp = 4;
366
367         int start_tx = position.x;
368         int start_ox = 0;
369
370         if (start_tx < 0) {
371                 start_ox = -start_tx;
372                 start_tx = 0;
373         }
374
375         int start_ty = position.y;
376         int start_oy = 0;
377
378         if (start_ty < 0) {
379                 start_oy = -start_ty;
380                 start_ty = 0;
381         }
382
383         switch (_pixel_format) {
384         case PIX_FMT_RGB24:
385         {
386                 int const this_bpp = 3;
387                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
388                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
389                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
390                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
391                                 float const alpha = float (op[3]) / 255;
392                                 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
393                                 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
394                                 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
395                                 
396                                 tp += this_bpp;
397                                 op += other_bpp;
398                         }
399                 }
400                 break;
401         }
402         case PIX_FMT_BGRA:
403         case PIX_FMT_RGBA:
404         {
405                 int const this_bpp = 4;
406                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
407                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
408                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
409                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
410                                 float const alpha = float (op[3]) / 255;
411                                 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
412                                 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
413                                 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
414                                 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
415                                 
416                                 tp += this_bpp;
417                                 op += other_bpp;
418                         }
419                 }
420                 break;
421         }
422         case PIX_FMT_RGB48LE:
423         {
424                 int const this_bpp = 6;
425                 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
426                         uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
427                         uint8_t* op = other->data()[0] + oy * other->stride()[0];
428                         for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
429                                 float const alpha = float (op[3]) / 255;
430                                 /* Blend high bytes */
431                                 tp[1] = op[0] * alpha + tp[1] * (1 - alpha);
432                                 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
433                                 tp[5] = op[2] * alpha + tp[5] * (1 - alpha);
434                                 
435                                 tp += this_bpp;
436                                 op += other_bpp;
437                         }
438                 }
439                 break;
440         }
441         default:
442                 DCPOMATIC_ASSERT (false);
443         }
444 }
445         
446 void
447 Image::copy (shared_ptr<const Image> other, Position<int> position)
448 {
449         /* Only implemented for RGB24 onto RGB24 so far */
450         DCPOMATIC_ASSERT (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
451         DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
452
453         int const N = min (position.x + other->size().width, size().width) - position.x;
454         for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
455                 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
456                 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
457                 memcpy (tp, op, N * 3);
458         }
459 }       
460
461 void
462 Image::read_from_socket (shared_ptr<Socket> socket)
463 {
464         for (int i = 0; i < components(); ++i) {
465                 uint8_t* p = data()[i];
466                 for (int y = 0; y < lines(i); ++y) {
467                         socket->read (p, line_size()[i]);
468                         p += stride()[i];
469                 }
470         }
471 }
472
473 void
474 Image::write_to_socket (shared_ptr<Socket> socket) const
475 {
476         for (int i = 0; i < components(); ++i) {
477                 uint8_t* p = data()[i];
478                 for (int y = 0; y < lines(i); ++y) {
479                         socket->write (p, line_size()[i]);
480                         p += stride()[i];
481                 }
482         }
483 }
484
485
486 float
487 Image::bytes_per_pixel (int c) const
488 {
489         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
490         if (!d) {
491                 throw PixelFormatError ("lines()", _pixel_format);
492         }
493
494         if (c >= components()) {
495                 return 0;
496         }
497
498         float bpp[4] = { 0, 0, 0, 0 };
499
500         bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
501         if (d->nb_components > 1) {
502                 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
503         }
504         if (d->nb_components > 2) {
505                 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
506         }
507         if (d->nb_components > 3) {
508                 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
509         }
510         
511         if ((d->flags & PIX_FMT_PLANAR) == 0) {
512                 /* Not planar; sum them up */
513                 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
514         }
515
516         return bpp[c];
517 }
518
519 /** Construct a Image of a given size and format, allocating memory
520  *  as required.
521  *
522  *  @param p Pixel format.
523  *  @param s Size in pixels.
524  */
525 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
526         : dcp::Image (s)
527         , _pixel_format (p)
528         , _aligned (aligned)
529 {
530         allocate ();
531 }
532
533 void
534 Image::allocate ()
535 {
536         _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
537         _data[0] = _data[1] = _data[2] = _data[3] = 0;
538         
539         _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
540         _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
541         
542         _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
543         _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
544
545         for (int i = 0; i < components(); ++i) {
546                 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
547                 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
548
549                 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
550                    uses a 16-byte fetch to read three bytes (R/G/B) of image data.
551                    Hence on the last pixel of the last line it reads over the end of
552                    the actual data by 1 byte.  If the width of an image is a multiple
553                    of the stride alignment there will be no padding at the end of image lines.
554                    OS X crashes on this illegal read, though other operating systems don't
555                    seem to mind.  The nasty + 1 in this malloc makes sure there is always a byte
556                    for that instruction to read safely.
557
558                    Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
559                    over-reads by more then _avx.  I can't follow the code to work out how much,
560                    so I'll just over-allocate by 32 bytes and have done with it.  Empirical
561                    testing suggests that it works.
562                 */
563                 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 32);
564         }
565 }
566
567 Image::Image (Image const & other)
568         : dcp::Image (other)
569         ,  _pixel_format (other._pixel_format)
570         , _aligned (other._aligned)
571 {
572         allocate ();
573
574         for (int i = 0; i < components(); ++i) {
575                 uint8_t* p = _data[i];
576                 uint8_t* q = other._data[i];
577                 for (int j = 0; j < lines(i); ++j) {
578                         memcpy (p, q, _line_size[i]);
579                         p += stride()[i];
580                         q += other.stride()[i];
581                 }
582         }
583 }
584
585 Image::Image (AVFrame* frame)
586         : dcp::Image (dcp::Size (frame->width, frame->height))
587         , _pixel_format (static_cast<AVPixelFormat> (frame->format))
588         , _aligned (true)
589 {
590         allocate ();
591
592         for (int i = 0; i < components(); ++i) {
593                 uint8_t* p = _data[i];
594                 uint8_t* q = frame->data[i];
595                 for (int j = 0; j < lines(i); ++j) {
596                         memcpy (p, q, _line_size[i]);
597                         p += stride()[i];
598                         /* AVFrame's linesize is what we call `stride' */
599                         q += frame->linesize[i];
600                 }
601         }
602 }
603
604 Image::Image (shared_ptr<const Image> other, bool aligned)
605         : dcp::Image (other)
606         , _pixel_format (other->_pixel_format)
607         , _aligned (aligned)
608 {
609         allocate ();
610
611         for (int i = 0; i < components(); ++i) {
612                 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
613                 uint8_t* p = _data[i];
614                 uint8_t* q = other->data()[i];
615                 for (int j = 0; j < lines(i); ++j) {
616                         memcpy (p, q, line_size()[i]);
617                         p += stride()[i];
618                         q += other->stride()[i];
619                 }
620         }
621 }
622
623 Image&
624 Image::operator= (Image const & other)
625 {
626         if (this == &other) {
627                 return *this;
628         }
629
630         Image tmp (other);
631         swap (tmp);
632         return *this;
633 }
634
635 void
636 Image::swap (Image & other)
637 {
638         dcp::Image::swap (other);
639         
640         std::swap (_pixel_format, other._pixel_format);
641
642         for (int i = 0; i < 4; ++i) {
643                 std::swap (_data[i], other._data[i]);
644                 std::swap (_line_size[i], other._line_size[i]);
645                 std::swap (_stride[i], other._stride[i]);
646         }
647
648         std::swap (_aligned, other._aligned);
649 }
650
651 /** Destroy a Image */
652 Image::~Image ()
653 {
654         for (int i = 0; i < components(); ++i) {
655                 av_free (_data[i]);
656         }
657
658         av_free (_data);
659         av_free (_line_size);
660         av_free (_stride);
661 }
662
663 uint8_t * const *
664 Image::data () const
665 {
666         return _data;
667 }
668
669 int *
670 Image::line_size () const
671 {
672         return _line_size;
673 }
674
675 int const *
676 Image::stride () const
677 {
678         return _stride;
679 }
680
681 dcp::Size
682 Image::size () const
683 {
684         return _size;
685 }
686
687 bool
688 Image::aligned () const
689 {
690         return _aligned;
691 }
692
693 PositionImage
694 merge (list<PositionImage> images)
695 {
696         if (images.empty ()) {
697                 return PositionImage ();
698         }
699
700         if (images.size() == 1) {
701                 return images.front ();
702         }
703
704         dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
705         for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
706                 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
707         }
708
709         shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
710         merged->make_transparent ();
711         for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
712                 merged->alpha_blend (i->image, i->position - all.position());
713         }
714
715         return PositionImage (merged, all.position ());
716 }
717
718 string
719 Image::digest () const
720 {
721         MD5Digester digester;
722
723         for (int i = 0; i < components(); ++i) {
724                 digester.add (data()[i], line_size()[i]);
725         }
726
727         return digester.get ();
728 }
729
730 bool
731 operator== (Image const & a, Image const & b)
732 {
733         if (a.components() != b.components() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
734                 return false;
735         }
736
737         for (int c = 0; c < a.components(); ++c) {
738                 if (a.lines(c) != b.lines(c) || a.line_size()[c] != b.line_size()[c] || a.stride()[c] != b.stride()[c]) {
739                         return false;
740                 }
741
742                 uint8_t* p = a.data()[c];
743                 uint8_t* q = b.data()[c];
744                 for (int y = 0; y < a.lines(c); ++y) {
745                         if (memcmp (p, q, a.line_size()[c]) != 0) {
746                                 return false;
747                         }
748
749                         p += a.stride()[c];
750                         q += b.stride()[c];
751                 }
752         }
753
754         return true;
755 }
756
757 void
758 Image::fade (float f)
759 {
760         switch (_pixel_format) {
761         case PIX_FMT_YUV420P:
762         case PIX_FMT_YUV422P:
763         case PIX_FMT_YUV444P:
764         case PIX_FMT_YUV411P:
765         case PIX_FMT_YUVJ420P:
766         case PIX_FMT_YUVJ422P:
767         case PIX_FMT_YUVJ444P:
768         case PIX_FMT_RGB24:
769         case PIX_FMT_ARGB:
770         case PIX_FMT_RGBA:
771         case PIX_FMT_ABGR:
772         case PIX_FMT_BGRA:
773         case PIX_FMT_RGB555LE:
774                 /* 8-bit */
775                 for (int c = 0; c < 3; ++c) {
776                         uint8_t* p = data()[c];
777                         for (int y = 0; y < lines(c); ++y) {
778                                 uint8_t* q = p;
779                                 for (int x = 0; x < line_size()[c]; ++x) {
780                                         *q = int (float (*q) * f);
781                                         ++q;
782                                 }
783                                 p += stride()[c];
784                         }
785                 }
786                 break;
787
788         case PIX_FMT_YUV422P9LE:
789         case PIX_FMT_YUV444P9LE:
790         case PIX_FMT_YUV422P10LE:
791         case PIX_FMT_YUV444P10LE:
792         case PIX_FMT_YUV422P16LE:
793         case PIX_FMT_YUV444P16LE:
794         case AV_PIX_FMT_YUVA420P9LE:
795         case AV_PIX_FMT_YUVA422P9LE:
796         case AV_PIX_FMT_YUVA444P9LE:
797         case AV_PIX_FMT_YUVA420P10LE:
798         case AV_PIX_FMT_YUVA422P10LE:
799         case AV_PIX_FMT_YUVA444P10LE:
800                 /* 16-bit little-endian */
801                 for (int c = 0; c < 3; ++c) {
802                         int const stride_pixels = stride()[c] / 2;
803                         int const line_size_pixels = line_size()[c] / 2;
804                         uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
805                         for (int y = 0; y < lines(c); ++y) {
806                                 uint16_t* q = p;
807                                 for (int x = 0; x < line_size_pixels; ++x) {
808                                         *q = int (float (*q) * f);
809                                         ++q;
810                                 }
811                                 p += stride_pixels;
812                         }
813                 }
814                 break;
815
816         case PIX_FMT_YUV422P9BE:
817         case PIX_FMT_YUV444P9BE:
818         case PIX_FMT_YUV444P10BE:
819         case PIX_FMT_YUV422P10BE:
820         case AV_PIX_FMT_YUVA420P9BE:
821         case AV_PIX_FMT_YUVA422P9BE:
822         case AV_PIX_FMT_YUVA444P9BE:
823         case AV_PIX_FMT_YUVA420P10BE:
824         case AV_PIX_FMT_YUVA422P10BE:
825         case AV_PIX_FMT_YUVA444P10BE:
826         case AV_PIX_FMT_YUVA420P16BE:
827         case AV_PIX_FMT_YUVA422P16BE:
828         case AV_PIX_FMT_YUVA444P16BE:
829                 /* 16-bit big-endian */
830                 for (int c = 0; c < 3; ++c) {
831                         int const stride_pixels = stride()[c] / 2;
832                         int const line_size_pixels = line_size()[c] / 2;
833                         uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
834                         for (int y = 0; y < lines(c); ++y) {
835                                 uint16_t* q = p;
836                                 for (int x = 0; x < line_size_pixels; ++x) {
837                                         *q = swap_16 (int (float (swap_16 (*q)) * f));
838                                         ++q;
839                                 }
840                                 p += stride_pixels;
841                         }
842                 }
843                 break;
844
845         case PIX_FMT_UYVY422:
846         {
847                 int const Y = lines(0);
848                 int const X = line_size()[0];
849                 uint8_t* p = data()[0];
850                 for (int y = 0; y < Y; ++y) {
851                         for (int x = 0; x < X; ++x) {
852                                 *p = int (float (*p) * f);
853                                 ++p;
854                         }
855                 }
856                 break;
857         }
858
859         default:
860                 throw PixelFormatError ("fade()", _pixel_format);
861         }
862 }