2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
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.
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.
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/>.
22 /** @file src/image.cc
23 * @brief A class to describe a video image.
27 #include "compose.hpp"
28 #include "dcpomatic_assert.h"
29 #include "dcpomatic_socket.h"
30 #include "exceptions.h"
32 #include "maths_util.h"
33 #include "memory_util.h"
36 #include <dcp/rgb_xyz.h>
37 #include <dcp/transfer_function.h>
38 #include <dcp/warnings.h>
39 LIBDCP_DISABLE_WARNINGS
41 #include <libavutil/frame.h>
42 #include <libavutil/pixdesc.h>
43 #include <libavutil/pixfmt.h>
44 #include <libswscale/swscale.h>
46 LIBDCP_ENABLE_WARNINGS
47 #if HAVE_VALGRIND_MEMCHECK_H
48 #include <valgrind/memcheck.h>
59 using std::make_shared;
62 using std::runtime_error;
63 using std::shared_ptr;
68 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
69 int constexpr ALIGNMENT = 64;
71 /* U/V black value for 8-bit colour */
72 static uint8_t const eight_bit_uv = (1 << 7) - 1;
73 /* U/V black value for 9-bit colour */
74 static uint16_t const nine_bit_uv = (1 << 8) - 1;
75 /* U/V black value for 10-bit colour */
76 static uint16_t const ten_bit_uv = (1 << 9) - 1;
77 /* U/V black value for 16-bit colour */
78 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
82 Image::vertical_factor (int n) const
88 auto d = av_pix_fmt_desc_get(_pixel_format);
90 throw PixelFormatError ("line_factor()", _pixel_format);
93 return lrintf(powf(2.0f, d->log2_chroma_h));
97 Image::horizontal_factor (int n) const
103 auto d = av_pix_fmt_desc_get(_pixel_format);
105 throw PixelFormatError ("sample_size()", _pixel_format);
108 return lrintf(powf(2.0f, d->log2_chroma_w));
112 /** @param n Component index.
113 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
116 Image::sample_size (int n) const
119 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
120 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
125 /** @return Number of planes */
127 Image::planes () const
129 if (_pixel_format == AV_PIX_FMT_PAL8) {
133 auto d = av_pix_fmt_desc_get(_pixel_format);
135 throw PixelFormatError ("planes()", _pixel_format);
138 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
142 return d->nb_components;
148 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
150 return p & ~ ((1 << desc->log2_chroma_w) - 1);
156 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
158 return p & ~ ((1 << desc->log2_chroma_h) - 1);
162 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
163 * @param crop Amount to crop by.
164 * @param inter_size Size to scale the cropped image to.
165 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
166 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
167 * @param video_range Video range of the image.
168 * @param out_format Output pixel format.
169 * @param out_aligned true to make the output image aligned.
170 * @param out_video_range Video range to use for the output image.
171 * @param fast Try to be fast at the possible expense of quality; at present this means using
172 * fast bilinear rather than bicubic scaling.
175 Image::crop_scale_window (
177 dcp::Size inter_size,
179 dcp::YUVToRGB yuv_to_rgb,
180 VideoRange video_range,
181 AVPixelFormat out_format,
182 VideoRange out_video_range,
183 Alignment out_alignment,
187 /* Empirical testing suggests that sws_scale() will crash if
188 the input image is not padded.
190 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
192 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
193 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
195 auto out = make_shared<Image>(out_format, out_size, out_alignment);
198 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
200 throw PixelFormatError ("crop_scale_window()", _pixel_format);
203 /* Round down so that we crop only the number of pixels that is straightforward
204 * considering any subsampling.
207 round_width_for_subsampling(crop.left, in_desc),
208 round_width_for_subsampling(crop.right, in_desc),
209 round_height_for_subsampling(crop.top, in_desc),
210 round_height_for_subsampling(crop.bottom, in_desc)
213 /* Also check that we aren't cropping more image than there actually is */
214 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
215 corrected_crop.left = 0;
216 corrected_crop.right = size().width - 4;
219 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
220 corrected_crop.top = 0;
221 corrected_crop.bottom = size().height - 4;
224 /* Size of the image after any crop */
225 auto const cropped_size = corrected_crop.apply (size());
227 /* Scale context for a scale from cropped_size to inter_size */
228 auto scale_context = sws_getContext (
229 cropped_size.width, cropped_size.height, pixel_format(),
230 inter_size.width, inter_size.height, out_format,
231 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
234 if (!scale_context) {
235 throw runtime_error (N_("Could not allocate SwsContext"));
238 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
239 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
244 /* The 3rd parameter here is:
245 0 -> source range MPEG (i.e. "video", 16-235)
246 1 -> source range JPEG (i.e. "full", 0-255)
248 0 -> destination range MPEG (i.e. "video", 16-235)
249 1 -> destination range JPEG (i.e. "full", 0-255)
251 But remember: sws_setColorspaceDetails ignores these
252 parameters unless the both source and destination images
253 are isYUV or isGray. (If either is not, it uses video range).
255 sws_setColorspaceDetails (
257 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
258 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
262 /* Prepare input data pointers with crop */
263 uint8_t* scale_in_data[planes()];
264 for (int c = 0; c < planes(); ++c) {
265 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
266 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
269 auto out_desc = av_pix_fmt_desc_get (out_format);
271 throw PixelFormatError ("crop_scale_window()", out_format);
274 /* Corner of the image within out_size */
275 Position<int> const corner (
276 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
277 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
280 uint8_t* scale_out_data[out->planes()];
281 for (int c = 0; c < out->planes(); ++c) {
282 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
283 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
288 scale_in_data, stride(),
289 0, cropped_size.height,
290 scale_out_data, out->stride()
293 sws_freeContext (scale_context);
295 /* There are some cases where there will be unwanted image data left in the image at this point:
297 * 1. When we are cropping without any scaling or pixel format conversion.
298 * 2. When we are scaling to certain sizes and placing the result into a larger
301 * Clear out the sides of the image to take care of those cases.
303 auto const pad = (out_size.width - inter_size.width) / 2;
304 out->make_part_black(0, pad);
305 out->make_part_black(corner.x + inter_size.width, pad);
308 video_range == VideoRange::VIDEO &&
309 out_video_range == VideoRange::FULL &&
310 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
312 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
313 out->video_range_to_full_range ();
321 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
323 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
327 /** @param out_size Size to scale to.
328 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
329 * @param out_format Output pixel format.
330 * @param out_aligment Output alignment.
331 * @param fast Try to be fast at the possible expense of quality; at present this means using
332 * fast bilinear rather than bicubic scaling.
335 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
337 /* Empirical testing suggests that sws_scale() will crash if
338 the input image alignment is not PADDED.
340 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
342 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
343 auto scale_context = sws_getContext (
344 size().width, size().height, pixel_format(),
345 out_size.width, out_size.height, out_format,
346 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
349 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
350 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
355 /* The 3rd parameter here is:
356 0 -> source range MPEG (i.e. "video", 16-235)
357 1 -> source range JPEG (i.e. "full", 0-255)
359 0 -> destination range MPEG (i.e. "video", 16-235)
360 1 -> destination range JPEG (i.e. "full", 0-255)
362 But remember: sws_setColorspaceDetails ignores these
363 parameters unless the corresponding image isYUV or isGray.
364 (If it's neither, it uses video range).
366 sws_setColorspaceDetails (
368 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
369 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
377 scaled->data(), scaled->stride()
380 sws_freeContext (scale_context);
386 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
388 Image::yuv_16_black (uint16_t v, bool alpha)
390 memset (data()[0], 0, sample_size(0).height * stride()[0]);
391 for (int i = 1; i < 3; ++i) {
392 auto p = reinterpret_cast<int16_t*> (data()[i]);
393 int const lines = sample_size(i).height;
394 for (int y = 0; y < lines; ++y) {
395 /* We divide by 2 here because we are writing 2 bytes at a time */
396 for (int x = 0; x < line_size()[i] / 2; ++x) {
399 p += stride()[i] / 2;
404 memset (data()[3], 0, sample_size(3).height * stride()[3]);
410 Image::swap_16 (uint16_t v)
412 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
417 Image::make_part_black (int const start, int const width)
419 auto y_part = [&]() {
420 int const bpp = bytes_per_pixel(0);
421 int const h = sample_size(0).height;
422 int const s = stride()[0];
424 for (int y = 0; y < h; ++y) {
425 memset (p + start * bpp, 0, width * bpp);
430 switch (_pixel_format) {
431 case AV_PIX_FMT_RGB24:
432 case AV_PIX_FMT_ARGB:
433 case AV_PIX_FMT_RGBA:
434 case AV_PIX_FMT_ABGR:
435 case AV_PIX_FMT_BGRA:
436 case AV_PIX_FMT_RGB555LE:
437 case AV_PIX_FMT_RGB48LE:
438 case AV_PIX_FMT_RGB48BE:
439 case AV_PIX_FMT_XYZ12LE:
441 int const h = sample_size(0).height;
442 int const bpp = bytes_per_pixel(0);
443 int const s = stride()[0];
444 uint8_t* p = data()[0];
445 for (int y = 0; y < h; y++) {
446 memset (p + start * bpp, 0, width * bpp);
451 case AV_PIX_FMT_YUV420P:
454 for (int i = 1; i < 3; ++i) {
456 int const h = sample_size(i).height;
457 for (int y = 0; y < h; ++y) {
458 for (int x = start / 2; x < (start + width) / 2; ++x) {
466 case AV_PIX_FMT_YUV422P10LE:
469 for (int i = 1; i < 3; ++i) {
470 auto p = reinterpret_cast<int16_t*>(data()[i]);
471 int const h = sample_size(i).height;
472 for (int y = 0; y < h; ++y) {
473 for (int x = start / 2; x < (start + width) / 2; ++x) {
476 p += stride()[i] / 2;
481 case AV_PIX_FMT_YUV444P10LE:
484 for (int i = 1; i < 3; ++i) {
485 auto p = reinterpret_cast<int16_t*>(data()[i]);
486 int const h = sample_size(i).height;
487 for (int y = 0; y < h; ++y) {
488 for (int x = start; x < (start + width); ++x) {
491 p += stride()[i] / 2;
497 throw PixelFormatError ("make_part_black()", _pixel_format);
505 switch (_pixel_format) {
506 case AV_PIX_FMT_YUV420P:
507 case AV_PIX_FMT_YUV422P:
508 case AV_PIX_FMT_YUV444P:
509 case AV_PIX_FMT_YUV411P:
510 memset (data()[0], 0, sample_size(0).height * stride()[0]);
511 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
512 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
515 case AV_PIX_FMT_YUVJ420P:
516 case AV_PIX_FMT_YUVJ422P:
517 case AV_PIX_FMT_YUVJ444P:
518 memset (data()[0], 0, sample_size(0).height * stride()[0]);
519 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
520 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
523 case AV_PIX_FMT_YUV422P9LE:
524 case AV_PIX_FMT_YUV444P9LE:
525 yuv_16_black (nine_bit_uv, false);
528 case AV_PIX_FMT_YUV422P9BE:
529 case AV_PIX_FMT_YUV444P9BE:
530 yuv_16_black (swap_16 (nine_bit_uv), false);
533 case AV_PIX_FMT_YUV422P10LE:
534 case AV_PIX_FMT_YUV444P10LE:
535 yuv_16_black (ten_bit_uv, false);
538 case AV_PIX_FMT_YUV422P16LE:
539 case AV_PIX_FMT_YUV444P16LE:
540 yuv_16_black (sixteen_bit_uv, false);
543 case AV_PIX_FMT_YUV444P10BE:
544 case AV_PIX_FMT_YUV422P10BE:
545 yuv_16_black (swap_16 (ten_bit_uv), false);
548 case AV_PIX_FMT_YUVA420P9BE:
549 case AV_PIX_FMT_YUVA422P9BE:
550 case AV_PIX_FMT_YUVA444P9BE:
551 yuv_16_black (swap_16 (nine_bit_uv), true);
554 case AV_PIX_FMT_YUVA420P9LE:
555 case AV_PIX_FMT_YUVA422P9LE:
556 case AV_PIX_FMT_YUVA444P9LE:
557 yuv_16_black (nine_bit_uv, true);
560 case AV_PIX_FMT_YUVA420P10BE:
561 case AV_PIX_FMT_YUVA422P10BE:
562 case AV_PIX_FMT_YUVA444P10BE:
563 yuv_16_black (swap_16 (ten_bit_uv), true);
566 case AV_PIX_FMT_YUVA420P10LE:
567 case AV_PIX_FMT_YUVA422P10LE:
568 case AV_PIX_FMT_YUVA444P10LE:
569 yuv_16_black (ten_bit_uv, true);
572 case AV_PIX_FMT_YUVA420P16BE:
573 case AV_PIX_FMT_YUVA422P16BE:
574 case AV_PIX_FMT_YUVA444P16BE:
575 yuv_16_black (swap_16 (sixteen_bit_uv), true);
578 case AV_PIX_FMT_YUVA420P16LE:
579 case AV_PIX_FMT_YUVA422P16LE:
580 case AV_PIX_FMT_YUVA444P16LE:
581 yuv_16_black (sixteen_bit_uv, true);
584 case AV_PIX_FMT_RGB24:
585 case AV_PIX_FMT_ARGB:
586 case AV_PIX_FMT_RGBA:
587 case AV_PIX_FMT_ABGR:
588 case AV_PIX_FMT_BGRA:
589 case AV_PIX_FMT_RGB555LE:
590 case AV_PIX_FMT_RGB48LE:
591 case AV_PIX_FMT_RGB48BE:
592 case AV_PIX_FMT_XYZ12LE:
593 memset (data()[0], 0, sample_size(0).height * stride()[0]);
596 case AV_PIX_FMT_UYVY422:
598 int const Y = sample_size(0).height;
599 int const X = line_size()[0];
600 uint8_t* p = data()[0];
601 for (int y = 0; y < Y; ++y) {
602 for (int x = 0; x < X / 4; ++x) {
603 *p++ = eight_bit_uv; // Cb
605 *p++ = eight_bit_uv; // Cr
613 throw PixelFormatError ("make_black()", _pixel_format);
619 Image::make_transparent ()
621 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
622 throw PixelFormatError ("make_transparent()", _pixel_format);
625 memset (data()[0], 0, sample_size(0).height * stride()[0]);
630 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
632 /* We're blending RGBA or BGRA images */
633 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
634 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
635 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
637 int const other_bpp = 4;
639 int start_tx = position.x;
643 start_ox = -start_tx;
647 int start_ty = position.y;
651 start_oy = -start_ty;
655 switch (_pixel_format) {
656 case AV_PIX_FMT_RGB24:
658 /* Going onto RGB24. First byte is red, second green, third blue */
659 int const this_bpp = 3;
660 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
661 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
662 uint8_t* op = other->data()[0] + oy * other->stride()[0];
663 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
664 float const alpha = float (op[3]) / 255;
665 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
666 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
667 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
675 case AV_PIX_FMT_BGRA:
677 int const this_bpp = 4;
678 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
679 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
680 uint8_t* op = other->data()[0] + oy * other->stride()[0];
681 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
682 float const alpha = float (op[3]) / 255;
683 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
684 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
685 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
686 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
694 case AV_PIX_FMT_RGBA:
696 int const this_bpp = 4;
697 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
698 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
699 uint8_t* op = other->data()[0] + oy * other->stride()[0];
700 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
701 float const alpha = float (op[3]) / 255;
702 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
703 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
704 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
705 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
713 case AV_PIX_FMT_RGB48LE:
715 int const this_bpp = 6;
716 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
717 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
718 uint8_t* op = other->data()[0] + oy * other->stride()[0];
719 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
720 float const alpha = float (op[3]) / 255;
721 /* Blend high bytes */
722 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
723 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
724 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
732 case AV_PIX_FMT_XYZ12LE:
734 auto conv = dcp::ColourConversion::srgb_to_xyz();
735 double fast_matrix[9];
736 dcp::combined_rgb_to_xyz (conv, fast_matrix);
737 auto lut_in = conv.in()->lut(0, 1, 8, false);
738 auto lut_out = conv.out()->lut(0, 1, 16, true);
739 int const this_bpp = 6;
740 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
741 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
742 uint8_t* op = other->data()[0] + oy * other->stride()[0];
743 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
744 float const alpha = float (op[3]) / 255;
746 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
747 double const r = lut_in[op[red]];
748 double const g = lut_in[op[1]];
749 double const b = lut_in[op[blue]];
751 /* RGB to XYZ, including Bradford transform and DCI companding */
752 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
753 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
754 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
756 /* Out gamma LUT and blend */
757 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
758 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
759 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
767 case AV_PIX_FMT_YUV420P:
769 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
770 dcp::Size const ts = size();
771 dcp::Size const os = yuv->size();
772 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
773 int const hty = ty / 2;
774 int const hoy = oy / 2;
775 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
776 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
777 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
778 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
779 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
780 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
781 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
782 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
783 float const a = float(alpha[3]) / 255;
784 *tY = *oY * a + *tY * (1 - a);
785 *tU = *oU * a + *tU * (1 - a);
786 *tV = *oV * a + *tV * (1 - a);
802 case AV_PIX_FMT_YUV420P10:
804 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
805 dcp::Size const ts = size();
806 dcp::Size const os = yuv->size();
807 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
808 int const hty = ty / 2;
809 int const hoy = oy / 2;
810 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
811 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
812 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
813 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
814 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
815 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
816 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
817 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
818 float const a = float(alpha[3]) / 255;
819 *tY = *oY * a + *tY * (1 - a);
820 *tU = *oU * a + *tU * (1 - a);
821 *tV = *oV * a + *tV * (1 - a);
837 case AV_PIX_FMT_YUV422P10LE:
839 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
840 dcp::Size const ts = size();
841 dcp::Size const os = yuv->size();
842 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
843 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
844 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
845 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
846 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
847 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
848 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
849 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
850 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
851 float const a = float(alpha[3]) / 255;
852 *tY = *oY * a + *tY * (1 - a);
853 *tU = *oU * a + *tU * (1 - a);
854 *tV = *oV * a + *tV * (1 - a);
871 throw PixelFormatError ("alpha_blend()", _pixel_format);
877 Image::copy (shared_ptr<const Image> other, Position<int> position)
879 /* Only implemented for RGB24 onto RGB24 so far */
880 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
881 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
883 int const N = min (position.x + other->size().width, size().width) - position.x;
884 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
885 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
886 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
887 memcpy (tp, op, N * 3);
893 Image::read_from_socket (shared_ptr<Socket> socket)
895 for (int i = 0; i < planes(); ++i) {
896 uint8_t* p = data()[i];
897 int const lines = sample_size(i).height;
898 for (int y = 0; y < lines; ++y) {
899 socket->read (p, line_size()[i]);
907 Image::write_to_socket (shared_ptr<Socket> socket) const
909 for (int i = 0; i < planes(); ++i) {
910 uint8_t* p = data()[i];
911 int const lines = sample_size(i).height;
912 for (int y = 0; y < lines; ++y) {
913 socket->write (p, line_size()[i]);
921 Image::bytes_per_pixel (int c) const
923 auto d = av_pix_fmt_desc_get(_pixel_format);
925 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
932 float bpp[4] = { 0, 0, 0, 0 };
934 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
935 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
936 if (d->nb_components > 1) {
937 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
939 if (d->nb_components > 2) {
940 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
942 if (d->nb_components > 3) {
943 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
946 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
947 if (d->nb_components > 1) {
948 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
950 if (d->nb_components > 2) {
951 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
953 if (d->nb_components > 3) {
954 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
958 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
959 /* Not planar; sum them up */
960 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
967 /** Construct a Image of a given size and format, allocating memory
970 * @param p Pixel format.
971 * @param s Size in pixels.
972 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
974 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
977 , _alignment (alignment)
986 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
987 _data[0] = _data[1] = _data[2] = _data[3] = 0;
989 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
990 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
992 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
993 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
995 auto stride_round_up = [](int stride, int t) {
996 int const a = stride + (t - 1);
1000 for (int i = 0; i < planes(); ++i) {
1001 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
1002 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
1004 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
1005 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
1006 Hence on the last pixel of the last line it reads over the end of
1007 the actual data by 1 byte. If the width of an image is a multiple
1008 of the stride alignment there will be no padding at the end of image lines.
1009 OS X crashes on this illegal read, though other operating systems don't
1010 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
1011 for that instruction to read safely.
1013 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
1014 over-reads by more then _avx. I can't follow the code to work out how much,
1015 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1016 testing suggests that it works.
1018 In addition to these concerns, we may read/write as much as a whole extra line
1019 at the end of each plane in cases where we are messing with offsets in order to
1020 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1022 As an example: we may write to images starting at an offset so we get some padding.
1023 Hence we want to write in the following pattern:
1025 block start write start line end
1026 |..(padding)..|<------line-size------------->|..(padding)..|
1027 |..(padding)..|<------line-size------------->|..(padding)..|
1028 |..(padding)..|<------line-size------------->|..(padding)..|
1030 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1031 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1032 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1033 specified *stride*. This does not matter until we get to the last line:
1035 block start write start line end
1036 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1037 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1038 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1041 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1042 #if HAVE_VALGRIND_MEMCHECK_H
1043 /* The data between the end of the line size and the stride is undefined but processed by
1044 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1046 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1052 Image::Image (Image const & other)
1053 : std::enable_shared_from_this<Image>(other)
1054 , _size (other._size)
1055 , _pixel_format (other._pixel_format)
1056 , _alignment (other._alignment)
1060 for (int i = 0; i < planes(); ++i) {
1061 uint8_t* p = _data[i];
1062 uint8_t* q = other._data[i];
1063 int const lines = sample_size(i).height;
1064 for (int j = 0; j < lines; ++j) {
1065 memcpy (p, q, _line_size[i]);
1067 q += other.stride()[i];
1073 Image::Image (AVFrame const * frame, Alignment alignment)
1074 : _size (frame->width, frame->height)
1075 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1076 , _alignment (alignment)
1078 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1082 for (int i = 0; i < planes(); ++i) {
1083 uint8_t* p = _data[i];
1084 uint8_t* q = frame->data[i];
1085 int const lines = sample_size(i).height;
1086 for (int j = 0; j < lines; ++j) {
1087 memcpy (p, q, _line_size[i]);
1089 /* AVFrame's linesize is what we call `stride' */
1090 q += frame->linesize[i];
1096 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1097 : _size (other->_size)
1098 , _pixel_format (other->_pixel_format)
1099 , _alignment (alignment)
1103 for (int i = 0; i < planes(); ++i) {
1104 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1105 uint8_t* p = _data[i];
1106 uint8_t* q = other->data()[i];
1107 int const lines = sample_size(i).height;
1108 for (int j = 0; j < lines; ++j) {
1109 memcpy (p, q, line_size()[i]);
1111 q += other->stride()[i];
1118 Image::operator= (Image const & other)
1120 if (this == &other) {
1131 Image::swap (Image & other)
1133 std::swap (_size, other._size);
1134 std::swap (_pixel_format, other._pixel_format);
1136 for (int i = 0; i < 4; ++i) {
1137 std::swap (_data[i], other._data[i]);
1138 std::swap (_line_size[i], other._line_size[i]);
1139 std::swap (_stride[i], other._stride[i]);
1142 std::swap (_alignment, other._alignment);
1148 for (int i = 0; i < planes(); ++i) {
1153 av_free (_line_size);
1159 Image::data () const
1166 Image::line_size () const
1173 Image::stride () const
1180 Image::size () const
1187 Image::alignment () const
1194 merge (list<PositionImage> images, Image::Alignment alignment)
1196 if (images.empty ()) {
1200 if (images.size() == 1) {
1201 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1202 return images.front();
1205 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1206 for (auto const& i: images) {
1207 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1210 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1211 merged->make_transparent ();
1212 for (auto const& i: images) {
1213 merged->alpha_blend (i.image, i.position - all.position());
1216 return PositionImage (merged, all.position ());
1221 operator== (Image const & a, Image const & b)
1223 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1227 for (int c = 0; c < a.planes(); ++c) {
1228 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]) {
1232 uint8_t* p = a.data()[c];
1233 uint8_t* q = b.data()[c];
1234 int const lines = a.sample_size(c).height;
1235 for (int y = 0; y < lines; ++y) {
1236 if (memcmp (p, q, a.line_size()[c]) != 0) {
1250 * @param f Amount to fade by; 0 is black, 1 is no fade.
1253 Image::fade (float f)
1255 /* U/V black value for 8-bit colour */
1256 static int const eight_bit_uv = (1 << 7) - 1;
1257 /* U/V black value for 10-bit colour */
1258 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1260 switch (_pixel_format) {
1261 case AV_PIX_FMT_YUV420P:
1264 uint8_t* p = data()[0];
1265 int const lines = sample_size(0).height;
1266 for (int y = 0; y < lines; ++y) {
1268 for (int x = 0; x < line_size()[0]; ++x) {
1269 *q = int(float(*q) * f);
1276 for (int c = 1; c < 3; ++c) {
1277 uint8_t* p = data()[c];
1278 int const lines = sample_size(c).height;
1279 for (int y = 0; y < lines; ++y) {
1281 for (int x = 0; x < line_size()[c]; ++x) {
1282 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1292 case AV_PIX_FMT_RGB24:
1295 uint8_t* p = data()[0];
1296 int const lines = sample_size(0).height;
1297 for (int y = 0; y < lines; ++y) {
1299 for (int x = 0; x < line_size()[0]; ++x) {
1300 *q = int (float (*q) * f);
1308 case AV_PIX_FMT_XYZ12LE:
1309 case AV_PIX_FMT_RGB48LE:
1310 /* 16-bit little-endian */
1311 for (int c = 0; c < 3; ++c) {
1312 int const stride_pixels = stride()[c] / 2;
1313 int const line_size_pixels = line_size()[c] / 2;
1314 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1315 int const lines = sample_size(c).height;
1316 for (int y = 0; y < lines; ++y) {
1318 for (int x = 0; x < line_size_pixels; ++x) {
1319 *q = int (float (*q) * f);
1327 case AV_PIX_FMT_YUV422P10LE:
1331 int const stride_pixels = stride()[0] / 2;
1332 int const line_size_pixels = line_size()[0] / 2;
1333 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1334 int const lines = sample_size(0).height;
1335 for (int y = 0; y < lines; ++y) {
1337 for (int x = 0; x < line_size_pixels; ++x) {
1338 *q = int(float(*q) * f);
1346 for (int c = 1; c < 3; ++c) {
1347 int const stride_pixels = stride()[c] / 2;
1348 int const line_size_pixels = line_size()[c] / 2;
1349 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1350 int const lines = sample_size(c).height;
1351 for (int y = 0; y < lines; ++y) {
1353 for (int x = 0; x < line_size_pixels; ++x) {
1354 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1365 throw PixelFormatError ("fade()", _pixel_format);
1370 shared_ptr<const Image>
1371 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1373 if (image->alignment() == alignment) {
1377 return make_shared<Image>(image, alignment);
1382 Image::memory_used () const
1385 for (int i = 0; i < planes(); ++i) {
1386 m += _stride[i] * sample_size(i).height;
1393 Image::video_range_to_full_range ()
1395 switch (_pixel_format) {
1396 case AV_PIX_FMT_RGB24:
1398 float const factor = 256.0 / 219.0;
1399 uint8_t* p = data()[0];
1400 int const lines = sample_size(0).height;
1401 for (int y = 0; y < lines; ++y) {
1403 for (int x = 0; x < line_size()[0]; ++x) {
1404 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1411 case AV_PIX_FMT_RGB48LE:
1413 float const factor = 65536.0 / 56064.0;
1414 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1415 int const lines = sample_size(0).height;
1416 for (int y = 0; y < lines; ++y) {
1418 int const line_size_pixels = line_size()[0] / 2;
1419 for (int x = 0; x < line_size_pixels; ++x) {
1420 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1423 p += stride()[0] / 2;
1427 case AV_PIX_FMT_GBRP12LE:
1429 float const factor = 4096.0 / 3504.0;
1430 for (int c = 0; c < 3; ++c) {
1431 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1432 int const lines = sample_size(c).height;
1433 for (int y = 0; y < lines; ++y) {
1435 int const line_size_pixels = line_size()[c] / 2;
1436 for (int x = 0; x < line_size_pixels; ++x) {
1437 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1445 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);