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"
35 #include <dcp/rgb_xyz.h>
36 #include <dcp/transfer_function.h>
37 DCPOMATIC_DISABLE_WARNINGS
39 #include <libavutil/frame.h>
40 #include <libavutil/pixdesc.h>
41 #include <libavutil/pixfmt.h>
42 #include <libswscale/swscale.h>
44 DCPOMATIC_ENABLE_WARNINGS
46 #if HAVE_VALGRIND_MEMCHECK_H
47 #include <valgrind/memcheck.h>
58 using std::make_shared;
61 using std::runtime_error;
62 using std::shared_ptr;
67 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
68 int constexpr ALIGNMENT = 64;
70 /* U/V black value for 8-bit colour */
71 static uint8_t const eight_bit_uv = (1 << 7) - 1;
72 /* U/V black value for 9-bit colour */
73 static uint16_t const nine_bit_uv = (1 << 8) - 1;
74 /* U/V black value for 10-bit colour */
75 static uint16_t const ten_bit_uv = (1 << 9) - 1;
76 /* U/V black value for 16-bit colour */
77 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
81 Image::vertical_factor (int n) const
87 auto d = av_pix_fmt_desc_get(_pixel_format);
89 throw PixelFormatError ("line_factor()", _pixel_format);
92 return lrintf(powf(2.0f, d->log2_chroma_h));
96 Image::horizontal_factor (int n) const
102 auto d = av_pix_fmt_desc_get(_pixel_format);
104 throw PixelFormatError ("sample_size()", _pixel_format);
107 return lrintf(powf(2.0f, d->log2_chroma_w));
111 /** @param n Component index.
112 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
115 Image::sample_size (int n) const
118 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
119 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
124 /** @return Number of planes */
126 Image::planes () const
128 if (_pixel_format == AV_PIX_FMT_PAL8) {
132 auto d = av_pix_fmt_desc_get(_pixel_format);
134 throw PixelFormatError ("planes()", _pixel_format);
137 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
141 return d->nb_components;
147 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
149 return p & ~ ((1 << desc->log2_chroma_w) - 1);
155 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
157 return p & ~ ((1 << desc->log2_chroma_h) - 1);
161 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
162 * @param crop Amount to crop by.
163 * @param inter_size Size to scale the cropped image to.
164 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
165 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
166 * @param video_range Video range of the image.
167 * @param out_format Output pixel format.
168 * @param out_aligned true to make the output image aligned.
169 * @param out_video_range Video range to use for the output image.
170 * @param fast Try to be fast at the possible expense of quality; at present this means using
171 * fast bilinear rather than bicubic scaling.
174 Image::crop_scale_window (
176 dcp::Size inter_size,
178 dcp::YUVToRGB yuv_to_rgb,
179 VideoRange video_range,
180 AVPixelFormat out_format,
181 VideoRange out_video_range,
182 Alignment out_alignment,
186 /* Empirical testing suggests that sws_scale() will crash if
187 the input image is not padded.
189 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
191 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
192 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
194 auto out = make_shared<Image>(out_format, out_size, out_alignment);
197 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
199 throw PixelFormatError ("crop_scale_window()", _pixel_format);
202 /* Round down so that we crop only the number of pixels that is straightforward
203 * considering any subsampling.
206 round_width_for_subsampling(crop.left, in_desc),
207 round_width_for_subsampling(crop.right, in_desc),
208 round_height_for_subsampling(crop.top, in_desc),
209 round_height_for_subsampling(crop.bottom, in_desc)
212 /* Also check that we aren't cropping more image than there actually is */
213 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
214 corrected_crop.left = 0;
215 corrected_crop.right = size().width - 4;
218 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
219 corrected_crop.top = 0;
220 corrected_crop.bottom = size().height - 4;
223 /* Size of the image after any crop */
224 auto const cropped_size = corrected_crop.apply (size());
226 /* Scale context for a scale from cropped_size to inter_size */
227 auto scale_context = sws_getContext (
228 cropped_size.width, cropped_size.height, pixel_format(),
229 inter_size.width, inter_size.height, out_format,
230 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
233 if (!scale_context) {
234 throw runtime_error (N_("Could not allocate SwsContext"));
237 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
238 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
243 /* The 3rd parameter here is:
244 0 -> source range MPEG (i.e. "video", 16-235)
245 1 -> source range JPEG (i.e. "full", 0-255)
247 0 -> destination range MPEG (i.e. "video", 16-235)
248 1 -> destination range JPEG (i.e. "full", 0-255)
250 But remember: sws_setColorspaceDetails ignores these
251 parameters unless the both source and destination images
252 are isYUV or isGray. (If either is not, it uses video range).
254 sws_setColorspaceDetails (
256 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
257 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
261 /* Prepare input data pointers with crop */
262 uint8_t* scale_in_data[planes()];
263 for (int c = 0; c < planes(); ++c) {
264 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
265 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
268 auto out_desc = av_pix_fmt_desc_get (out_format);
270 throw PixelFormatError ("crop_scale_window()", out_format);
273 /* Corner of the image within out_size */
274 Position<int> const corner (
275 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
276 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
279 uint8_t* scale_out_data[out->planes()];
280 for (int c = 0; c < out->planes(); ++c) {
281 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
282 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
287 scale_in_data, stride(),
288 0, cropped_size.height,
289 scale_out_data, out->stride()
292 sws_freeContext (scale_context);
294 if (corrected_crop != Crop() && cropped_size == inter_size) {
295 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
296 data behind in our image. Clear it out. It may get to the point where we should just stop
297 trying to be clever with cropping.
299 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
303 video_range == VideoRange::VIDEO &&
304 out_video_range == VideoRange::FULL &&
305 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
307 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
308 out->video_range_to_full_range ();
316 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
318 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
322 /** @param out_size Size to scale to.
323 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
324 * @param out_format Output pixel format.
325 * @param out_aligment Output alignment.
326 * @param fast Try to be fast at the possible expense of quality; at present this means using
327 * fast bilinear rather than bicubic scaling.
330 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
332 /* Empirical testing suggests that sws_scale() will crash if
333 the input image alignment is not PADDED.
335 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
337 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
338 auto scale_context = sws_getContext (
339 size().width, size().height, pixel_format(),
340 out_size.width, out_size.height, out_format,
341 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
344 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
345 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
350 /* The 3rd parameter here is:
351 0 -> source range MPEG (i.e. "video", 16-235)
352 1 -> source range JPEG (i.e. "full", 0-255)
354 0 -> destination range MPEG (i.e. "video", 16-235)
355 1 -> destination range JPEG (i.e. "full", 0-255)
357 But remember: sws_setColorspaceDetails ignores these
358 parameters unless the corresponding image isYUV or isGray.
359 (If it's neither, it uses video range).
361 sws_setColorspaceDetails (
363 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
364 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
372 scaled->data(), scaled->stride()
375 sws_freeContext (scale_context);
381 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
383 Image::yuv_16_black (uint16_t v, bool alpha)
385 memset (data()[0], 0, sample_size(0).height * stride()[0]);
386 for (int i = 1; i < 3; ++i) {
387 auto p = reinterpret_cast<int16_t*> (data()[i]);
388 int const lines = sample_size(i).height;
389 for (int y = 0; y < lines; ++y) {
390 /* We divide by 2 here because we are writing 2 bytes at a time */
391 for (int x = 0; x < line_size()[i] / 2; ++x) {
394 p += stride()[i] / 2;
399 memset (data()[3], 0, sample_size(3).height * stride()[3]);
405 Image::swap_16 (uint16_t v)
407 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
412 Image::make_part_black (int const start, int const width)
414 auto y_part = [&]() {
415 int const bpp = bytes_per_pixel(0);
416 int const h = sample_size(0).height;
417 int const s = stride()[0];
419 for (int y = 0; y < h; ++y) {
420 memset (p + start * bpp, 0, width * bpp);
425 switch (_pixel_format) {
426 case AV_PIX_FMT_RGB24:
427 case AV_PIX_FMT_ARGB:
428 case AV_PIX_FMT_RGBA:
429 case AV_PIX_FMT_ABGR:
430 case AV_PIX_FMT_BGRA:
431 case AV_PIX_FMT_RGB555LE:
432 case AV_PIX_FMT_RGB48LE:
433 case AV_PIX_FMT_RGB48BE:
434 case AV_PIX_FMT_XYZ12LE:
436 int const h = sample_size(0).height;
437 int const bpp = bytes_per_pixel(0);
438 int const s = stride()[0];
439 uint8_t* p = data()[0];
440 for (int y = 0; y < h; y++) {
441 memset (p + start * bpp, 0, width * bpp);
446 case AV_PIX_FMT_YUV420P:
449 for (int i = 1; i < 3; ++i) {
451 int const h = sample_size(i).height;
452 for (int y = 0; y < h; ++y) {
453 for (int x = start / 2; x < (start + width) / 2; ++x) {
461 case AV_PIX_FMT_YUV422P10LE:
464 for (int i = 1; i < 3; ++i) {
465 auto p = reinterpret_cast<int16_t*>(data()[i]);
466 int const h = sample_size(i).height;
467 for (int y = 0; y < h; ++y) {
468 for (int x = start / 2; x < (start + width) / 2; ++x) {
471 p += stride()[i] / 2;
477 throw PixelFormatError ("make_part_black()", _pixel_format);
485 switch (_pixel_format) {
486 case AV_PIX_FMT_YUV420P:
487 case AV_PIX_FMT_YUV422P:
488 case AV_PIX_FMT_YUV444P:
489 case AV_PIX_FMT_YUV411P:
490 memset (data()[0], 0, sample_size(0).height * stride()[0]);
491 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
492 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
495 case AV_PIX_FMT_YUVJ420P:
496 case AV_PIX_FMT_YUVJ422P:
497 case AV_PIX_FMT_YUVJ444P:
498 memset (data()[0], 0, sample_size(0).height * stride()[0]);
499 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
500 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
503 case AV_PIX_FMT_YUV422P9LE:
504 case AV_PIX_FMT_YUV444P9LE:
505 yuv_16_black (nine_bit_uv, false);
508 case AV_PIX_FMT_YUV422P9BE:
509 case AV_PIX_FMT_YUV444P9BE:
510 yuv_16_black (swap_16 (nine_bit_uv), false);
513 case AV_PIX_FMT_YUV422P10LE:
514 case AV_PIX_FMT_YUV444P10LE:
515 yuv_16_black (ten_bit_uv, false);
518 case AV_PIX_FMT_YUV422P16LE:
519 case AV_PIX_FMT_YUV444P16LE:
520 yuv_16_black (sixteen_bit_uv, false);
523 case AV_PIX_FMT_YUV444P10BE:
524 case AV_PIX_FMT_YUV422P10BE:
525 yuv_16_black (swap_16 (ten_bit_uv), false);
528 case AV_PIX_FMT_YUVA420P9BE:
529 case AV_PIX_FMT_YUVA422P9BE:
530 case AV_PIX_FMT_YUVA444P9BE:
531 yuv_16_black (swap_16 (nine_bit_uv), true);
534 case AV_PIX_FMT_YUVA420P9LE:
535 case AV_PIX_FMT_YUVA422P9LE:
536 case AV_PIX_FMT_YUVA444P9LE:
537 yuv_16_black (nine_bit_uv, true);
540 case AV_PIX_FMT_YUVA420P10BE:
541 case AV_PIX_FMT_YUVA422P10BE:
542 case AV_PIX_FMT_YUVA444P10BE:
543 yuv_16_black (swap_16 (ten_bit_uv), true);
546 case AV_PIX_FMT_YUVA420P10LE:
547 case AV_PIX_FMT_YUVA422P10LE:
548 case AV_PIX_FMT_YUVA444P10LE:
549 yuv_16_black (ten_bit_uv, true);
552 case AV_PIX_FMT_YUVA420P16BE:
553 case AV_PIX_FMT_YUVA422P16BE:
554 case AV_PIX_FMT_YUVA444P16BE:
555 yuv_16_black (swap_16 (sixteen_bit_uv), true);
558 case AV_PIX_FMT_YUVA420P16LE:
559 case AV_PIX_FMT_YUVA422P16LE:
560 case AV_PIX_FMT_YUVA444P16LE:
561 yuv_16_black (sixteen_bit_uv, true);
564 case AV_PIX_FMT_RGB24:
565 case AV_PIX_FMT_ARGB:
566 case AV_PIX_FMT_RGBA:
567 case AV_PIX_FMT_ABGR:
568 case AV_PIX_FMT_BGRA:
569 case AV_PIX_FMT_RGB555LE:
570 case AV_PIX_FMT_RGB48LE:
571 case AV_PIX_FMT_RGB48BE:
572 case AV_PIX_FMT_XYZ12LE:
573 memset (data()[0], 0, sample_size(0).height * stride()[0]);
576 case AV_PIX_FMT_UYVY422:
578 int const Y = sample_size(0).height;
579 int const X = line_size()[0];
580 uint8_t* p = data()[0];
581 for (int y = 0; y < Y; ++y) {
582 for (int x = 0; x < X / 4; ++x) {
583 *p++ = eight_bit_uv; // Cb
585 *p++ = eight_bit_uv; // Cr
593 throw PixelFormatError ("make_black()", _pixel_format);
599 Image::make_transparent ()
601 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
602 throw PixelFormatError ("make_transparent()", _pixel_format);
605 memset (data()[0], 0, sample_size(0).height * stride()[0]);
610 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
612 /* We're blending RGBA or BGRA images */
613 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
614 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
615 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
617 int const other_bpp = 4;
619 int start_tx = position.x;
623 start_ox = -start_tx;
627 int start_ty = position.y;
631 start_oy = -start_ty;
635 switch (_pixel_format) {
636 case AV_PIX_FMT_RGB24:
638 /* Going onto RGB24. First byte is red, second green, third blue */
639 int const this_bpp = 3;
640 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
641 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
642 uint8_t* op = other->data()[0] + oy * other->stride()[0];
643 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
644 float const alpha = float (op[3]) / 255;
645 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
646 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
647 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
655 case AV_PIX_FMT_BGRA:
657 int const this_bpp = 4;
658 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
659 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
660 uint8_t* op = other->data()[0] + oy * other->stride()[0];
661 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
662 float const alpha = float (op[3]) / 255;
663 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
664 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
665 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
666 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
674 case AV_PIX_FMT_RGBA:
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[red] * alpha + tp[0] * (1 - alpha);
683 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
684 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
685 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
693 case AV_PIX_FMT_RGB48LE:
695 int const this_bpp = 6;
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 /* Blend high bytes */
702 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
703 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
704 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
712 case AV_PIX_FMT_XYZ12LE:
714 auto conv = dcp::ColourConversion::srgb_to_xyz();
715 double fast_matrix[9];
716 dcp::combined_rgb_to_xyz (conv, fast_matrix);
717 double const * lut_in = conv.in()->lut (8, false);
718 double const * lut_out = conv.out()->lut (16, true);
719 int const this_bpp = 6;
720 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
721 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
722 uint8_t* op = other->data()[0] + oy * other->stride()[0];
723 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
724 float const alpha = float (op[3]) / 255;
726 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
727 double const r = lut_in[op[red]];
728 double const g = lut_in[op[1]];
729 double const b = lut_in[op[blue]];
731 /* RGB to XYZ, including Bradford transform and DCI companding */
732 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
733 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
734 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
736 /* Out gamma LUT and blend */
737 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
738 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
739 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
747 case AV_PIX_FMT_YUV420P:
749 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
750 dcp::Size const ts = size();
751 dcp::Size const os = yuv->size();
752 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
753 int const hty = ty / 2;
754 int const hoy = oy / 2;
755 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
756 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
757 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
758 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
759 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
760 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
761 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
762 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
763 float const a = float(alpha[3]) / 255;
764 *tY = *oY * a + *tY * (1 - a);
765 *tU = *oU * a + *tU * (1 - a);
766 *tV = *oV * a + *tV * (1 - a);
782 case AV_PIX_FMT_YUV420P10:
784 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
785 dcp::Size const ts = size();
786 dcp::Size const os = yuv->size();
787 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
788 int const hty = ty / 2;
789 int const hoy = oy / 2;
790 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
791 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
792 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
793 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
794 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
795 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
796 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
797 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
798 float const a = float(alpha[3]) / 255;
799 *tY = *oY * a + *tY * (1 - a);
800 *tU = *oU * a + *tU * (1 - a);
801 *tV = *oV * a + *tV * (1 - a);
817 case AV_PIX_FMT_YUV422P10LE:
819 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
820 dcp::Size const ts = size();
821 dcp::Size const os = yuv->size();
822 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
823 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
824 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
825 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * 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] + (oy * yuv->stride()[1]))) + start_ox / 2;
828 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * 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);
851 throw PixelFormatError ("alpha_blend()", _pixel_format);
857 Image::copy (shared_ptr<const Image> other, Position<int> position)
859 /* Only implemented for RGB24 onto RGB24 so far */
860 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
861 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
863 int const N = min (position.x + other->size().width, size().width) - position.x;
864 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
865 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
866 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
867 memcpy (tp, op, N * 3);
873 Image::read_from_socket (shared_ptr<Socket> socket)
875 for (int i = 0; i < planes(); ++i) {
876 uint8_t* p = data()[i];
877 int const lines = sample_size(i).height;
878 for (int y = 0; y < lines; ++y) {
879 socket->read (p, line_size()[i]);
887 Image::write_to_socket (shared_ptr<Socket> socket) const
889 for (int i = 0; i < planes(); ++i) {
890 uint8_t* p = data()[i];
891 int const lines = sample_size(i).height;
892 for (int y = 0; y < lines; ++y) {
893 socket->write (p, line_size()[i]);
901 Image::bytes_per_pixel (int c) const
903 auto d = av_pix_fmt_desc_get(_pixel_format);
905 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
912 float bpp[4] = { 0, 0, 0, 0 };
914 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
915 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
916 if (d->nb_components > 1) {
917 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
919 if (d->nb_components > 2) {
920 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
922 if (d->nb_components > 3) {
923 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
926 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
927 if (d->nb_components > 1) {
928 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
930 if (d->nb_components > 2) {
931 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
933 if (d->nb_components > 3) {
934 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
938 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
939 /* Not planar; sum them up */
940 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
947 /** Construct a Image of a given size and format, allocating memory
950 * @param p Pixel format.
951 * @param s Size in pixels.
952 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
954 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
957 , _alignment (alignment)
966 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
967 _data[0] = _data[1] = _data[2] = _data[3] = 0;
969 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
970 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
972 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
973 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
975 auto stride_round_up = [](int stride, int t) {
976 int const a = stride + (t - 1);
980 for (int i = 0; i < planes(); ++i) {
981 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
982 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
984 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
985 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
986 Hence on the last pixel of the last line it reads over the end of
987 the actual data by 1 byte. If the width of an image is a multiple
988 of the stride alignment there will be no padding at the end of image lines.
989 OS X crashes on this illegal read, though other operating systems don't
990 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
991 for that instruction to read safely.
993 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
994 over-reads by more then _avx. I can't follow the code to work out how much,
995 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
996 testing suggests that it works.
998 In addition to these concerns, we may read/write as much as a whole extra line
999 at the end of each plane in cases where we are messing with offsets in order to
1000 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1002 As an example: we may write to images starting at an offset so we get some padding.
1003 Hence we want to write in the following pattern:
1005 block start write start line end
1006 |..(padding)..|<------line-size------------->|..(padding)..|
1007 |..(padding)..|<------line-size------------->|..(padding)..|
1008 |..(padding)..|<------line-size------------->|..(padding)..|
1010 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1011 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1012 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1013 specified *stride*. This does not matter until we get to the last line:
1015 block start write start line end
1016 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1017 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1018 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1021 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1022 #if HAVE_VALGRIND_MEMCHECK_H
1023 /* The data between the end of the line size and the stride is undefined but processed by
1024 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1026 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1032 Image::Image (Image const & other)
1033 : std::enable_shared_from_this<Image>(other)
1034 , _size (other._size)
1035 , _pixel_format (other._pixel_format)
1036 , _alignment (other._alignment)
1040 for (int i = 0; i < planes(); ++i) {
1041 uint8_t* p = _data[i];
1042 uint8_t* q = other._data[i];
1043 int const lines = sample_size(i).height;
1044 for (int j = 0; j < lines; ++j) {
1045 memcpy (p, q, _line_size[i]);
1047 q += other.stride()[i];
1053 Image::Image (AVFrame const * frame, Alignment alignment)
1054 : _size (frame->width, frame->height)
1055 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1056 , _alignment (alignment)
1058 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1062 for (int i = 0; i < planes(); ++i) {
1063 uint8_t* p = _data[i];
1064 uint8_t* q = frame->data[i];
1065 int const lines = sample_size(i).height;
1066 for (int j = 0; j < lines; ++j) {
1067 memcpy (p, q, _line_size[i]);
1069 /* AVFrame's linesize is what we call `stride' */
1070 q += frame->linesize[i];
1076 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1077 : _size (other->_size)
1078 , _pixel_format (other->_pixel_format)
1079 , _alignment (alignment)
1083 for (int i = 0; i < planes(); ++i) {
1084 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1085 uint8_t* p = _data[i];
1086 uint8_t* q = other->data()[i];
1087 int const lines = sample_size(i).height;
1088 for (int j = 0; j < lines; ++j) {
1089 memcpy (p, q, line_size()[i]);
1091 q += other->stride()[i];
1098 Image::operator= (Image const & other)
1100 if (this == &other) {
1111 Image::swap (Image & other)
1113 std::swap (_size, other._size);
1114 std::swap (_pixel_format, other._pixel_format);
1116 for (int i = 0; i < 4; ++i) {
1117 std::swap (_data[i], other._data[i]);
1118 std::swap (_line_size[i], other._line_size[i]);
1119 std::swap (_stride[i], other._stride[i]);
1122 std::swap (_alignment, other._alignment);
1128 for (int i = 0; i < planes(); ++i) {
1133 av_free (_line_size);
1139 Image::data () const
1146 Image::line_size () const
1153 Image::stride () const
1160 Image::size () const
1167 Image::alignment () const
1174 merge (list<PositionImage> images, Image::Alignment alignment)
1176 if (images.empty ()) {
1180 if (images.size() == 1) {
1181 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1182 return images.front();
1185 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1186 for (auto const& i: images) {
1187 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1190 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1191 merged->make_transparent ();
1192 for (auto const& i: images) {
1193 merged->alpha_blend (i.image, i.position - all.position());
1196 return PositionImage (merged, all.position ());
1201 operator== (Image const & a, Image const & b)
1203 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1207 for (int c = 0; c < a.planes(); ++c) {
1208 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]) {
1212 uint8_t* p = a.data()[c];
1213 uint8_t* q = b.data()[c];
1214 int const lines = a.sample_size(c).height;
1215 for (int y = 0; y < lines; ++y) {
1216 if (memcmp (p, q, a.line_size()[c]) != 0) {
1230 * @param f Amount to fade by; 0 is black, 1 is no fade.
1233 Image::fade (float f)
1235 /* U/V black value for 8-bit colour */
1236 static int const eight_bit_uv = (1 << 7) - 1;
1237 /* U/V black value for 10-bit colour */
1238 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1240 switch (_pixel_format) {
1241 case AV_PIX_FMT_YUV420P:
1244 uint8_t* p = data()[0];
1245 int const lines = sample_size(0).height;
1246 for (int y = 0; y < lines; ++y) {
1248 for (int x = 0; x < line_size()[0]; ++x) {
1249 *q = int(float(*q) * f);
1256 for (int c = 1; c < 3; ++c) {
1257 uint8_t* p = data()[c];
1258 int const lines = sample_size(c).height;
1259 for (int y = 0; y < lines; ++y) {
1261 for (int x = 0; x < line_size()[c]; ++x) {
1262 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1272 case AV_PIX_FMT_RGB24:
1275 uint8_t* p = data()[0];
1276 int const lines = sample_size(0).height;
1277 for (int y = 0; y < lines; ++y) {
1279 for (int x = 0; x < line_size()[0]; ++x) {
1280 *q = int (float (*q) * f);
1288 case AV_PIX_FMT_XYZ12LE:
1289 case AV_PIX_FMT_RGB48LE:
1290 /* 16-bit little-endian */
1291 for (int c = 0; c < 3; ++c) {
1292 int const stride_pixels = stride()[c] / 2;
1293 int const line_size_pixels = line_size()[c] / 2;
1294 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1295 int const lines = sample_size(c).height;
1296 for (int y = 0; y < lines; ++y) {
1298 for (int x = 0; x < line_size_pixels; ++x) {
1299 *q = int (float (*q) * f);
1307 case AV_PIX_FMT_YUV422P10LE:
1311 int const stride_pixels = stride()[0] / 2;
1312 int const line_size_pixels = line_size()[0] / 2;
1313 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1314 int const lines = sample_size(0).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 for (int c = 1; c < 3; ++c) {
1327 int const stride_pixels = stride()[c] / 2;
1328 int const line_size_pixels = line_size()[c] / 2;
1329 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1330 int const lines = sample_size(c).height;
1331 for (int y = 0; y < lines; ++y) {
1333 for (int x = 0; x < line_size_pixels; ++x) {
1334 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1345 throw PixelFormatError ("fade()", _pixel_format);
1350 shared_ptr<const Image>
1351 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1353 if (image->alignment() == alignment) {
1357 return make_shared<Image>(image, alignment);
1362 Image::memory_used () const
1365 for (int i = 0; i < planes(); ++i) {
1366 m += _stride[i] * sample_size(i).height;
1391 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1393 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1394 size_t size = mem->size + length;
1397 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1399 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1403 throw EncodeError (N_("could not allocate memory for PNG"));
1406 memcpy (mem->data + mem->size, data, length);
1407 mem->size += length;
1412 png_flush (png_structp)
1419 png_error_fn (png_structp png_ptr, char const * message)
1421 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1426 Image::png_error (char const * message)
1428 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1433 Image::as_png () const
1435 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1436 DCPOMATIC_ASSERT (planes() == 1);
1437 if (pixel_format() != AV_PIX_FMT_RGBA) {
1438 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png();
1441 /* error handling? */
1442 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1444 throw EncodeError (N_("could not create PNG write struct"));
1449 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1451 png_infop info_ptr = png_create_info_struct(png_ptr);
1453 png_destroy_write_struct (&png_ptr, &info_ptr);
1454 throw EncodeError (N_("could not create PNG info struct"));
1457 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);
1459 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1460 for (int i = 0; i < size().height; ++i) {
1461 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1464 png_write_info (png_ptr, info_ptr);
1465 png_write_image (png_ptr, row_pointers);
1466 png_write_end (png_ptr, info_ptr);
1468 png_destroy_write_struct (&png_ptr, &info_ptr);
1469 png_free (png_ptr, row_pointers);
1471 return dcp::ArrayData (state.data, state.size);
1476 Image::video_range_to_full_range ()
1478 switch (_pixel_format) {
1479 case AV_PIX_FMT_RGB24:
1481 float const factor = 256.0 / 219.0;
1482 uint8_t* p = data()[0];
1483 int const lines = sample_size(0).height;
1484 for (int y = 0; y < lines; ++y) {
1486 for (int x = 0; x < line_size()[0]; ++x) {
1487 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1494 case AV_PIX_FMT_RGB48LE:
1496 float const factor = 65536.0 / 56064.0;
1497 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1498 int const lines = sample_size(0).height;
1499 for (int y = 0; y < lines; ++y) {
1501 int const line_size_pixels = line_size()[0] / 2;
1502 for (int x = 0; x < line_size_pixels; ++x) {
1503 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1506 p += stride()[0] / 2;
1510 case AV_PIX_FMT_GBRP12LE:
1512 float const factor = 4096.0 / 3504.0;
1513 for (int c = 0; c < 3; ++c) {
1514 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1515 int const lines = sample_size(c).height;
1516 for (int y = 0; y < lines; ++y) {
1518 int const line_size_pixels = line_size()[c] / 2;
1519 for (int x = 0; x < line_size_pixels; ++x) {
1520 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1528 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);