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_socket.h"
29 #include "exceptions.h"
34 #include <dcp/rgb_xyz.h>
35 #include <dcp/transfer_function.h>
37 #include <libavutil/frame.h>
38 #include <libavutil/pixdesc.h>
39 #include <libavutil/pixfmt.h>
40 #include <libswscale/swscale.h>
43 #if HAVE_VALGRIND_MEMCHECK_H
44 #include <valgrind/memcheck.h>
55 using std::make_shared;
58 using std::runtime_error;
59 using std::shared_ptr;
64 /** The memory alignment, in bytes, used for each row of an image if aligment is requested */
67 /* U/V black value for 8-bit colour */
68 static uint8_t const eight_bit_uv = (1 << 7) - 1;
69 /* U/V black value for 9-bit colour */
70 static uint16_t const nine_bit_uv = (1 << 8) - 1;
71 /* U/V black value for 10-bit colour */
72 static uint16_t const ten_bit_uv = (1 << 9) - 1;
73 /* U/V black value for 16-bit colour */
74 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
78 Image::vertical_factor (int n) const
84 auto d = av_pix_fmt_desc_get(_pixel_format);
86 throw PixelFormatError ("line_factor()", _pixel_format);
89 return lrintf(powf(2.0f, d->log2_chroma_h));
93 Image::horizontal_factor (int n) const
99 auto d = av_pix_fmt_desc_get(_pixel_format);
101 throw PixelFormatError ("sample_size()", _pixel_format);
104 return lrintf(powf(2.0f, d->log2_chroma_w));
107 /** @param n Component index.
108 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
111 Image::sample_size (int n) const
114 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
115 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
119 /** @return Number of planes */
121 Image::planes () const
123 auto d = av_pix_fmt_desc_get(_pixel_format);
125 throw PixelFormatError ("planes()", _pixel_format);
128 if (_pixel_format == AV_PIX_FMT_PAL8) {
132 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
136 return d->nb_components;
142 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
144 return p & ~ ((1 << desc->log2_chroma_w) - 1);
150 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
152 return p & ~ ((1 << desc->log2_chroma_h) - 1);
156 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
157 * @param crop Amount to crop by.
158 * @param inter_size Size to scale the cropped image to.
159 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
160 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
161 * @param video_range Video range of the image.
162 * @param out_format Output pixel format.
163 * @param out_aligned true to make the output image aligned.
164 * @param out_video_range Video range to use for the output image.
165 * @param fast Try to be fast at the possible expense of quality; at present this means using
166 * fast bilinear rather than bicubic scaling.
169 Image::crop_scale_window (
171 dcp::Size inter_size,
173 dcp::YUVToRGB yuv_to_rgb,
174 VideoRange video_range,
175 AVPixelFormat out_format,
176 VideoRange out_video_range,
181 /* Empirical testing suggests that sws_scale() will crash if
182 the input image is not aligned.
184 DCPOMATIC_ASSERT (aligned ());
186 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
187 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
189 auto out = make_shared<Image>(out_format, out_size, out_aligned);
192 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
194 throw PixelFormatError ("crop_scale_window()", _pixel_format);
197 /* Round down so that we crop only the number of pixels that is straightforward
198 * considering any subsampling.
201 round_width_for_subsampling(crop.left, in_desc),
202 round_width_for_subsampling(crop.right, in_desc),
203 round_height_for_subsampling(crop.top, in_desc),
204 round_height_for_subsampling(crop.bottom, in_desc)
207 /* Also check that we aren't cropping more image than there actually is */
208 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
209 corrected_crop.left = 0;
210 corrected_crop.right = size().width - 4;
213 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
214 corrected_crop.top = 0;
215 corrected_crop.bottom = size().height - 4;
218 /* Size of the image after any crop */
219 auto const cropped_size = corrected_crop.apply (size());
221 /* Scale context for a scale from cropped_size to inter_size */
222 auto scale_context = sws_getContext (
223 cropped_size.width, cropped_size.height, pixel_format(),
224 inter_size.width, inter_size.height, out_format,
225 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
228 if (!scale_context) {
229 throw runtime_error (N_("Could not allocate SwsContext"));
232 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
233 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
238 /* The 3rd parameter here is:
239 0 -> source range MPEG (i.e. "video", 16-235)
240 1 -> source range JPEG (i.e. "full", 0-255)
242 0 -> destination range MPEG (i.e. "video", 16-235)
243 1 -> destination range JPEG (i.e. "full", 0-255)
245 But remember: sws_setColorspaceDetails ignores these
246 parameters unless the both source and destination images
247 are isYUV or isGray. (If either is not, it uses video range).
249 sws_setColorspaceDetails (
251 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
252 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
256 /* Prepare input data pointers with crop */
257 uint8_t* scale_in_data[planes()];
258 for (int c = 0; c < planes(); ++c) {
259 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
260 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
263 auto out_desc = av_pix_fmt_desc_get (out_format);
265 throw PixelFormatError ("crop_scale_window()", out_format);
268 /* Corner of the image within out_size */
269 Position<int> const corner (
270 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
271 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
274 uint8_t* scale_out_data[out->planes()];
275 for (int c = 0; c < out->planes(); ++c) {
276 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
277 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
282 scale_in_data, stride(),
283 0, cropped_size.height,
284 scale_out_data, out->stride()
287 sws_freeContext (scale_context);
289 if (corrected_crop != Crop() && cropped_size == inter_size) {
290 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
291 data behind in our image. Clear it out. It may get to the point where we should just stop
292 trying to be clever with cropping.
294 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
301 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
303 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
306 /** @param out_size Size to scale to.
307 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
308 * @param out_format Output pixel format.
309 * @param out_aligned true to make an aligned output image.
310 * @param fast Try to be fast at the possible expense of quality; at present this means using
311 * fast bilinear rather than bicubic scaling.
314 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
316 /* Empirical testing suggests that sws_scale() will crash if
317 the input image is not aligned.
319 DCPOMATIC_ASSERT (aligned ());
321 auto scaled = make_shared<Image>(out_format, out_size, out_aligned);
322 auto scale_context = sws_getContext (
323 size().width, size().height, pixel_format(),
324 out_size.width, out_size.height, out_format,
325 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
328 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
329 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
334 /* The 3rd parameter here is:
335 0 -> source range MPEG (i.e. "video", 16-235)
336 1 -> source range JPEG (i.e. "full", 0-255)
338 0 -> destination range MPEG (i.e. "video", 16-235)
339 1 -> destination range JPEG (i.e. "full", 0-255)
341 But remember: sws_setColorspaceDetails ignores these
342 parameters unless the corresponding image isYUV or isGray.
343 (If it's neither, it uses video range).
345 sws_setColorspaceDetails (
347 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
348 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
356 scaled->data(), scaled->stride()
359 sws_freeContext (scale_context);
364 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
366 Image::yuv_16_black (uint16_t v, bool alpha)
368 memset (data()[0], 0, sample_size(0).height * stride()[0]);
369 for (int i = 1; i < 3; ++i) {
370 auto p = reinterpret_cast<int16_t*> (data()[i]);
371 int const lines = sample_size(i).height;
372 for (int y = 0; y < lines; ++y) {
373 /* We divide by 2 here because we are writing 2 bytes at a time */
374 for (int x = 0; x < line_size()[i] / 2; ++x) {
377 p += stride()[i] / 2;
382 memset (data()[3], 0, sample_size(3).height * stride()[3]);
387 Image::swap_16 (uint16_t v)
389 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
393 Image::make_part_black (int const start, int const width)
395 auto y_part = [&]() {
396 int const bpp = bytes_per_pixel(0);
397 int const h = sample_size(0).height;
398 int const s = stride()[0];
400 for (int y = 0; y < h; ++y) {
401 memset (p + start * bpp, 0, width * bpp);
406 switch (_pixel_format) {
407 case AV_PIX_FMT_RGB24:
408 case AV_PIX_FMT_ARGB:
409 case AV_PIX_FMT_RGBA:
410 case AV_PIX_FMT_ABGR:
411 case AV_PIX_FMT_BGRA:
412 case AV_PIX_FMT_RGB555LE:
413 case AV_PIX_FMT_RGB48LE:
414 case AV_PIX_FMT_RGB48BE:
415 case AV_PIX_FMT_XYZ12LE:
417 int const h = sample_size(0).height;
418 int const bpp = bytes_per_pixel(0);
419 int const s = stride()[0];
420 uint8_t* p = data()[0];
421 for (int y = 0; y < h; y++) {
422 memset (p + start * bpp, 0, width * bpp);
427 case AV_PIX_FMT_YUV420P:
430 for (int i = 1; i < 3; ++i) {
432 int const h = sample_size(i).height;
433 for (int y = 0; y < h; ++y) {
434 for (int x = start / 2; x < (start + width) / 2; ++x) {
442 case AV_PIX_FMT_YUV422P10LE:
445 for (int i = 1; i < 3; ++i) {
446 auto p = reinterpret_cast<int16_t*>(data()[i]);
447 int const h = sample_size(i).height;
448 for (int y = 0; y < h; ++y) {
449 for (int x = start / 2; x < (start + width) / 2; ++x) {
452 p += stride()[i] / 2;
458 throw PixelFormatError ("make_part_black()", _pixel_format);
465 switch (_pixel_format) {
466 case AV_PIX_FMT_YUV420P:
467 case AV_PIX_FMT_YUV422P:
468 case AV_PIX_FMT_YUV444P:
469 case AV_PIX_FMT_YUV411P:
470 memset (data()[0], 0, sample_size(0).height * stride()[0]);
471 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
472 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
475 case AV_PIX_FMT_YUVJ420P:
476 case AV_PIX_FMT_YUVJ422P:
477 case AV_PIX_FMT_YUVJ444P:
478 memset (data()[0], 0, sample_size(0).height * stride()[0]);
479 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
480 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
483 case AV_PIX_FMT_YUV422P9LE:
484 case AV_PIX_FMT_YUV444P9LE:
485 yuv_16_black (nine_bit_uv, false);
488 case AV_PIX_FMT_YUV422P9BE:
489 case AV_PIX_FMT_YUV444P9BE:
490 yuv_16_black (swap_16 (nine_bit_uv), false);
493 case AV_PIX_FMT_YUV422P10LE:
494 case AV_PIX_FMT_YUV444P10LE:
495 yuv_16_black (ten_bit_uv, false);
498 case AV_PIX_FMT_YUV422P16LE:
499 case AV_PIX_FMT_YUV444P16LE:
500 yuv_16_black (sixteen_bit_uv, false);
503 case AV_PIX_FMT_YUV444P10BE:
504 case AV_PIX_FMT_YUV422P10BE:
505 yuv_16_black (swap_16 (ten_bit_uv), false);
508 case AV_PIX_FMT_YUVA420P9BE:
509 case AV_PIX_FMT_YUVA422P9BE:
510 case AV_PIX_FMT_YUVA444P9BE:
511 yuv_16_black (swap_16 (nine_bit_uv), true);
514 case AV_PIX_FMT_YUVA420P9LE:
515 case AV_PIX_FMT_YUVA422P9LE:
516 case AV_PIX_FMT_YUVA444P9LE:
517 yuv_16_black (nine_bit_uv, true);
520 case AV_PIX_FMT_YUVA420P10BE:
521 case AV_PIX_FMT_YUVA422P10BE:
522 case AV_PIX_FMT_YUVA444P10BE:
523 yuv_16_black (swap_16 (ten_bit_uv), true);
526 case AV_PIX_FMT_YUVA420P10LE:
527 case AV_PIX_FMT_YUVA422P10LE:
528 case AV_PIX_FMT_YUVA444P10LE:
529 yuv_16_black (ten_bit_uv, true);
532 case AV_PIX_FMT_YUVA420P16BE:
533 case AV_PIX_FMT_YUVA422P16BE:
534 case AV_PIX_FMT_YUVA444P16BE:
535 yuv_16_black (swap_16 (sixteen_bit_uv), true);
538 case AV_PIX_FMT_YUVA420P16LE:
539 case AV_PIX_FMT_YUVA422P16LE:
540 case AV_PIX_FMT_YUVA444P16LE:
541 yuv_16_black (sixteen_bit_uv, true);
544 case AV_PIX_FMT_RGB24:
545 case AV_PIX_FMT_ARGB:
546 case AV_PIX_FMT_RGBA:
547 case AV_PIX_FMT_ABGR:
548 case AV_PIX_FMT_BGRA:
549 case AV_PIX_FMT_RGB555LE:
550 case AV_PIX_FMT_RGB48LE:
551 case AV_PIX_FMT_RGB48BE:
552 case AV_PIX_FMT_XYZ12LE:
553 memset (data()[0], 0, sample_size(0).height * stride()[0]);
556 case AV_PIX_FMT_UYVY422:
558 int const Y = sample_size(0).height;
559 int const X = line_size()[0];
560 uint8_t* p = data()[0];
561 for (int y = 0; y < Y; ++y) {
562 for (int x = 0; x < X / 4; ++x) {
563 *p++ = eight_bit_uv; // Cb
565 *p++ = eight_bit_uv; // Cr
573 throw PixelFormatError ("make_black()", _pixel_format);
578 Image::make_transparent ()
580 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
581 throw PixelFormatError ("make_transparent()", _pixel_format);
584 memset (data()[0], 0, sample_size(0).height * stride()[0]);
588 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
590 /* We're blending RGBA or BGRA images */
591 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
592 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
593 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
595 int const other_bpp = 4;
597 int start_tx = position.x;
601 start_ox = -start_tx;
605 int start_ty = position.y;
609 start_oy = -start_ty;
613 switch (_pixel_format) {
614 case AV_PIX_FMT_RGB24:
616 /* Going onto RGB24. First byte is red, second green, third blue */
617 int const this_bpp = 3;
618 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
619 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
620 uint8_t* op = other->data()[0] + oy * other->stride()[0];
621 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
622 float const alpha = float (op[3]) / 255;
623 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
624 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
625 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
633 case AV_PIX_FMT_BGRA:
635 int const this_bpp = 4;
636 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
637 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
638 uint8_t* op = other->data()[0] + oy * other->stride()[0];
639 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
640 float const alpha = float (op[3]) / 255;
641 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
642 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
643 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
644 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
652 case AV_PIX_FMT_RGBA:
654 int const this_bpp = 4;
655 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
656 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
657 uint8_t* op = other->data()[0] + oy * other->stride()[0];
658 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
659 float const alpha = float (op[3]) / 255;
660 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
661 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
662 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
663 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
671 case AV_PIX_FMT_RGB48LE:
673 int const this_bpp = 6;
674 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
675 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
676 uint8_t* op = other->data()[0] + oy * other->stride()[0];
677 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
678 float const alpha = float (op[3]) / 255;
679 /* Blend high bytes */
680 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
681 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
682 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
690 case AV_PIX_FMT_XYZ12LE:
692 auto conv = dcp::ColourConversion::srgb_to_xyz();
693 double fast_matrix[9];
694 dcp::combined_rgb_to_xyz (conv, fast_matrix);
695 double const * lut_in = conv.in()->lut (8, false);
696 double const * lut_out = conv.out()->lut (16, true);
697 int const this_bpp = 6;
698 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
699 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
700 uint8_t* op = other->data()[0] + oy * other->stride()[0];
701 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
702 float const alpha = float (op[3]) / 255;
704 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
705 double const r = lut_in[op[red]];
706 double const g = lut_in[op[1]];
707 double const b = lut_in[op[blue]];
709 /* RGB to XYZ, including Bradford transform and DCI companding */
710 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
711 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
712 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
714 /* Out gamma LUT and blend */
715 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
716 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
717 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
725 case AV_PIX_FMT_YUV420P:
727 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
728 dcp::Size const ts = size();
729 dcp::Size const os = yuv->size();
730 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
731 int const hty = ty / 2;
732 int const hoy = oy / 2;
733 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
734 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
735 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
736 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
737 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
738 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
739 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
740 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
741 float const a = float(alpha[3]) / 255;
742 *tY = *oY * a + *tY * (1 - a);
743 *tU = *oU * a + *tU * (1 - a);
744 *tV = *oV * a + *tV * (1 - a);
760 case AV_PIX_FMT_YUV420P10:
762 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
763 dcp::Size const ts = size();
764 dcp::Size const os = yuv->size();
765 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
766 int const hty = ty / 2;
767 int const hoy = oy / 2;
768 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
769 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
770 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
771 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
772 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
773 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
774 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
775 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
776 float const a = float(alpha[3]) / 255;
777 *tY = *oY * a + *tY * (1 - a);
778 *tU = *oU * a + *tU * (1 - a);
779 *tV = *oV * a + *tV * (1 - a);
795 case AV_PIX_FMT_YUV422P10LE:
797 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
798 dcp::Size const ts = size();
799 dcp::Size const os = yuv->size();
800 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
801 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
802 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
803 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
804 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
805 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
806 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
807 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
808 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
809 float const a = float(alpha[3]) / 255;
810 *tY = *oY * a + *tY * (1 - a);
811 *tU = *oU * a + *tU * (1 - a);
812 *tV = *oV * a + *tV * (1 - a);
829 throw PixelFormatError ("alpha_blend()", _pixel_format);
834 Image::copy (shared_ptr<const Image> other, Position<int> position)
836 /* Only implemented for RGB24 onto RGB24 so far */
837 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
838 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
840 int const N = min (position.x + other->size().width, size().width) - position.x;
841 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
842 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
843 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
844 memcpy (tp, op, N * 3);
849 Image::read_from_socket (shared_ptr<Socket> socket)
851 for (int i = 0; i < planes(); ++i) {
852 uint8_t* p = data()[i];
853 int const lines = sample_size(i).height;
854 for (int y = 0; y < lines; ++y) {
855 socket->read (p, line_size()[i]);
862 Image::write_to_socket (shared_ptr<Socket> socket) const
864 for (int i = 0; i < planes(); ++i) {
865 uint8_t* p = data()[i];
866 int const lines = sample_size(i).height;
867 for (int y = 0; y < lines; ++y) {
868 socket->write (p, line_size()[i]);
875 Image::bytes_per_pixel (int c) const
877 auto d = av_pix_fmt_desc_get(_pixel_format);
879 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
886 float bpp[4] = { 0, 0, 0, 0 };
888 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
889 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
890 if (d->nb_components > 1) {
891 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
893 if (d->nb_components > 2) {
894 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
896 if (d->nb_components > 3) {
897 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
900 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
901 if (d->nb_components > 1) {
902 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
904 if (d->nb_components > 2) {
905 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
907 if (d->nb_components > 3) {
908 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
912 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
913 /* Not planar; sum them up */
914 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
920 /** Construct a Image of a given size and format, allocating memory
923 * @param p Pixel format.
924 * @param s Size in pixels.
925 * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
927 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
938 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
939 _data[0] = _data[1] = _data[2] = _data[3] = 0;
941 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
942 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
944 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
945 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
947 for (int i = 0; i < planes(); ++i) {
948 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
949 _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
951 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
952 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
953 Hence on the last pixel of the last line it reads over the end of
954 the actual data by 1 byte. If the width of an image is a multiple
955 of the stride alignment there will be no padding at the end of image lines.
956 OS X crashes on this illegal read, though other operating systems don't
957 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
958 for that instruction to read safely.
960 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
961 over-reads by more then _avx. I can't follow the code to work out how much,
962 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
963 testing suggests that it works.
965 In addition to these concerns, we may read/write as much as a whole extra line
966 at the end of each plane in cases where we are messing with offsets in order to
967 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
969 As an example: we may write to images starting at an offset so we get some padding.
970 Hence we want to write in the following pattern:
972 block start write start line end
973 |..(padding)..|<------line-size------------->|..(padding)..|
974 |..(padding)..|<------line-size------------->|..(padding)..|
975 |..(padding)..|<------line-size------------->|..(padding)..|
977 where line-size is of the smaller (inter_size) image and the full padded line length is that of
978 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
979 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
980 specified *stride*. This does not matter until we get to the last line:
982 block start write start line end
983 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
984 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
985 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
988 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
989 #if HAVE_VALGRIND_MEMCHECK_H
990 /* The data between the end of the line size and the stride is undefined but processed by
991 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
993 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
998 Image::Image (Image const & other)
999 : std::enable_shared_from_this<Image>(other)
1000 , _size (other._size)
1001 , _pixel_format (other._pixel_format)
1002 , _aligned (other._aligned)
1006 for (int i = 0; i < planes(); ++i) {
1007 uint8_t* p = _data[i];
1008 uint8_t* q = other._data[i];
1009 int const lines = sample_size(i).height;
1010 for (int j = 0; j < lines; ++j) {
1011 memcpy (p, q, _line_size[i]);
1013 q += other.stride()[i];
1018 Image::Image (AVFrame* frame)
1019 : _size (frame->width, frame->height)
1020 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1023 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1027 for (int i = 0; i < planes(); ++i) {
1028 uint8_t* p = _data[i];
1029 uint8_t* q = frame->data[i];
1030 int const lines = sample_size(i).height;
1031 for (int j = 0; j < lines; ++j) {
1032 memcpy (p, q, _line_size[i]);
1034 /* AVFrame's linesize is what we call `stride' */
1035 q += frame->linesize[i];
1040 Image::Image (shared_ptr<const Image> other, bool aligned)
1041 : _size (other->_size)
1042 , _pixel_format (other->_pixel_format)
1043 , _aligned (aligned)
1047 for (int i = 0; i < planes(); ++i) {
1048 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1049 uint8_t* p = _data[i];
1050 uint8_t* q = other->data()[i];
1051 int const lines = sample_size(i).height;
1052 for (int j = 0; j < lines; ++j) {
1053 memcpy (p, q, line_size()[i]);
1055 q += other->stride()[i];
1061 Image::operator= (Image const & other)
1063 if (this == &other) {
1073 Image::swap (Image & other)
1075 std::swap (_size, other._size);
1076 std::swap (_pixel_format, other._pixel_format);
1078 for (int i = 0; i < 4; ++i) {
1079 std::swap (_data[i], other._data[i]);
1080 std::swap (_line_size[i], other._line_size[i]);
1081 std::swap (_stride[i], other._stride[i]);
1084 std::swap (_aligned, other._aligned);
1089 for (int i = 0; i < planes(); ++i) {
1094 av_free (_line_size);
1099 Image::data () const
1105 Image::line_size () const
1111 Image::stride () const
1117 Image::size () const
1123 Image::aligned () const
1130 merge (list<PositionImage> images)
1132 if (images.empty ()) {
1136 if (images.size() == 1) {
1137 return images.front ();
1140 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1141 for (auto const& i: images) {
1142 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1145 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
1146 merged->make_transparent ();
1147 for (auto const& i: images) {
1148 merged->alpha_blend (i.image, i.position - all.position());
1151 return PositionImage (merged, all.position ());
1156 operator== (Image const & a, Image const & b)
1158 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1162 for (int c = 0; c < a.planes(); ++c) {
1163 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]) {
1167 uint8_t* p = a.data()[c];
1168 uint8_t* q = b.data()[c];
1169 int const lines = a.sample_size(c).height;
1170 for (int y = 0; y < lines; ++y) {
1171 if (memcmp (p, q, a.line_size()[c]) != 0) {
1184 * @param f Amount to fade by; 0 is black, 1 is no fade.
1187 Image::fade (float f)
1189 /* U/V black value for 8-bit colour */
1190 static int const eight_bit_uv = (1 << 7) - 1;
1191 /* U/V black value for 10-bit colour */
1192 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1194 switch (_pixel_format) {
1195 case AV_PIX_FMT_YUV420P:
1198 uint8_t* p = data()[0];
1199 int const lines = sample_size(0).height;
1200 for (int y = 0; y < lines; ++y) {
1202 for (int x = 0; x < line_size()[0]; ++x) {
1203 *q = int(float(*q) * f);
1210 for (int c = 1; c < 3; ++c) {
1211 uint8_t* p = data()[c];
1212 int const lines = sample_size(c).height;
1213 for (int y = 0; y < lines; ++y) {
1215 for (int x = 0; x < line_size()[c]; ++x) {
1216 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1226 case AV_PIX_FMT_RGB24:
1229 uint8_t* p = data()[0];
1230 int const lines = sample_size(0).height;
1231 for (int y = 0; y < lines; ++y) {
1233 for (int x = 0; x < line_size()[0]; ++x) {
1234 *q = int (float (*q) * f);
1242 case AV_PIX_FMT_XYZ12LE:
1243 case AV_PIX_FMT_RGB48LE:
1244 /* 16-bit little-endian */
1245 for (int c = 0; c < 3; ++c) {
1246 int const stride_pixels = stride()[c] / 2;
1247 int const line_size_pixels = line_size()[c] / 2;
1248 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1249 int const lines = sample_size(c).height;
1250 for (int y = 0; y < lines; ++y) {
1252 for (int x = 0; x < line_size_pixels; ++x) {
1253 *q = int (float (*q) * f);
1261 case AV_PIX_FMT_YUV422P10LE:
1265 int const stride_pixels = stride()[0] / 2;
1266 int const line_size_pixels = line_size()[0] / 2;
1267 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1268 int const lines = sample_size(0).height;
1269 for (int y = 0; y < lines; ++y) {
1271 for (int x = 0; x < line_size_pixels; ++x) {
1272 *q = int(float(*q) * f);
1280 for (int c = 1; c < 3; ++c) {
1281 int const stride_pixels = stride()[c] / 2;
1282 int const line_size_pixels = line_size()[c] / 2;
1283 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1284 int const lines = sample_size(c).height;
1285 for (int y = 0; y < lines; ++y) {
1287 for (int x = 0; x < line_size_pixels; ++x) {
1288 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1299 throw PixelFormatError ("fade()", _pixel_format);
1303 shared_ptr<const Image>
1304 Image::ensure_aligned (shared_ptr<const Image> image)
1306 if (image->aligned()) {
1310 return make_shared<Image>(image, true);
1314 Image::memory_used () const
1317 for (int i = 0; i < planes(); ++i) {
1318 m += _stride[i] * sample_size(i).height;
1341 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1343 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1344 size_t size = mem->size + length;
1347 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1349 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1353 throw EncodeError (N_("could not allocate memory for PNG"));
1356 memcpy (mem->data + mem->size, data, length);
1357 mem->size += length;
1361 png_flush (png_structp)
1367 png_error_fn (png_structp png_ptr, char const * message)
1369 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1373 Image::png_error (char const * message)
1375 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1379 Image::as_png () const
1381 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1382 DCPOMATIC_ASSERT (planes() == 1);
1383 if (pixel_format() != AV_PIX_FMT_RGBA) {
1384 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1387 /* error handling? */
1388 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1390 throw EncodeError (N_("could not create PNG write struct"));
1395 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1397 png_infop info_ptr = png_create_info_struct(png_ptr);
1399 png_destroy_write_struct (&png_ptr, &info_ptr);
1400 throw EncodeError (N_("could not create PNG info struct"));
1403 png_set_IHDR (png_ptr, info_ptr, size().width, size().height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1405 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1406 for (int i = 0; i < size().height; ++i) {
1407 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1410 png_write_info (png_ptr, info_ptr);
1411 png_write_image (png_ptr, row_pointers);
1412 png_write_end (png_ptr, info_ptr);
1414 png_destroy_write_struct (&png_ptr, &info_ptr);
1415 png_free (png_ptr, row_pointers);
1417 return dcp::ArrayData (state.data, state.size);
1422 Image::video_range_to_full_range ()
1424 switch (_pixel_format) {
1425 case AV_PIX_FMT_RGB24:
1427 float const factor = 256.0 / 219.0;
1428 uint8_t* p = data()[0];
1429 int const lines = sample_size(0).height;
1430 for (int y = 0; y < lines; ++y) {
1432 for (int x = 0; x < line_size()[0]; ++x) {
1433 *q = int((*q - 16) * factor);
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 = int((*q - 256) * factor);
1458 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);