Tidy up duplicated code.
[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, AVPixelFormat result_format, 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 (result_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, result_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 /** Run a FFmpeg post-process on this image and return the processed version.
111  *  @param pp Flags for the required set of post processes.
112  *  @return Post-processed image.
113  */
114 shared_ptr<Image>
115 Image::post_process (string pp, bool aligned) const
116 {
117         shared_ptr<Image> out (new Image (pixel_format(), size (), aligned));
118
119         int pp_format = 0;
120         switch (pixel_format()) {
121         case PIX_FMT_YUV420P:
122                 pp_format = PP_FORMAT_420;
123                 break;
124         case PIX_FMT_YUV422P10LE:
125         case PIX_FMT_YUV422P:
126         case PIX_FMT_UYVY422:
127                 pp_format = PP_FORMAT_422;
128                 break;
129         case PIX_FMT_YUV444P:
130         case PIX_FMT_YUV444P9BE:
131         case PIX_FMT_YUV444P9LE:
132         case PIX_FMT_YUV444P10BE:
133         case PIX_FMT_YUV444P10LE:
134                 pp_format = PP_FORMAT_444;
135         default:
136                 throw PixelFormatError ("post_process", pixel_format());
137         }
138                 
139         pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
140         pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
141
142         pp_postprocess (
143                 (const uint8_t **) data(), stride(),
144                 out->data(), out->stride(),
145                 size().width, size().height,
146                 0, 0, mode, context, 0
147                 );
148                 
149         pp_free_mode (mode);
150         pp_free_context (context);
151
152         return out;
153 }
154
155 shared_ptr<Image>
156 Image::crop (Crop crop, bool aligned) const
157 {
158         libdcp::Size cropped_size = size ();
159         cropped_size.width -= crop.left + crop.right;
160         cropped_size.height -= crop.top + crop.bottom;
161
162         shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
163
164         for (int c = 0; c < components(); ++c) {
165                 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
166                 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
167                    up, and we need to make sure that we copy over the width (up to the stride)
168                    rather than short of the width; hence the ceil() here.
169                 */
170                 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
171
172                 /* Start of the source line, cropped from the top but not the left */
173                 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
174                 uint8_t* out_p = out->data()[c];
175
176                 for (int y = 0; y < out->lines(c); ++y) {
177                         memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
178                         in_p += stride()[c];
179                         out_p += out->stride()[c];
180                 }
181         }
182
183         return out;
184 }
185
186 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
187 void
188 Image::yuv_16_black (uint16_t v)
189 {
190         memset (data()[0], 0, lines(0) * stride()[0]);
191         for (int i = 1; i < 3; ++i) {
192                 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
193                 for (int y = 0; y < size().height; ++y) {
194                         for (int x = 0; x < line_size()[i] / 2; ++x) {
195                                 p[x] = v;
196                         }
197                         p += stride()[i] / 2;
198                 }
199         }
200 }
201
202 uint16_t
203 Image::swap_16 (uint16_t v)
204 {
205         return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
206 }
207
208 void
209 Image::make_black ()
210 {
211         /* U/V black value for 8-bit colour */
212         static uint8_t const eight_bit_uv =     (1 << 7) - 1;
213         /* U/V black value for 9-bit colour */
214         static uint16_t const nine_bit_uv =     (1 << 8) - 1;
215         /* U/V black value for 10-bit colour */
216         static uint16_t const ten_bit_uv =      (1 << 9) - 1;
217         /* U/V black value for 16-bit colour */
218         static uint16_t const sixteen_bit_uv =  (1 << 15) - 1;
219         
220         switch (_pixel_format) {
221         case PIX_FMT_YUV420P:
222         case PIX_FMT_YUV422P:
223         case PIX_FMT_YUV444P:
224                 memset (data()[0], 0, lines(0) * stride()[0]);
225                 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
226                 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
227                 break;
228
229         case PIX_FMT_YUVJ420P:
230         case PIX_FMT_YUVJ422P:
231         case PIX_FMT_YUVJ444P:
232                 memset (data()[0], 0, lines(0) * stride()[0]);
233                 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
234                 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
235                 break;
236
237         case PIX_FMT_YUV422P9LE:
238         case PIX_FMT_YUV444P9LE:
239                 yuv_16_black (nine_bit_uv);
240                 break;
241
242         case PIX_FMT_YUV422P9BE:
243         case PIX_FMT_YUV444P9BE:
244                 yuv_16_black (swap_16 (nine_bit_uv));
245                 break;
246                 
247         case PIX_FMT_YUV422P10LE:
248         case PIX_FMT_YUV444P10LE:
249                 yuv_16_black (ten_bit_uv);
250                 break;
251
252         case PIX_FMT_YUV422P16LE:
253         case PIX_FMT_YUV444P16LE:
254                 yuv_16_black (sixteen_bit_uv);
255                 break;
256                 
257         case PIX_FMT_YUV444P10BE:
258         case PIX_FMT_YUV422P10BE:
259                 yuv_16_black (swap_16 (ten_bit_uv));
260                 break;
261
262         case PIX_FMT_RGB24:             
263                 memset (data()[0], 0, lines(0) * stride()[0]);
264                 break;
265
266         case PIX_FMT_UYVY422:
267         {
268                 int const Y = lines(0);
269                 int const X = line_size()[0];
270                 uint8_t* p = data()[0];
271                 for (int y = 0; y < Y; ++y) {
272                         for (int x = 0; x < X / 4; ++x) {
273                                 *p++ = eight_bit_uv; // Cb
274                                 *p++ = 0;            // Y0
275                                 *p++ = eight_bit_uv; // Cr
276                                 *p++ = 0;            // Y1
277                         }
278                 }
279                 break;
280         }
281
282         default:
283                 throw PixelFormatError ("make_black()", _pixel_format);
284         }
285 }
286
287 void
288 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
289 {
290         /* Only implemented for RGBA onto RGB24 so far */
291         assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
292
293         int start_tx = position.x;
294         int start_ox = 0;
295
296         if (start_tx < 0) {
297                 start_ox = -start_tx;
298                 start_tx = 0;
299         }
300
301         int start_ty = position.y;
302         int start_oy = 0;
303
304         if (start_ty < 0) {
305                 start_oy = -start_ty;
306                 start_ty = 0;
307         }
308
309         for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
310                 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
311                 uint8_t* op = other->data()[0] + oy * other->stride()[0];
312                 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
313                         float const alpha = float (op[3]) / 255;
314                         tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
315                         tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
316                         tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
317                         tp += 3;
318                         op += 4;
319                 }
320         }
321 }
322
323 void
324 Image::copy (shared_ptr<const Image> other, Position<int> position)
325 {
326         /* Only implemented for RGB24 onto RGB24 so far */
327         assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
328         assert (position.x >= 0 && position.y >= 0);
329
330         int const N = min (position.x + other->size().width, size().width) - position.x;
331         for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
332                 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
333                 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
334                 memcpy (tp, op, N * 3);
335         }
336 }       
337
338 void
339 Image::read_from_socket (shared_ptr<Socket> socket)
340 {
341         for (int i = 0; i < components(); ++i) {
342                 uint8_t* p = data()[i];
343                 for (int y = 0; y < lines(i); ++y) {
344                         socket->read (p, line_size()[i]);
345                         p += stride()[i];
346                 }
347         }
348 }
349
350 void
351 Image::write_to_socket (shared_ptr<Socket> socket) const
352 {
353         for (int i = 0; i < components(); ++i) {
354                 uint8_t* p = data()[i];
355                 for (int y = 0; y < lines(i); ++y) {
356                         socket->write (p, line_size()[i]);
357                         p += stride()[i];
358                 }
359         }
360 }
361
362
363 float
364 Image::bytes_per_pixel (int c) const
365 {
366         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
367         if (!d) {
368                 throw PixelFormatError ("lines()", _pixel_format);
369         }
370
371         if (c >= components()) {
372                 return 0;
373         }
374
375         float bpp[4] = { 0, 0, 0, 0 };
376
377         bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
378         if (d->nb_components > 1) {
379                 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
380         }
381         if (d->nb_components > 2) {
382                 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
383         }
384         if (d->nb_components > 3) {
385                 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
386         }
387         
388         if ((d->flags & PIX_FMT_PLANAR) == 0) {
389                 /* Not planar; sum them up */
390                 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
391         }
392
393         return bpp[c];
394 }
395
396 /** Construct a Image of a given size and format, allocating memory
397  *  as required.
398  *
399  *  @param p Pixel format.
400  *  @param s Size in pixels.
401  */
402 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
403         : libdcp::Image (s)
404         , _pixel_format (p)
405         , _aligned (aligned)
406 {
407         allocate ();
408 }
409
410 void
411 Image::allocate ()
412 {
413         _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
414         _data[0] = _data[1] = _data[2] = _data[3] = 0;
415         
416         _line_size = (int *) av_malloc (4 * sizeof (int));
417         _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
418         
419         _stride = (int *) av_malloc (4 * sizeof (int));
420         _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
421
422         for (int i = 0; i < components(); ++i) {
423                 _line_size[i] = _size.width * bytes_per_pixel(i);
424                 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
425                 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i));
426         }
427 }
428
429 Image::Image (Image const & other)
430         : libdcp::Image (other)
431         ,  _pixel_format (other._pixel_format)
432         , _aligned (other._aligned)
433 {
434         allocate ();
435
436         for (int i = 0; i < components(); ++i) {
437                 uint8_t* p = _data[i];
438                 uint8_t* q = other._data[i];
439                 for (int j = 0; j < lines(i); ++j) {
440                         memcpy (p, q, _line_size[i]);
441                         p += stride()[i];
442                         q += other.stride()[i];
443                 }
444         }
445 }
446
447 Image::Image (AVFrame* frame)
448         : libdcp::Image (libdcp::Size (frame->width, frame->height))
449         , _pixel_format (static_cast<AVPixelFormat> (frame->format))
450         , _aligned (true)
451 {
452         allocate ();
453
454         for (int i = 0; i < components(); ++i) {
455                 uint8_t* p = _data[i];
456                 uint8_t* q = frame->data[i];
457                 for (int j = 0; j < lines(i); ++j) {
458                         memcpy (p, q, _line_size[i]);
459                         p += stride()[i];
460                         /* AVFrame's linesize is what we call `stride' */
461                         q += frame->linesize[i];
462                 }
463         }
464 }
465
466 Image::Image (shared_ptr<const Image> other, bool aligned)
467         : libdcp::Image (other)
468         , _pixel_format (other->_pixel_format)
469         , _aligned (aligned)
470 {
471         allocate ();
472
473         for (int i = 0; i < components(); ++i) {
474                 assert(line_size()[i] == other->line_size()[i]);
475                 uint8_t* p = _data[i];
476                 uint8_t* q = other->data()[i];
477                 for (int j = 0; j < lines(i); ++j) {
478                         memcpy (p, q, line_size()[i]);
479                         p += stride()[i];
480                         q += other->stride()[i];
481                 }
482         }
483 }
484
485 Image&
486 Image::operator= (Image const & other)
487 {
488         if (this == &other) {
489                 return *this;
490         }
491
492         Image tmp (other);
493         swap (tmp);
494         return *this;
495 }
496
497 void
498 Image::swap (Image & other)
499 {
500         libdcp::Image::swap (other);
501         
502         std::swap (_pixel_format, other._pixel_format);
503
504         for (int i = 0; i < 4; ++i) {
505                 std::swap (_data[i], other._data[i]);
506                 std::swap (_line_size[i], other._line_size[i]);
507                 std::swap (_stride[i], other._stride[i]);
508         }
509
510         std::swap (_aligned, other._aligned);
511 }
512
513 /** Destroy a Image */
514 Image::~Image ()
515 {
516         for (int i = 0; i < components(); ++i) {
517                 av_free (_data[i]);
518         }
519
520         av_free (_data);
521         av_free (_line_size);
522         av_free (_stride);
523 }
524
525 uint8_t **
526 Image::data () const
527 {
528         return _data;
529 }
530
531 int *
532 Image::line_size () const
533 {
534         return _line_size;
535 }
536
537 int *
538 Image::stride () const
539 {
540         return _stride;
541 }
542
543 libdcp::Size
544 Image::size () const
545 {
546         return _size;
547 }
548
549 bool
550 Image::aligned () const
551 {
552         return _aligned;
553 }
554