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/opt.h>
44 #include <libavutil/pixdesc.h>
45 #include <libavutil/pixfmt.h>
46 #include <libswscale/swscale.h>
48 LIBDCP_ENABLE_WARNINGS
49 #if HAVE_VALGRIND_MEMCHECK_H
50 #include <valgrind/memcheck.h>
61 using std::make_shared;
64 using std::runtime_error;
65 using std::shared_ptr;
70 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
71 int constexpr ALIGNMENT = 64;
73 /* U/V black value for 8-bit colour */
74 static uint8_t const eight_bit_uv = (1 << 7) - 1;
75 /* U/V black value for 9-bit colour */
76 static uint16_t const nine_bit_uv = (1 << 8) - 1;
77 /* U/V black value for 10-bit colour */
78 static uint16_t const ten_bit_uv = (1 << 9) - 1;
79 /* U/V black value for 16-bit colour */
80 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
84 Image::vertical_factor (int n) const
90 auto d = av_pix_fmt_desc_get(_pixel_format);
92 throw PixelFormatError ("line_factor()", _pixel_format);
95 return lrintf(powf(2.0f, d->log2_chroma_h));
99 Image::horizontal_factor (int n) const
105 auto d = av_pix_fmt_desc_get(_pixel_format);
107 throw PixelFormatError ("sample_size()", _pixel_format);
110 return lrintf(powf(2.0f, d->log2_chroma_w));
114 /** @param n Component index.
115 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
118 Image::sample_size (int n) const
121 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
122 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
127 /** @return Number of planes */
129 Image::planes () const
131 if (_pixel_format == AV_PIX_FMT_PAL8) {
135 auto d = av_pix_fmt_desc_get(_pixel_format);
137 throw PixelFormatError ("planes()", _pixel_format);
140 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
144 return d->nb_components;
150 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
152 return p & ~ ((1 << desc->log2_chroma_w) - 1);
158 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
160 return p & ~ ((1 << desc->log2_chroma_h) - 1);
164 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
165 * @param crop Amount to crop by.
166 * @param inter_size Size to scale the cropped image to.
167 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
168 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
169 * @param video_range Video range of the image.
170 * @param out_format Output pixel format.
171 * @param out_aligned true to make the output image aligned.
172 * @param out_video_range Video range to use for the output image.
173 * @param fast Try to be fast at the possible expense of quality; at present this means using
174 * fast bilinear rather than bicubic scaling.
177 Image::crop_scale_window (
179 dcp::Size inter_size,
181 dcp::YUVToRGB yuv_to_rgb,
182 VideoRange video_range,
183 AVPixelFormat out_format,
184 VideoRange out_video_range,
185 Alignment out_alignment,
189 /* Empirical testing suggests that sws_scale() will crash if
190 the input image is not padded.
192 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
194 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
195 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
197 auto out = make_shared<Image>(out_format, out_size, out_alignment);
200 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
202 throw PixelFormatError ("crop_scale_window()", _pixel_format);
205 /* Round down so that we crop only the number of pixels that is straightforward
206 * considering any subsampling.
209 round_width_for_subsampling(crop.left, in_desc),
210 round_width_for_subsampling(crop.right, in_desc),
211 round_height_for_subsampling(crop.top, in_desc),
212 round_height_for_subsampling(crop.bottom, in_desc)
215 /* Also check that we aren't cropping more image than there actually is */
216 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
217 corrected_crop.left = 0;
218 corrected_crop.right = size().width - 4;
221 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
222 corrected_crop.top = 0;
223 corrected_crop.bottom = size().height - 4;
226 /* Size of the image after any crop */
227 auto const cropped_size = corrected_crop.apply (size());
229 /* Scale context for a scale from cropped_size to inter_size */
230 auto scale_context = sws_getContext (
231 cropped_size.width, cropped_size.height, pixel_format(),
232 inter_size.width, inter_size.height, out_format,
233 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
236 if (!scale_context) {
237 throw runtime_error (N_("Could not allocate SwsContext"));
240 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
241 EnumIndexedVector<int, dcp::YUVToRGB> lut;
242 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
243 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
244 lut[dcp::YUVToRGB::REC2020] = SWS_CS_BT2020;
246 /* The 3rd parameter here is:
247 0 -> source range MPEG (i.e. "video", 16-235)
248 1 -> source range JPEG (i.e. "full", 0-255)
250 0 -> destination range MPEG (i.e. "video", 16-235)
251 1 -> destination range JPEG (i.e. "full", 0-255)
253 But remember: sws_setColorspaceDetails ignores these
254 parameters unless the both source and destination images
255 are isYUV or isGray. (If either is not, it uses video range).
257 sws_setColorspaceDetails (
259 sws_getCoefficients(lut[yuv_to_rgb]), video_range == VideoRange::VIDEO ? 0 : 1,
260 sws_getCoefficients(lut[yuv_to_rgb]), out_video_range == VideoRange::VIDEO ? 0 : 1,
264 static int64_t uniform_color = -1;
265 if (uniform_color == -1) {
266 // auto error = av_opt_get_int(scale_context, "uniform_color", AV_OPT_SEARCH_CHILDREN, &uniform_color);
267 auto option = av_opt_find2(scale_context, "uniform_color", "alphablend", 0, AV_OPT_SEARCH_CHILDREN, nullptr);
268 DCPOMATIC_ASSERT(option->type == AV_OPT_TYPE_CONST);
269 uniform_color = option->default_val.i64;
270 std::cout << "uniform_color=" << uniform_color << "\n";
273 std::cout << "set it: " << av_opt_set_int(scale_context, "alphablend", uniform_color, AV_OPT_SEARCH_CHILDREN) << "\n";
275 /* Prepare input data pointers with crop */
276 uint8_t* scale_in_data[planes()];
277 for (int c = 0; c < planes(); ++c) {
278 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
279 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
282 auto out_desc = av_pix_fmt_desc_get (out_format);
284 throw PixelFormatError ("crop_scale_window()", out_format);
287 /* Corner of the image within out_size */
288 Position<int> const corner (
289 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
290 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
293 uint8_t* scale_out_data[out->planes()];
294 for (int c = 0; c < out->planes(); ++c) {
295 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
296 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
301 scale_in_data, stride(),
302 0, cropped_size.height,
303 scale_out_data, out->stride()
306 sws_freeContext (scale_context);
308 /* There are some cases where there will be unwanted image data left in the image at this point:
310 * 1. When we are cropping without any scaling or pixel format conversion.
311 * 2. When we are scaling to certain sizes and placing the result into a larger
314 * Clear out the sides of the image to take care of those cases.
316 auto const pad = (out_size.width - inter_size.width) / 2;
317 out->make_part_black(0, pad);
318 out->make_part_black(corner.x + inter_size.width, pad);
321 video_range == VideoRange::VIDEO &&
322 out_video_range == VideoRange::FULL &&
323 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
325 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
326 out->video_range_to_full_range ();
334 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
336 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
340 /** @param out_size Size to scale to.
341 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
342 * @param out_format Output pixel format.
343 * @param out_alignment Output alignment.
344 * @param fast Try to be fast at the possible expense of quality; at present this means using
345 * fast bilinear rather than bicubic scaling.
348 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
350 /* Empirical testing suggests that sws_scale() will crash if
351 the input image alignment is not PADDED.
353 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
355 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
356 auto scale_context = sws_getContext (
357 size().width, size().height, pixel_format(),
358 out_size.width, out_size.height, out_format,
359 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
362 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
363 EnumIndexedVector<int, dcp::YUVToRGB> lut;
364 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
365 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
366 lut[dcp::YUVToRGB::REC2020] = SWS_CS_BT2020;
368 /* The 3rd parameter here is:
369 0 -> source range MPEG (i.e. "video", 16-235)
370 1 -> source range JPEG (i.e. "full", 0-255)
372 0 -> destination range MPEG (i.e. "video", 16-235)
373 1 -> destination range JPEG (i.e. "full", 0-255)
375 But remember: sws_setColorspaceDetails ignores these
376 parameters unless the corresponding image isYUV or isGray.
377 (If it's neither, it uses video range).
379 sws_setColorspaceDetails (
381 sws_getCoefficients(lut[yuv_to_rgb]), 0,
382 sws_getCoefficients(lut[yuv_to_rgb]), 0,
390 scaled->data(), scaled->stride()
393 sws_freeContext (scale_context);
399 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
401 Image::yuv_16_black (uint16_t v, bool alpha)
403 memset (data()[0], 0, sample_size(0).height * stride()[0]);
404 for (int i = 1; i < 3; ++i) {
405 auto p = reinterpret_cast<int16_t*> (data()[i]);
406 int const lines = sample_size(i).height;
407 for (int y = 0; y < lines; ++y) {
408 /* We divide by 2 here because we are writing 2 bytes at a time */
409 for (int x = 0; x < line_size()[i] / 2; ++x) {
412 p += stride()[i] / 2;
417 memset (data()[3], 0, sample_size(3).height * stride()[3]);
423 Image::swap_16 (uint16_t v)
425 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
430 Image::make_part_black (int const start, int const width)
432 auto y_part = [&]() {
433 int const bpp = bytes_per_pixel(0);
434 int const h = sample_size(0).height;
435 int const s = stride()[0];
437 for (int y = 0; y < h; ++y) {
438 memset (p + start * bpp, 0, width * bpp);
443 switch (_pixel_format) {
444 case AV_PIX_FMT_RGB24:
445 case AV_PIX_FMT_ARGB:
446 case AV_PIX_FMT_RGBA:
447 case AV_PIX_FMT_ABGR:
448 case AV_PIX_FMT_BGRA:
449 case AV_PIX_FMT_RGB555LE:
450 case AV_PIX_FMT_RGB48LE:
451 case AV_PIX_FMT_RGB48BE:
452 case AV_PIX_FMT_XYZ12LE:
454 int const h = sample_size(0).height;
455 int const bpp = bytes_per_pixel(0);
456 int const s = stride()[0];
457 uint8_t* p = data()[0];
458 for (int y = 0; y < h; y++) {
459 memset (p + start * bpp, 0, width * bpp);
464 case AV_PIX_FMT_YUV420P:
467 for (int i = 1; i < 3; ++i) {
469 int const h = sample_size(i).height;
470 for (int y = 0; y < h; ++y) {
471 for (int x = start / 2; x < (start + width) / 2; ++x) {
479 case AV_PIX_FMT_YUV422P10LE:
482 for (int i = 1; i < 3; ++i) {
483 auto p = reinterpret_cast<int16_t*>(data()[i]);
484 int const h = sample_size(i).height;
485 for (int y = 0; y < h; ++y) {
486 for (int x = start / 2; x < (start + width) / 2; ++x) {
489 p += stride()[i] / 2;
494 case AV_PIX_FMT_YUV444P10LE:
497 for (int i = 1; i < 3; ++i) {
498 auto p = reinterpret_cast<int16_t*>(data()[i]);
499 int const h = sample_size(i).height;
500 for (int y = 0; y < h; ++y) {
501 for (int x = start; x < (start + width); ++x) {
504 p += stride()[i] / 2;
510 throw PixelFormatError ("make_part_black()", _pixel_format);
518 switch (_pixel_format) {
519 case AV_PIX_FMT_YUV420P:
520 case AV_PIX_FMT_YUV422P:
521 case AV_PIX_FMT_YUV444P:
522 case AV_PIX_FMT_YUV411P:
523 memset (data()[0], 0, sample_size(0).height * stride()[0]);
524 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
525 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
528 case AV_PIX_FMT_YUVJ420P:
529 case AV_PIX_FMT_YUVJ422P:
530 case AV_PIX_FMT_YUVJ444P:
531 memset (data()[0], 0, sample_size(0).height * stride()[0]);
532 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
533 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
536 case AV_PIX_FMT_YUV422P9LE:
537 case AV_PIX_FMT_YUV444P9LE:
538 yuv_16_black (nine_bit_uv, false);
541 case AV_PIX_FMT_YUV422P9BE:
542 case AV_PIX_FMT_YUV444P9BE:
543 yuv_16_black (swap_16 (nine_bit_uv), false);
546 case AV_PIX_FMT_YUV422P10LE:
547 case AV_PIX_FMT_YUV444P10LE:
548 yuv_16_black (ten_bit_uv, false);
551 case AV_PIX_FMT_YUV422P16LE:
552 case AV_PIX_FMT_YUV444P16LE:
553 yuv_16_black (sixteen_bit_uv, false);
556 case AV_PIX_FMT_YUV444P10BE:
557 case AV_PIX_FMT_YUV422P10BE:
558 yuv_16_black (swap_16 (ten_bit_uv), false);
561 case AV_PIX_FMT_YUVA420P9BE:
562 case AV_PIX_FMT_YUVA422P9BE:
563 case AV_PIX_FMT_YUVA444P9BE:
564 yuv_16_black (swap_16 (nine_bit_uv), true);
567 case AV_PIX_FMT_YUVA420P9LE:
568 case AV_PIX_FMT_YUVA422P9LE:
569 case AV_PIX_FMT_YUVA444P9LE:
570 yuv_16_black (nine_bit_uv, true);
573 case AV_PIX_FMT_YUVA420P10BE:
574 case AV_PIX_FMT_YUVA422P10BE:
575 case AV_PIX_FMT_YUVA444P10BE:
576 yuv_16_black (swap_16 (ten_bit_uv), true);
579 case AV_PIX_FMT_YUVA420P10LE:
580 case AV_PIX_FMT_YUVA422P10LE:
581 case AV_PIX_FMT_YUVA444P10LE:
582 yuv_16_black (ten_bit_uv, true);
585 case AV_PIX_FMT_YUVA420P16BE:
586 case AV_PIX_FMT_YUVA422P16BE:
587 case AV_PIX_FMT_YUVA444P16BE:
588 yuv_16_black (swap_16 (sixteen_bit_uv), true);
591 case AV_PIX_FMT_YUVA420P16LE:
592 case AV_PIX_FMT_YUVA422P16LE:
593 case AV_PIX_FMT_YUVA444P16LE:
594 yuv_16_black (sixteen_bit_uv, true);
597 case AV_PIX_FMT_RGB24:
598 case AV_PIX_FMT_ARGB:
599 case AV_PIX_FMT_RGBA:
600 case AV_PIX_FMT_ABGR:
601 case AV_PIX_FMT_BGRA:
602 case AV_PIX_FMT_RGB555LE:
603 case AV_PIX_FMT_RGB48LE:
604 case AV_PIX_FMT_RGB48BE:
605 case AV_PIX_FMT_XYZ12LE:
606 memset (data()[0], 0, sample_size(0).height * stride()[0]);
609 case AV_PIX_FMT_UYVY422:
611 int const Y = sample_size(0).height;
612 int const X = line_size()[0];
613 uint8_t* p = data()[0];
614 for (int y = 0; y < Y; ++y) {
615 for (int x = 0; x < X / 4; ++x) {
616 *p++ = eight_bit_uv; // Cb
618 *p++ = eight_bit_uv; // Cr
626 throw PixelFormatError ("make_black()", _pixel_format);
632 Image::make_transparent ()
634 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
635 throw PixelFormatError ("make_transparent()", _pixel_format);
638 memset (data()[0], 0, sample_size(0).height * stride()[0]);
643 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
645 /* We're blending RGBA or BGRA images */
646 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
647 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
648 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
650 int const other_bpp = 4;
652 int start_tx = position.x;
656 start_ox = -start_tx;
660 int start_ty = position.y;
664 start_oy = -start_ty;
668 switch (_pixel_format) {
669 case AV_PIX_FMT_RGB24:
671 /* Going onto RGB24. First byte is red, second green, third blue */
672 int const this_bpp = 3;
673 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
674 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
675 uint8_t* op = other->data()[0] + oy * other->stride()[0];
676 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
677 float const alpha = float (op[3]) / 255;
678 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
679 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
680 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
688 case AV_PIX_FMT_BGRA:
690 int const this_bpp = 4;
691 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
692 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
693 uint8_t* op = other->data()[0] + oy * other->stride()[0];
694 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
695 float const alpha = float (op[3]) / 255;
696 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
697 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
698 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
699 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
707 case AV_PIX_FMT_RGBA:
709 int const this_bpp = 4;
710 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
711 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
712 uint8_t* op = other->data()[0] + oy * other->stride()[0];
713 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
714 float const alpha = float (op[3]) / 255;
715 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
716 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
717 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
718 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
726 case AV_PIX_FMT_RGB48LE:
728 int const this_bpp = 6;
729 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
730 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
731 uint8_t* op = other->data()[0] + oy * other->stride()[0];
732 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
733 float const alpha = float (op[3]) / 255;
734 /* Blend high bytes */
735 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
736 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
737 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
745 case AV_PIX_FMT_XYZ12LE:
747 auto conv = dcp::ColourConversion::srgb_to_xyz();
748 double fast_matrix[9];
749 dcp::combined_rgb_to_xyz (conv, fast_matrix);
750 auto lut_in = conv.in()->lut(0, 1, 8, false);
751 auto lut_out = conv.out()->lut(0, 1, 16, true);
752 int const this_bpp = 6;
753 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
754 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
755 uint8_t* op = other->data()[0] + oy * other->stride()[0];
756 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
757 float const alpha = float (op[3]) / 255;
759 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
760 double const r = lut_in[op[red]];
761 double const g = lut_in[op[1]];
762 double const b = lut_in[op[blue]];
764 /* RGB to XYZ, including Bradford transform and DCI companding */
765 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
766 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
767 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
769 /* Out gamma LUT and blend */
770 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
771 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
772 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
780 case AV_PIX_FMT_YUV420P:
782 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
783 dcp::Size const ts = size();
784 dcp::Size const os = yuv->size();
785 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
786 int const hty = ty / 2;
787 int const hoy = oy / 2;
788 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
789 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
790 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
791 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
792 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
793 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
794 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
795 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
796 float const a = float(alpha[3]) / 255;
797 *tY = *oY * a + *tY * (1 - a);
798 *tU = *oU * a + *tU * (1 - a);
799 *tV = *oV * a + *tV * (1 - a);
815 case AV_PIX_FMT_YUV420P10:
817 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
818 dcp::Size const ts = size();
819 dcp::Size const os = yuv->size();
820 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
821 int const hty = ty / 2;
822 int const hoy = oy / 2;
823 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
824 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
825 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
826 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
827 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
828 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
829 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
830 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
831 float const a = float(alpha[3]) / 255;
832 *tY = *oY * a + *tY * (1 - a);
833 *tU = *oU * a + *tU * (1 - a);
834 *tV = *oV * a + *tV * (1 - a);
850 case AV_PIX_FMT_YUV422P10LE:
852 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
853 dcp::Size const ts = size();
854 dcp::Size const os = yuv->size();
855 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
856 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
857 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
858 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
859 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
860 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
861 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
862 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
863 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
864 float const a = float(alpha[3]) / 255;
865 *tY = *oY * a + *tY * (1 - a);
866 *tU = *oU * a + *tU * (1 - a);
867 *tV = *oV * a + *tV * (1 - a);
884 throw PixelFormatError ("alpha_blend()", _pixel_format);
890 Image::copy (shared_ptr<const Image> other, Position<int> position)
892 /* Only implemented for RGB24 onto RGB24 so far */
893 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
894 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
896 int const N = min (position.x + other->size().width, size().width) - position.x;
897 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
898 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
899 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
900 memcpy (tp, op, N * 3);
906 Image::read_from_socket (shared_ptr<Socket> socket)
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->read (p, line_size()[i]);
920 Image::write_to_socket (shared_ptr<Socket> socket) const
922 for (int i = 0; i < planes(); ++i) {
923 uint8_t* p = data()[i];
924 int const lines = sample_size(i).height;
925 for (int y = 0; y < lines; ++y) {
926 socket->write (p, line_size()[i]);
934 Image::bytes_per_pixel (int c) const
936 auto d = av_pix_fmt_desc_get(_pixel_format);
938 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
945 float bpp[4] = { 0, 0, 0, 0 };
947 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
948 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
949 if (d->nb_components > 1) {
950 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
952 if (d->nb_components > 2) {
953 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
955 if (d->nb_components > 3) {
956 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
959 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
960 if (d->nb_components > 1) {
961 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
963 if (d->nb_components > 2) {
964 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
966 if (d->nb_components > 3) {
967 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
971 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
972 /* Not planar; sum them up */
973 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
980 /** Construct a Image of a given size and format, allocating memory
983 * @param p Pixel format.
984 * @param s Size in pixels.
985 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
987 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
990 , _alignment (alignment)
999 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
1000 _data[0] = _data[1] = _data[2] = _data[3] = 0;
1002 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
1003 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
1005 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
1006 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
1008 auto stride_round_up = [](int stride, int t) {
1009 int const a = stride + (t - 1);
1013 for (int i = 0; i < planes(); ++i) {
1014 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
1015 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
1017 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
1018 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
1019 Hence on the last pixel of the last line it reads over the end of
1020 the actual data by 1 byte. If the width of an image is a multiple
1021 of the stride alignment there will be no padding at the end of image lines.
1022 OS X crashes on this illegal read, though other operating systems don't
1023 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
1024 for that instruction to read safely.
1026 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
1027 over-reads by more then _avx. I can't follow the code to work out how much,
1028 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1029 testing suggests that it works.
1031 In addition to these concerns, we may read/write as much as a whole extra line
1032 at the end of each plane in cases where we are messing with offsets in order to
1033 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1035 As an example: we may write to images starting at an offset so we get some padding.
1036 Hence we want to write in the following pattern:
1038 block start write start line end
1039 |..(padding)..|<------line-size------------->|..(padding)..|
1040 |..(padding)..|<------line-size------------->|..(padding)..|
1041 |..(padding)..|<------line-size------------->|..(padding)..|
1043 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1044 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1045 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1046 specified *stride*. This does not matter until we get to the last line:
1048 block start write start line end
1049 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1050 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1051 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1054 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1055 #if HAVE_VALGRIND_MEMCHECK_H
1056 /* The data between the end of the line size and the stride is undefined but processed by
1057 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1059 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1065 Image::Image (Image const & other)
1066 : std::enable_shared_from_this<Image>(other)
1067 , _size (other._size)
1068 , _pixel_format (other._pixel_format)
1069 , _alignment (other._alignment)
1073 for (int i = 0; i < planes(); ++i) {
1074 uint8_t* p = _data[i];
1075 uint8_t* q = other._data[i];
1076 int const lines = sample_size(i).height;
1077 for (int j = 0; j < lines; ++j) {
1078 memcpy (p, q, _line_size[i]);
1080 q += other.stride()[i];
1086 Image::Image (AVFrame const * frame, Alignment alignment)
1087 : _size (frame->width, frame->height)
1088 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1089 , _alignment (alignment)
1091 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1095 for (int i = 0; i < planes(); ++i) {
1096 uint8_t* p = _data[i];
1097 uint8_t* q = frame->data[i];
1098 int const lines = sample_size(i).height;
1099 for (int j = 0; j < lines; ++j) {
1100 memcpy (p, q, _line_size[i]);
1102 /* AVFrame's linesize is what we call `stride' */
1103 q += frame->linesize[i];
1109 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1110 : _size (other->_size)
1111 , _pixel_format (other->_pixel_format)
1112 , _alignment (alignment)
1116 for (int i = 0; i < planes(); ++i) {
1117 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1118 uint8_t* p = _data[i];
1119 uint8_t* q = other->data()[i];
1120 int const lines = sample_size(i).height;
1121 for (int j = 0; j < lines; ++j) {
1122 memcpy (p, q, line_size()[i]);
1124 q += other->stride()[i];
1131 Image::operator= (Image const & other)
1133 if (this == &other) {
1144 Image::swap (Image & other)
1146 std::swap (_size, other._size);
1147 std::swap (_pixel_format, other._pixel_format);
1149 for (int i = 0; i < 4; ++i) {
1150 std::swap (_data[i], other._data[i]);
1151 std::swap (_line_size[i], other._line_size[i]);
1152 std::swap (_stride[i], other._stride[i]);
1155 std::swap (_alignment, other._alignment);
1161 for (int i = 0; i < planes(); ++i) {
1166 av_free (_line_size);
1172 Image::data () const
1179 Image::line_size () const
1186 Image::stride () const
1193 Image::size () const
1200 Image::alignment () const
1207 merge (list<PositionImage> images, Image::Alignment alignment)
1209 if (images.empty ()) {
1213 if (images.size() == 1) {
1214 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1215 return images.front();
1218 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1219 for (auto const& i: images) {
1220 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1223 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1224 merged->make_transparent ();
1225 for (auto const& i: images) {
1226 merged->alpha_blend (i.image, i.position - all.position());
1229 return PositionImage (merged, all.position ());
1234 operator== (Image const & a, Image const & b)
1236 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1240 for (int c = 0; c < a.planes(); ++c) {
1241 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]) {
1245 uint8_t* p = a.data()[c];
1246 uint8_t* q = b.data()[c];
1247 int const lines = a.sample_size(c).height;
1248 for (int y = 0; y < lines; ++y) {
1249 if (memcmp (p, q, a.line_size()[c]) != 0) {
1263 * @param f Amount to fade by; 0 is black, 1 is no fade.
1266 Image::fade (float f)
1268 /* U/V black value for 8-bit colour */
1269 static int const eight_bit_uv = (1 << 7) - 1;
1270 /* U/V black value for 10-bit colour */
1271 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1273 switch (_pixel_format) {
1274 case AV_PIX_FMT_YUV420P:
1277 uint8_t* p = data()[0];
1278 int const lines = sample_size(0).height;
1279 for (int y = 0; y < lines; ++y) {
1281 for (int x = 0; x < line_size()[0]; ++x) {
1282 *q = int(float(*q) * f);
1289 for (int c = 1; c < 3; ++c) {
1290 uint8_t* p = data()[c];
1291 int const lines = sample_size(c).height;
1292 for (int y = 0; y < lines; ++y) {
1294 for (int x = 0; x < line_size()[c]; ++x) {
1295 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1305 case AV_PIX_FMT_RGB24:
1308 uint8_t* p = data()[0];
1309 int const lines = sample_size(0).height;
1310 for (int y = 0; y < lines; ++y) {
1312 for (int x = 0; x < line_size()[0]; ++x) {
1313 *q = int (float (*q) * f);
1321 case AV_PIX_FMT_XYZ12LE:
1322 case AV_PIX_FMT_RGB48LE:
1323 /* 16-bit little-endian */
1324 for (int c = 0; c < 3; ++c) {
1325 int const stride_pixels = stride()[c] / 2;
1326 int const line_size_pixels = line_size()[c] / 2;
1327 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1328 int const lines = sample_size(c).height;
1329 for (int y = 0; y < lines; ++y) {
1331 for (int x = 0; x < line_size_pixels; ++x) {
1332 *q = int (float (*q) * f);
1340 case AV_PIX_FMT_YUV422P10LE:
1344 int const stride_pixels = stride()[0] / 2;
1345 int const line_size_pixels = line_size()[0] / 2;
1346 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1347 int const lines = sample_size(0).height;
1348 for (int y = 0; y < lines; ++y) {
1350 for (int x = 0; x < line_size_pixels; ++x) {
1351 *q = int(float(*q) * f);
1359 for (int c = 1; c < 3; ++c) {
1360 int const stride_pixels = stride()[c] / 2;
1361 int const line_size_pixels = line_size()[c] / 2;
1362 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1363 int const lines = sample_size(c).height;
1364 for (int y = 0; y < lines; ++y) {
1366 for (int x = 0; x < line_size_pixels; ++x) {
1367 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1378 throw PixelFormatError ("fade()", _pixel_format);
1383 shared_ptr<const Image>
1384 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1386 if (image->alignment() == alignment) {
1390 return make_shared<Image>(image, alignment);
1395 Image::memory_used () const
1398 for (int i = 0; i < planes(); ++i) {
1399 m += _stride[i] * sample_size(i).height;
1406 Image::video_range_to_full_range ()
1408 switch (_pixel_format) {
1409 case AV_PIX_FMT_RGB24:
1411 float const factor = 256.0 / 219.0;
1412 uint8_t* p = data()[0];
1413 int const lines = sample_size(0).height;
1414 for (int y = 0; y < lines; ++y) {
1416 for (int x = 0; x < line_size()[0]; ++x) {
1417 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1424 case AV_PIX_FMT_RGB48LE:
1426 float const factor = 65536.0 / 56064.0;
1427 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1428 int const lines = sample_size(0).height;
1429 for (int y = 0; y < lines; ++y) {
1431 int const line_size_pixels = line_size()[0] / 2;
1432 for (int x = 0; x < line_size_pixels; ++x) {
1433 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1436 p += stride()[0] / 2;
1440 case AV_PIX_FMT_GBRP12LE:
1442 float const factor = 4096.0 / 3504.0;
1443 for (int c = 0; c < 3; ++c) {
1444 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1445 int const lines = sample_size(c).height;
1446 for (int y = 0; y < lines; ++y) {
1448 int const line_size_pixels = line_size()[c] / 2;
1449 for (int x = 0; x < line_size_pixels; ++x) {
1450 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1458 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);