Remove unused RGBPlusAlphaImage; merge Image/SimpleImage.
[dcpomatic.git] / src / lib / image.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/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 #include <libpostproc/postprocess.h>
30 }
31 #include "image.h"
32 #include "exceptions.h"
33 #include "scaler.h"
34
35 using std::string;
36 using std::min;
37 using std::cout;
38 using boost::shared_ptr;
39 using libdcp::Size;
40
41 int
42 Image::line_factor (int n) const
43 {
44         if (n == 0) {
45                 return 1;
46         }
47
48         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
49         if (!d) {
50                 throw PixelFormatError ("lines()", _pixel_format);
51         }
52         
53         return pow (2.0f, d->log2_chroma_h);
54 }
55
56 /** @param n Component index.
57  *  @return Number of lines in the image for the given component.
58  */
59 int
60 Image::lines (int n) const
61 {
62         return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
63 }
64
65 /** @return Number of components */
66 int
67 Image::components () const
68 {
69         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
70         if (!d) {
71                 throw PixelFormatError ("components()", _pixel_format);
72         }
73
74         if ((d->flags & PIX_FMT_PLANAR) == 0) {
75                 return 1;
76         }
77         
78         return d->nb_components;
79 }
80
81 shared_ptr<Image>
82 Image::scale (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
83 {
84         assert (scaler);
85         /* Empirical testing suggests that sws_scale() will crash if
86            the input image is not aligned.
87         */
88         assert (aligned ());
89
90         shared_ptr<Image> scaled (new Image (pixel_format(), out_size, result_aligned));
91
92         struct SwsContext* scale_context = sws_getContext (
93                 size().width, size().height, pixel_format(),
94                 out_size.width, out_size.height, pixel_format(),
95                 scaler->ffmpeg_id (), 0, 0, 0
96                 );
97
98         sws_scale (
99                 scale_context,
100                 data(), stride(),
101                 0, size().height,
102                 scaled->data(), scaled->stride()
103                 );
104
105         sws_freeContext (scale_context);
106
107         return scaled;
108 }
109
110 /** Scale this image to a given size and convert it to RGB.
111  *  @param out_size Output image size in pixels.
112  *  @param scaler Scaler to use.
113  */
114 shared_ptr<Image>
115 Image::scale_and_convert_to_rgb (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
116 {
117         assert (scaler);
118         /* Empirical testing suggests that sws_scale() will crash if
119            the input image is not aligned.
120         */
121         assert (aligned ());
122
123         shared_ptr<Image> rgb (new Image (PIX_FMT_RGB24, out_size, result_aligned));
124
125         struct SwsContext* scale_context = sws_getContext (
126                 size().width, size().height, pixel_format(),
127                 out_size.width, out_size.height, PIX_FMT_RGB24,
128                 scaler->ffmpeg_id (), 0, 0, 0
129                 );
130
131         /* Scale and convert to RGB from whatever its currently in (which may be RGB) */
132         sws_scale (
133                 scale_context,
134                 data(), stride(),
135                 0, size().height,
136                 rgb->data(), rgb->stride()
137                 );
138
139         sws_freeContext (scale_context);
140
141         return rgb;
142 }
143
144 /** Run a FFmpeg post-process on this image and return the processed version.
145  *  @param pp Flags for the required set of post processes.
146  *  @return Post-processed image.
147  */
148 shared_ptr<Image>
149 Image::post_process (string pp, bool aligned) const
150 {
151         shared_ptr<Image> out (new Image (pixel_format(), size (), aligned));
152
153         int pp_format = 0;
154         switch (pixel_format()) {
155         case PIX_FMT_YUV420P:
156                 pp_format = PP_FORMAT_420;
157                 break;
158         case PIX_FMT_YUV422P10LE:
159         case PIX_FMT_YUV422P:
160         case PIX_FMT_UYVY422:
161                 pp_format = PP_FORMAT_422;
162                 break;
163         case PIX_FMT_YUV444P:
164         case PIX_FMT_YUV444P9BE:
165         case PIX_FMT_YUV444P9LE:
166         case PIX_FMT_YUV444P10BE:
167         case PIX_FMT_YUV444P10LE:
168                 pp_format = PP_FORMAT_444;
169         default:
170                 throw PixelFormatError ("post_process", pixel_format());
171         }
172                 
173         pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
174         pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
175
176         pp_postprocess (
177                 (const uint8_t **) data(), stride(),
178                 out->data(), out->stride(),
179                 size().width, size().height,
180                 0, 0, mode, context, 0
181                 );
182                 
183         pp_free_mode (mode);
184         pp_free_context (context);
185
186         return out;
187 }
188
189 shared_ptr<Image>
190 Image::crop (Crop crop, bool aligned) const
191 {
192         libdcp::Size cropped_size = size ();
193         cropped_size.width -= crop.left + crop.right;
194         cropped_size.height -= crop.top + crop.bottom;
195
196         shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
197
198         for (int c = 0; c < components(); ++c) {
199                 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
200                 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
201                    up, and we need to make sure that we copy over the width (up to the stride)
202                    rather than short of the width; hence the ceil() here.
203                 */
204                 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
205
206                 /* Start of the source line, cropped from the top but not the left */
207                 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
208                 uint8_t* out_p = out->data()[c];
209
210                 for (int y = 0; y < out->lines(c); ++y) {
211                         memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
212                         in_p += stride()[c];
213                         out_p += out->stride()[c];
214                 }
215         }
216
217         return out;
218 }
219
220 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
221 void
222 Image::yuv_16_black (uint16_t v)
223 {
224         memset (data()[0], 0, lines(0) * stride()[0]);
225         for (int i = 1; i < 3; ++i) {
226                 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
227                 for (int y = 0; y < size().height; ++y) {
228                         for (int x = 0; x < line_size()[i] / 2; ++x) {
229                                 p[x] = v;
230                         }
231                         p += stride()[i] / 2;
232                 }
233         }
234 }
235
236 uint16_t
237 Image::swap_16 (uint16_t v)
238 {
239         return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
240 }
241
242 void
243 Image::make_black ()
244 {
245         /* U/V black value for 8-bit colour */
246         static uint8_t const eight_bit_uv =     (1 << 7) - 1;
247         /* U/V black value for 9-bit colour */
248         static uint16_t const nine_bit_uv =     (1 << 8) - 1;
249         /* U/V black value for 10-bit colour */
250         static uint16_t const ten_bit_uv =      (1 << 9) - 1;
251         /* U/V black value for 16-bit colour */
252         static uint16_t const sixteen_bit_uv =  (1 << 15) - 1;
253         
254         switch (_pixel_format) {
255         case PIX_FMT_YUV420P:
256         case PIX_FMT_YUV422P:
257         case PIX_FMT_YUV444P:
258                 memset (data()[0], 0, lines(0) * stride()[0]);
259                 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
260                 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
261                 break;
262
263         case PIX_FMT_YUVJ420P:
264         case PIX_FMT_YUVJ422P:
265         case PIX_FMT_YUVJ444P:
266                 memset (data()[0], 0, lines(0) * stride()[0]);
267                 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
268                 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
269                 break;
270
271         case PIX_FMT_YUV422P9LE:
272         case PIX_FMT_YUV444P9LE:
273                 yuv_16_black (nine_bit_uv);
274                 break;
275
276         case PIX_FMT_YUV422P9BE:
277         case PIX_FMT_YUV444P9BE:
278                 yuv_16_black (swap_16 (nine_bit_uv));
279                 break;
280                 
281         case PIX_FMT_YUV422P10LE:
282         case PIX_FMT_YUV444P10LE:
283                 yuv_16_black (ten_bit_uv);
284                 break;
285
286         case PIX_FMT_YUV422P16LE:
287         case PIX_FMT_YUV444P16LE:
288                 yuv_16_black (sixteen_bit_uv);
289                 break;
290                 
291         case PIX_FMT_YUV444P10BE:
292         case PIX_FMT_YUV422P10BE:
293                 yuv_16_black (swap_16 (ten_bit_uv));
294                 break;
295
296         case PIX_FMT_RGB24:             
297                 memset (data()[0], 0, lines(0) * stride()[0]);
298                 break;
299
300         case PIX_FMT_UYVY422:
301         {
302                 int const Y = lines(0);
303                 int const X = line_size()[0];
304                 uint8_t* p = data()[0];
305                 for (int y = 0; y < Y; ++y) {
306                         for (int x = 0; x < X / 4; ++x) {
307                                 *p++ = eight_bit_uv; // Cb
308                                 *p++ = 0;            // Y0
309                                 *p++ = eight_bit_uv; // Cr
310                                 *p++ = 0;            // Y1
311                         }
312                 }
313                 break;
314         }
315
316         default:
317                 throw PixelFormatError ("make_black()", _pixel_format);
318         }
319 }
320
321 void
322 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
323 {
324         /* Only implemented for RGBA onto RGB24 so far */
325         assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
326
327         int start_tx = position.x;
328         int start_ox = 0;
329
330         if (start_tx < 0) {
331                 start_ox = -start_tx;
332                 start_tx = 0;
333         }
334
335         int start_ty = position.y;
336         int start_oy = 0;
337
338         if (start_ty < 0) {
339                 start_oy = -start_ty;
340                 start_ty = 0;
341         }
342
343         for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
344                 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
345                 uint8_t* op = other->data()[0] + oy * other->stride()[0];
346                 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
347                         float const alpha = float (op[3]) / 255;
348                         tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
349                         tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
350                         tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
351                         tp += 3;
352                         op += 4;
353                 }
354         }
355 }
356
357 void
358 Image::copy (shared_ptr<const Image> other, Position<int> position)
359 {
360         /* Only implemented for RGB24 onto RGB24 so far */
361         assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
362         assert (position.x >= 0 && position.y >= 0);
363
364         int const N = min (position.x + other->size().width, size().width) - position.x;
365         for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
366                 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
367                 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
368                 memcpy (tp, op, N * 3);
369         }
370 }       
371
372 void
373 Image::read_from_socket (shared_ptr<Socket> socket)
374 {
375         for (int i = 0; i < components(); ++i) {
376                 uint8_t* p = data()[i];
377                 for (int y = 0; y < lines(i); ++y) {
378                         socket->read (p, line_size()[i]);
379                         p += stride()[i];
380                 }
381         }
382 }
383
384 void
385 Image::write_to_socket (shared_ptr<Socket> socket) const
386 {
387         for (int i = 0; i < components(); ++i) {
388                 uint8_t* p = data()[i];
389                 for (int y = 0; y < lines(i); ++y) {
390                         socket->write (p, line_size()[i]);
391                         p += stride()[i];
392                 }
393         }
394 }
395
396
397 float
398 Image::bytes_per_pixel (int c) const
399 {
400         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
401         if (!d) {
402                 throw PixelFormatError ("lines()", _pixel_format);
403         }
404
405         if (c >= components()) {
406                 return 0;
407         }
408
409         float bpp[4] = { 0, 0, 0, 0 };
410
411         bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
412         if (d->nb_components > 1) {
413                 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
414         }
415         if (d->nb_components > 2) {
416                 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
417         }
418         if (d->nb_components > 3) {
419                 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
420         }
421         
422         if ((d->flags & PIX_FMT_PLANAR) == 0) {
423                 /* Not planar; sum them up */
424                 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
425         }
426
427         return bpp[c];
428 }
429
430 /** Construct a Image of a given size and format, allocating memory
431  *  as required.
432  *
433  *  @param p Pixel format.
434  *  @param s Size in pixels.
435  */
436 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
437         : _pixel_format (p)
438         , _size (s)
439         , _aligned (aligned)
440 {
441         allocate ();
442 }
443
444 void
445 Image::allocate ()
446 {
447         _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
448         _data[0] = _data[1] = _data[2] = _data[3] = 0;
449         
450         _line_size = (int *) av_malloc (4 * sizeof (int));
451         _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
452         
453         _stride = (int *) av_malloc (4 * sizeof (int));
454         _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
455
456         for (int i = 0; i < components(); ++i) {
457                 _line_size[i] = _size.width * bytes_per_pixel(i);
458                 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
459                 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i));
460         }
461 }
462
463 Image::Image (Image const & other)
464         : _pixel_format (other._pixel_format)
465         , _size (other._size)
466         , _aligned (other._aligned)
467 {
468         allocate ();
469
470         for (int i = 0; i < components(); ++i) {
471                 uint8_t* p = _data[i];
472                 uint8_t* q = other._data[i];
473                 for (int j = 0; j < lines(i); ++j) {
474                         memcpy (p, q, _line_size[i]);
475                         p += stride()[i];
476                         q += other.stride()[i];
477                 }
478         }
479 }
480
481 Image::Image (AVFrame* frame)
482         : _pixel_format (static_cast<AVPixelFormat> (frame->format))
483         , _size (frame->width, frame->height)
484         , _aligned (true)
485 {
486         allocate ();
487
488         for (int i = 0; i < components(); ++i) {
489                 uint8_t* p = _data[i];
490                 uint8_t* q = frame->data[i];
491                 for (int j = 0; j < lines(i); ++j) {
492                         memcpy (p, q, _line_size[i]);
493                         p += stride()[i];
494                         /* AVFrame's linesize is what we call `stride' */
495                         q += frame->linesize[i];
496                 }
497         }
498 }
499
500 Image::Image (shared_ptr<const Image> other, bool aligned)
501         : _pixel_format (other->_pixel_format)
502         , _size (other->size())
503         , _aligned (aligned)
504 {
505         allocate ();
506
507         for (int i = 0; i < components(); ++i) {
508                 assert(line_size()[i] == other->line_size()[i]);
509                 uint8_t* p = _data[i];
510                 uint8_t* q = other->data()[i];
511                 for (int j = 0; j < lines(i); ++j) {
512                         memcpy (p, q, line_size()[i]);
513                         p += stride()[i];
514                         q += other->stride()[i];
515                 }
516         }
517 }
518
519 Image&
520 Image::operator= (Image const & other)
521 {
522         if (this == &other) {
523                 return *this;
524         }
525
526         Image tmp (other);
527         swap (tmp);
528         return *this;
529 }
530
531 void
532 Image::swap (Image & other)
533 {
534         std::swap (_pixel_format, other._pixel_format);
535         std::swap (_size, other._size);
536
537         for (int i = 0; i < 4; ++i) {
538                 std::swap (_data[i], other._data[i]);
539                 std::swap (_line_size[i], other._line_size[i]);
540                 std::swap (_stride[i], other._stride[i]);
541         }
542
543         std::swap (_aligned, other._aligned);
544 }
545
546 /** Destroy a Image */
547 Image::~Image ()
548 {
549         for (int i = 0; i < components(); ++i) {
550                 av_free (_data[i]);
551         }
552
553         av_free (_data);
554         av_free (_line_size);
555         av_free (_stride);
556 }
557
558 uint8_t **
559 Image::data () const
560 {
561         return _data;
562 }
563
564 int *
565 Image::line_size () const
566 {
567         return _line_size;
568 }
569
570 int *
571 Image::stride () const
572 {
573         return _stride;
574 }
575
576 libdcp::Size
577 Image::size () const
578 {
579         return _size;
580 }
581
582 bool
583 Image::aligned () const
584 {
585         return _aligned;
586 }
587