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 "enum_indexed_vector.h"
31 #include "exceptions.h"
33 #include "maths_util.h"
34 #include "memory_util.h"
37 #include <dcp/rgb_xyz.h>
38 #include <dcp/transfer_function.h>
39 #include <dcp/warnings.h>
40 LIBDCP_DISABLE_WARNINGS
42 #include <libavutil/frame.h>
43 #include <libavutil/pixdesc.h>
44 #include <libavutil/pixfmt.h>
45 #include <libswscale/swscale.h>
47 LIBDCP_ENABLE_WARNINGS
48 #if HAVE_VALGRIND_MEMCHECK_H
49 #include <valgrind/memcheck.h>
60 using std::make_shared;
63 using std::runtime_error;
64 using std::shared_ptr;
69 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
70 int constexpr ALIGNMENT = 64;
72 /* U/V black value for 8-bit colour */
73 static uint8_t const eight_bit_uv = (1 << 7) - 1;
74 /* U/V black value for 9-bit colour */
75 static uint16_t const nine_bit_uv = (1 << 8) - 1;
76 /* U/V black value for 10-bit colour */
77 static uint16_t const ten_bit_uv = (1 << 9) - 1;
78 /* U/V black value for 16-bit colour */
79 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
83 Image::vertical_factor (int n) const
89 auto d = av_pix_fmt_desc_get(_pixel_format);
91 throw PixelFormatError ("line_factor()", _pixel_format);
94 return lrintf(powf(2.0f, d->log2_chroma_h));
98 Image::horizontal_factor (int n) const
104 auto d = av_pix_fmt_desc_get(_pixel_format);
106 throw PixelFormatError ("sample_size()", _pixel_format);
109 return lrintf(powf(2.0f, d->log2_chroma_w));
113 /** @param n Component index.
114 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
117 Image::sample_size (int n) const
120 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
121 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
126 /** @return Number of planes */
128 Image::planes () const
130 if (_pixel_format == AV_PIX_FMT_PAL8) {
134 auto d = av_pix_fmt_desc_get(_pixel_format);
136 throw PixelFormatError ("planes()", _pixel_format);
139 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
143 return d->nb_components;
149 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
151 return p & ~ ((1 << desc->log2_chroma_w) - 1);
157 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
159 return p & ~ ((1 << desc->log2_chroma_h) - 1);
163 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
164 * @param crop Amount to crop by.
165 * @param inter_size Size to scale the cropped image to.
166 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
167 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
168 * @param video_range Video range of the image.
169 * @param out_format Output pixel format.
170 * @param out_aligned true to make the output image aligned.
171 * @param out_video_range Video range to use for the output image.
172 * @param fast Try to be fast at the possible expense of quality; at present this means using
173 * fast bilinear rather than bicubic scaling.
176 Image::crop_scale_window (
178 dcp::Size inter_size,
180 dcp::YUVToRGB yuv_to_rgb,
181 VideoRange video_range,
182 AVPixelFormat out_format,
183 VideoRange out_video_range,
184 Alignment out_alignment,
188 /* Empirical testing suggests that sws_scale() will crash if
189 the input image is not padded.
191 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
193 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
194 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
196 auto out = make_shared<Image>(out_format, out_size, out_alignment);
199 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
201 throw PixelFormatError ("crop_scale_window()", _pixel_format);
204 /* Round down so that we crop only the number of pixels that is straightforward
205 * considering any subsampling.
208 round_width_for_subsampling(crop.left, in_desc),
209 round_width_for_subsampling(crop.right, in_desc),
210 round_height_for_subsampling(crop.top, in_desc),
211 round_height_for_subsampling(crop.bottom, in_desc)
214 /* Also check that we aren't cropping more image than there actually is */
215 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
216 corrected_crop.left = 0;
217 corrected_crop.right = size().width - 4;
220 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
221 corrected_crop.top = 0;
222 corrected_crop.bottom = size().height - 4;
225 /* Size of the image after any crop */
226 auto const cropped_size = corrected_crop.apply (size());
228 /* Scale context for a scale from cropped_size to inter_size */
229 auto scale_context = sws_getContext (
230 cropped_size.width, cropped_size.height, pixel_format(),
231 inter_size.width, inter_size.height, out_format,
232 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
235 if (!scale_context) {
236 throw runtime_error (N_("Could not allocate SwsContext"));
239 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
240 EnumIndexedVector<int, dcp::YUVToRGB> lut;
241 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
242 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
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[yuv_to_rgb]), video_range == VideoRange::VIDEO ? 0 : 1,
258 sws_getCoefficients(lut[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 EnumIndexedVector<int, dcp::YUVToRGB> lut;
351 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
352 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
354 /* The 3rd parameter here is:
355 0 -> source range MPEG (i.e. "video", 16-235)
356 1 -> source range JPEG (i.e. "full", 0-255)
358 0 -> destination range MPEG (i.e. "video", 16-235)
359 1 -> destination range JPEG (i.e. "full", 0-255)
361 But remember: sws_setColorspaceDetails ignores these
362 parameters unless the corresponding image isYUV or isGray.
363 (If it's neither, it uses video range).
365 sws_setColorspaceDetails (
367 sws_getCoefficients(lut[yuv_to_rgb]), 0,
368 sws_getCoefficients(lut[yuv_to_rgb]), 0,
376 scaled->data(), scaled->stride()
379 sws_freeContext (scale_context);
385 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
387 Image::yuv_16_black (uint16_t v, bool alpha)
389 memset (data()[0], 0, sample_size(0).height * stride()[0]);
390 for (int i = 1; i < 3; ++i) {
391 auto p = reinterpret_cast<int16_t*> (data()[i]);
392 int const lines = sample_size(i).height;
393 for (int y = 0; y < lines; ++y) {
394 /* We divide by 2 here because we are writing 2 bytes at a time */
395 for (int x = 0; x < line_size()[i] / 2; ++x) {
398 p += stride()[i] / 2;
403 memset (data()[3], 0, sample_size(3).height * stride()[3]);
409 Image::swap_16 (uint16_t v)
411 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
416 Image::make_part_black (int const start, int const width)
418 auto y_part = [&]() {
419 int const bpp = bytes_per_pixel(0);
420 int const h = sample_size(0).height;
421 int const s = stride()[0];
423 for (int y = 0; y < h; ++y) {
424 memset (p + start * bpp, 0, width * bpp);
429 switch (_pixel_format) {
430 case AV_PIX_FMT_RGB24:
431 case AV_PIX_FMT_ARGB:
432 case AV_PIX_FMT_RGBA:
433 case AV_PIX_FMT_ABGR:
434 case AV_PIX_FMT_BGRA:
435 case AV_PIX_FMT_RGB555LE:
436 case AV_PIX_FMT_RGB48LE:
437 case AV_PIX_FMT_RGB48BE:
438 case AV_PIX_FMT_XYZ12LE:
440 int const h = sample_size(0).height;
441 int const bpp = bytes_per_pixel(0);
442 int const s = stride()[0];
443 uint8_t* p = data()[0];
444 for (int y = 0; y < h; y++) {
445 memset (p + start * bpp, 0, width * bpp);
450 case AV_PIX_FMT_YUV420P:
453 for (int i = 1; i < 3; ++i) {
455 int const h = sample_size(i).height;
456 for (int y = 0; y < h; ++y) {
457 for (int x = start / 2; x < (start + width) / 2; ++x) {
465 case AV_PIX_FMT_YUV422P10LE:
468 for (int i = 1; i < 3; ++i) {
469 auto p = reinterpret_cast<int16_t*>(data()[i]);
470 int const h = sample_size(i).height;
471 for (int y = 0; y < h; ++y) {
472 for (int x = start / 2; x < (start + width) / 2; ++x) {
475 p += stride()[i] / 2;
480 case AV_PIX_FMT_YUV444P10LE:
483 for (int i = 1; i < 3; ++i) {
484 auto p = reinterpret_cast<int16_t*>(data()[i]);
485 int const h = sample_size(i).height;
486 for (int y = 0; y < h; ++y) {
487 for (int x = start; x < (start + width); ++x) {
490 p += stride()[i] / 2;
496 throw PixelFormatError ("make_part_black()", _pixel_format);
504 switch (_pixel_format) {
505 case AV_PIX_FMT_YUV420P:
506 case AV_PIX_FMT_YUV422P:
507 case AV_PIX_FMT_YUV444P:
508 case AV_PIX_FMT_YUV411P:
509 memset (data()[0], 0, sample_size(0).height * stride()[0]);
510 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
511 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
514 case AV_PIX_FMT_YUVJ420P:
515 case AV_PIX_FMT_YUVJ422P:
516 case AV_PIX_FMT_YUVJ444P:
517 memset (data()[0], 0, sample_size(0).height * stride()[0]);
518 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
519 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
522 case AV_PIX_FMT_YUV422P9LE:
523 case AV_PIX_FMT_YUV444P9LE:
524 yuv_16_black (nine_bit_uv, false);
527 case AV_PIX_FMT_YUV422P9BE:
528 case AV_PIX_FMT_YUV444P9BE:
529 yuv_16_black (swap_16 (nine_bit_uv), false);
532 case AV_PIX_FMT_YUV422P10LE:
533 case AV_PIX_FMT_YUV444P10LE:
534 yuv_16_black (ten_bit_uv, false);
537 case AV_PIX_FMT_YUV422P16LE:
538 case AV_PIX_FMT_YUV444P16LE:
539 yuv_16_black (sixteen_bit_uv, false);
542 case AV_PIX_FMT_YUV444P10BE:
543 case AV_PIX_FMT_YUV422P10BE:
544 yuv_16_black (swap_16 (ten_bit_uv), false);
547 case AV_PIX_FMT_YUVA420P9BE:
548 case AV_PIX_FMT_YUVA422P9BE:
549 case AV_PIX_FMT_YUVA444P9BE:
550 yuv_16_black (swap_16 (nine_bit_uv), true);
553 case AV_PIX_FMT_YUVA420P9LE:
554 case AV_PIX_FMT_YUVA422P9LE:
555 case AV_PIX_FMT_YUVA444P9LE:
556 yuv_16_black (nine_bit_uv, true);
559 case AV_PIX_FMT_YUVA420P10BE:
560 case AV_PIX_FMT_YUVA422P10BE:
561 case AV_PIX_FMT_YUVA444P10BE:
562 yuv_16_black (swap_16 (ten_bit_uv), true);
565 case AV_PIX_FMT_YUVA420P10LE:
566 case AV_PIX_FMT_YUVA422P10LE:
567 case AV_PIX_FMT_YUVA444P10LE:
568 yuv_16_black (ten_bit_uv, true);
571 case AV_PIX_FMT_YUVA420P16BE:
572 case AV_PIX_FMT_YUVA422P16BE:
573 case AV_PIX_FMT_YUVA444P16BE:
574 yuv_16_black (swap_16 (sixteen_bit_uv), true);
577 case AV_PIX_FMT_YUVA420P16LE:
578 case AV_PIX_FMT_YUVA422P16LE:
579 case AV_PIX_FMT_YUVA444P16LE:
580 yuv_16_black (sixteen_bit_uv, true);
583 case AV_PIX_FMT_RGB24:
584 case AV_PIX_FMT_ARGB:
585 case AV_PIX_FMT_RGBA:
586 case AV_PIX_FMT_ABGR:
587 case AV_PIX_FMT_BGRA:
588 case AV_PIX_FMT_RGB555LE:
589 case AV_PIX_FMT_RGB48LE:
590 case AV_PIX_FMT_RGB48BE:
591 case AV_PIX_FMT_XYZ12LE:
592 memset (data()[0], 0, sample_size(0).height * stride()[0]);
595 case AV_PIX_FMT_UYVY422:
597 int const Y = sample_size(0).height;
598 int const X = line_size()[0];
599 uint8_t* p = data()[0];
600 for (int y = 0; y < Y; ++y) {
601 for (int x = 0; x < X / 4; ++x) {
602 *p++ = eight_bit_uv; // Cb
604 *p++ = eight_bit_uv; // Cr
612 throw PixelFormatError ("make_black()", _pixel_format);
618 Image::make_transparent ()
620 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
621 throw PixelFormatError ("make_transparent()", _pixel_format);
624 memset (data()[0], 0, sample_size(0).height * stride()[0]);
629 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
631 /* We're blending RGBA or BGRA images */
632 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
633 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
634 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
636 int const other_bpp = 4;
638 int start_tx = position.x;
642 start_ox = -start_tx;
646 int start_ty = position.y;
650 start_oy = -start_ty;
654 switch (_pixel_format) {
655 case AV_PIX_FMT_RGB24:
657 /* Going onto RGB24. First byte is red, second green, third blue */
658 int const this_bpp = 3;
659 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
660 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
661 uint8_t* op = other->data()[0] + oy * other->stride()[0];
662 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
663 float const alpha = float (op[3]) / 255;
664 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
665 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
666 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
674 case AV_PIX_FMT_BGRA:
676 int const this_bpp = 4;
677 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
678 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
679 uint8_t* op = other->data()[0] + oy * other->stride()[0];
680 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
681 float const alpha = float (op[3]) / 255;
682 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
683 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
684 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
685 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
693 case AV_PIX_FMT_RGBA:
695 int const this_bpp = 4;
696 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
697 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
698 uint8_t* op = other->data()[0] + oy * other->stride()[0];
699 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
700 float const alpha = float (op[3]) / 255;
701 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
702 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
703 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
704 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
712 case AV_PIX_FMT_RGB48LE:
714 int const this_bpp = 6;
715 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
716 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
717 uint8_t* op = other->data()[0] + oy * other->stride()[0];
718 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
719 float const alpha = float (op[3]) / 255;
720 /* Blend high bytes */
721 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
722 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
723 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
731 case AV_PIX_FMT_XYZ12LE:
733 auto conv = dcp::ColourConversion::srgb_to_xyz();
734 double fast_matrix[9];
735 dcp::combined_rgb_to_xyz (conv, fast_matrix);
736 auto lut_in = conv.in()->lut(0, 1, 8, false);
737 auto lut_out = conv.out()->lut(0, 1, 16, true);
738 int const this_bpp = 6;
739 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
740 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
741 uint8_t* op = other->data()[0] + oy * other->stride()[0];
742 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
743 float const alpha = float (op[3]) / 255;
745 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
746 double const r = lut_in[op[red]];
747 double const g = lut_in[op[1]];
748 double const b = lut_in[op[blue]];
750 /* RGB to XYZ, including Bradford transform and DCI companding */
751 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
752 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
753 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
755 /* Out gamma LUT and blend */
756 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
757 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
758 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
766 case AV_PIX_FMT_YUV420P:
768 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
769 dcp::Size const ts = size();
770 dcp::Size const os = yuv->size();
771 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
772 int const hty = ty / 2;
773 int const hoy = oy / 2;
774 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
775 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
776 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
777 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
778 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
779 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
780 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
781 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
782 float const a = float(alpha[3]) / 255;
783 *tY = *oY * a + *tY * (1 - a);
784 *tU = *oU * a + *tU * (1 - a);
785 *tV = *oV * a + *tV * (1 - a);
801 case AV_PIX_FMT_YUV420P10:
803 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
804 dcp::Size const ts = size();
805 dcp::Size const os = yuv->size();
806 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
807 int const hty = ty / 2;
808 int const hoy = oy / 2;
809 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
810 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
811 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
812 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
813 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
814 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
815 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
816 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
817 float const a = float(alpha[3]) / 255;
818 *tY = *oY * a + *tY * (1 - a);
819 *tU = *oU * a + *tU * (1 - a);
820 *tV = *oV * a + *tV * (1 - a);
836 case AV_PIX_FMT_YUV422P10LE:
838 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
839 dcp::Size const ts = size();
840 dcp::Size const os = yuv->size();
841 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
842 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
843 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
844 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
845 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
846 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
847 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
848 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
849 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
850 float const a = float(alpha[3]) / 255;
851 *tY = *oY * a + *tY * (1 - a);
852 *tU = *oU * a + *tU * (1 - a);
853 *tV = *oV * a + *tV * (1 - a);
870 throw PixelFormatError ("alpha_blend()", _pixel_format);
876 Image::copy (shared_ptr<const Image> other, Position<int> position)
878 /* Only implemented for RGB24 onto RGB24 so far */
879 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
880 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
882 int const N = min (position.x + other->size().width, size().width) - position.x;
883 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
884 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
885 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
886 memcpy (tp, op, N * 3);
892 Image::read_from_socket (shared_ptr<Socket> socket)
894 for (int i = 0; i < planes(); ++i) {
895 uint8_t* p = data()[i];
896 int const lines = sample_size(i).height;
897 for (int y = 0; y < lines; ++y) {
898 socket->read (p, line_size()[i]);
906 Image::write_to_socket (shared_ptr<Socket> socket) const
908 for (int i = 0; i < planes(); ++i) {
909 uint8_t* p = data()[i];
910 int const lines = sample_size(i).height;
911 for (int y = 0; y < lines; ++y) {
912 socket->write (p, line_size()[i]);
920 Image::bytes_per_pixel (int c) const
922 auto d = av_pix_fmt_desc_get(_pixel_format);
924 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
931 float bpp[4] = { 0, 0, 0, 0 };
933 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
934 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
935 if (d->nb_components > 1) {
936 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
938 if (d->nb_components > 2) {
939 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
941 if (d->nb_components > 3) {
942 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
945 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
946 if (d->nb_components > 1) {
947 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
949 if (d->nb_components > 2) {
950 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
952 if (d->nb_components > 3) {
953 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
957 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
958 /* Not planar; sum them up */
959 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
966 /** Construct a Image of a given size and format, allocating memory
969 * @param p Pixel format.
970 * @param s Size in pixels.
971 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
973 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
976 , _alignment (alignment)
985 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
986 _data[0] = _data[1] = _data[2] = _data[3] = 0;
988 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
989 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
991 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
992 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
994 auto stride_round_up = [](int stride, int t) {
995 int const a = stride + (t - 1);
999 for (int i = 0; i < planes(); ++i) {
1000 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
1001 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
1003 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
1004 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
1005 Hence on the last pixel of the last line it reads over the end of
1006 the actual data by 1 byte. If the width of an image is a multiple
1007 of the stride alignment there will be no padding at the end of image lines.
1008 OS X crashes on this illegal read, though other operating systems don't
1009 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
1010 for that instruction to read safely.
1012 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
1013 over-reads by more then _avx. I can't follow the code to work out how much,
1014 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1015 testing suggests that it works.
1017 In addition to these concerns, we may read/write as much as a whole extra line
1018 at the end of each plane in cases where we are messing with offsets in order to
1019 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1021 As an example: we may write to images starting at an offset so we get some padding.
1022 Hence we want to write in the following pattern:
1024 block start write start line end
1025 |..(padding)..|<------line-size------------->|..(padding)..|
1026 |..(padding)..|<------line-size------------->|..(padding)..|
1027 |..(padding)..|<------line-size------------->|..(padding)..|
1029 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1030 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1031 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1032 specified *stride*. This does not matter until we get to the last line:
1034 block start write start line end
1035 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1036 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1037 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1040 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1041 #if HAVE_VALGRIND_MEMCHECK_H
1042 /* The data between the end of the line size and the stride is undefined but processed by
1043 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1045 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1051 Image::Image (Image const & other)
1052 : std::enable_shared_from_this<Image>(other)
1053 , _size (other._size)
1054 , _pixel_format (other._pixel_format)
1055 , _alignment (other._alignment)
1059 for (int i = 0; i < planes(); ++i) {
1060 uint8_t* p = _data[i];
1061 uint8_t* q = other._data[i];
1062 int const lines = sample_size(i).height;
1063 for (int j = 0; j < lines; ++j) {
1064 memcpy (p, q, _line_size[i]);
1066 q += other.stride()[i];
1072 Image::Image (AVFrame const * frame, Alignment alignment)
1073 : _size (frame->width, frame->height)
1074 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1075 , _alignment (alignment)
1077 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1081 for (int i = 0; i < planes(); ++i) {
1082 uint8_t* p = _data[i];
1083 uint8_t* q = frame->data[i];
1084 int const lines = sample_size(i).height;
1085 for (int j = 0; j < lines; ++j) {
1086 memcpy (p, q, _line_size[i]);
1088 /* AVFrame's linesize is what we call `stride' */
1089 q += frame->linesize[i];
1095 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1096 : _size (other->_size)
1097 , _pixel_format (other->_pixel_format)
1098 , _alignment (alignment)
1102 for (int i = 0; i < planes(); ++i) {
1103 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1104 uint8_t* p = _data[i];
1105 uint8_t* q = other->data()[i];
1106 int const lines = sample_size(i).height;
1107 for (int j = 0; j < lines; ++j) {
1108 memcpy (p, q, line_size()[i]);
1110 q += other->stride()[i];
1117 Image::operator= (Image const & other)
1119 if (this == &other) {
1130 Image::swap (Image & other)
1132 std::swap (_size, other._size);
1133 std::swap (_pixel_format, other._pixel_format);
1135 for (int i = 0; i < 4; ++i) {
1136 std::swap (_data[i], other._data[i]);
1137 std::swap (_line_size[i], other._line_size[i]);
1138 std::swap (_stride[i], other._stride[i]);
1141 std::swap (_alignment, other._alignment);
1147 for (int i = 0; i < planes(); ++i) {
1152 av_free (_line_size);
1158 Image::data () const
1165 Image::line_size () const
1172 Image::stride () const
1179 Image::size () const
1186 Image::alignment () const
1193 merge (list<PositionImage> images, Image::Alignment alignment)
1195 if (images.empty ()) {
1199 if (images.size() == 1) {
1200 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1201 return images.front();
1204 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1205 for (auto const& i: images) {
1206 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1209 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1210 merged->make_transparent ();
1211 for (auto const& i: images) {
1212 merged->alpha_blend (i.image, i.position - all.position());
1215 return PositionImage (merged, all.position ());
1220 operator== (Image const & a, Image const & b)
1222 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1226 for (int c = 0; c < a.planes(); ++c) {
1227 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]) {
1231 uint8_t* p = a.data()[c];
1232 uint8_t* q = b.data()[c];
1233 int const lines = a.sample_size(c).height;
1234 for (int y = 0; y < lines; ++y) {
1235 if (memcmp (p, q, a.line_size()[c]) != 0) {
1249 * @param f Amount to fade by; 0 is black, 1 is no fade.
1252 Image::fade (float f)
1254 /* U/V black value for 8-bit colour */
1255 static int const eight_bit_uv = (1 << 7) - 1;
1256 /* U/V black value for 10-bit colour */
1257 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1259 switch (_pixel_format) {
1260 case AV_PIX_FMT_YUV420P:
1263 uint8_t* p = data()[0];
1264 int const lines = sample_size(0).height;
1265 for (int y = 0; y < lines; ++y) {
1267 for (int x = 0; x < line_size()[0]; ++x) {
1268 *q = int(float(*q) * f);
1275 for (int c = 1; c < 3; ++c) {
1276 uint8_t* p = data()[c];
1277 int const lines = sample_size(c).height;
1278 for (int y = 0; y < lines; ++y) {
1280 for (int x = 0; x < line_size()[c]; ++x) {
1281 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1291 case AV_PIX_FMT_RGB24:
1294 uint8_t* p = data()[0];
1295 int const lines = sample_size(0).height;
1296 for (int y = 0; y < lines; ++y) {
1298 for (int x = 0; x < line_size()[0]; ++x) {
1299 *q = int (float (*q) * f);
1307 case AV_PIX_FMT_XYZ12LE:
1308 case AV_PIX_FMT_RGB48LE:
1309 /* 16-bit little-endian */
1310 for (int c = 0; c < 3; ++c) {
1311 int const stride_pixels = stride()[c] / 2;
1312 int const line_size_pixels = line_size()[c] / 2;
1313 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1314 int const lines = sample_size(c).height;
1315 for (int y = 0; y < lines; ++y) {
1317 for (int x = 0; x < line_size_pixels; ++x) {
1318 *q = int (float (*q) * f);
1326 case AV_PIX_FMT_YUV422P10LE:
1330 int const stride_pixels = stride()[0] / 2;
1331 int const line_size_pixels = line_size()[0] / 2;
1332 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1333 int const lines = sample_size(0).height;
1334 for (int y = 0; y < lines; ++y) {
1336 for (int x = 0; x < line_size_pixels; ++x) {
1337 *q = int(float(*q) * f);
1345 for (int c = 1; c < 3; ++c) {
1346 int const stride_pixels = stride()[c] / 2;
1347 int const line_size_pixels = line_size()[c] / 2;
1348 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1349 int const lines = sample_size(c).height;
1350 for (int y = 0; y < lines; ++y) {
1352 for (int x = 0; x < line_size_pixels; ++x) {
1353 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1364 throw PixelFormatError ("fade()", _pixel_format);
1369 shared_ptr<const Image>
1370 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1372 if (image->alignment() == alignment) {
1376 return make_shared<Image>(image, alignment);
1381 Image::memory_used () const
1384 for (int i = 0; i < planes(); ++i) {
1385 m += _stride[i] * sample_size(i).height;
1392 Image::video_range_to_full_range ()
1394 switch (_pixel_format) {
1395 case AV_PIX_FMT_RGB24:
1397 float const factor = 256.0 / 219.0;
1398 uint8_t* p = data()[0];
1399 int const lines = sample_size(0).height;
1400 for (int y = 0; y < lines; ++y) {
1402 for (int x = 0; x < line_size()[0]; ++x) {
1403 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1410 case AV_PIX_FMT_RGB48LE:
1412 float const factor = 65536.0 / 56064.0;
1413 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1414 int const lines = sample_size(0).height;
1415 for (int y = 0; y < lines; ++y) {
1417 int const line_size_pixels = line_size()[0] / 2;
1418 for (int x = 0; x < line_size_pixels; ++x) {
1419 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1422 p += stride()[0] / 2;
1426 case AV_PIX_FMT_GBRP12LE:
1428 float const factor = 4096.0 / 3504.0;
1429 for (int c = 0; c < 3; ++c) {
1430 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1431 int const lines = sample_size(c).height;
1432 for (int y = 0; y < lines; ++y) {
1434 int const line_size_pixels = line_size()[c] / 2;
1435 for (int x = 0; x < line_size_pixels; ++x) {
1436 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1444 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);