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 for (int i = 0; i < planes(); ++i) {
976 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
977 _stride[i] = stride_round_up (i, _line_size, _alignment == Alignment::PADDED ? ALIGNMENT : 1);
979 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
980 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
981 Hence on the last pixel of the last line it reads over the end of
982 the actual data by 1 byte. If the width of an image is a multiple
983 of the stride alignment there will be no padding at the end of image lines.
984 OS X crashes on this illegal read, though other operating systems don't
985 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
986 for that instruction to read safely.
988 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
989 over-reads by more then _avx. I can't follow the code to work out how much,
990 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
991 testing suggests that it works.
993 In addition to these concerns, we may read/write as much as a whole extra line
994 at the end of each plane in cases where we are messing with offsets in order to
995 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
997 As an example: we may write to images starting at an offset so we get some padding.
998 Hence we want to write in the following pattern:
1000 block start write start line end
1001 |..(padding)..|<------line-size------------->|..(padding)..|
1002 |..(padding)..|<------line-size------------->|..(padding)..|
1003 |..(padding)..|<------line-size------------->|..(padding)..|
1005 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1006 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1007 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1008 specified *stride*. This does not matter until we get to the last line:
1010 block start write start line end
1011 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1012 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1013 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1016 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1017 #if HAVE_VALGRIND_MEMCHECK_H
1018 /* The data between the end of the line size and the stride is undefined but processed by
1019 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1021 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1027 Image::Image (Image const & other)
1028 : std::enable_shared_from_this<Image>(other)
1029 , _size (other._size)
1030 , _pixel_format (other._pixel_format)
1031 , _alignment (other._alignment)
1035 for (int i = 0; i < planes(); ++i) {
1036 uint8_t* p = _data[i];
1037 uint8_t* q = other._data[i];
1038 int const lines = sample_size(i).height;
1039 for (int j = 0; j < lines; ++j) {
1040 memcpy (p, q, _line_size[i]);
1042 q += other.stride()[i];
1048 Image::Image (AVFrame const * frame, Alignment alignment)
1049 : _size (frame->width, frame->height)
1050 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1051 , _alignment (alignment)
1053 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1057 for (int i = 0; i < planes(); ++i) {
1058 uint8_t* p = _data[i];
1059 uint8_t* q = frame->data[i];
1060 int const lines = sample_size(i).height;
1061 for (int j = 0; j < lines; ++j) {
1062 memcpy (p, q, _line_size[i]);
1064 /* AVFrame's linesize is what we call `stride' */
1065 q += frame->linesize[i];
1071 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1072 : _size (other->_size)
1073 , _pixel_format (other->_pixel_format)
1074 , _alignment (alignment)
1078 for (int i = 0; i < planes(); ++i) {
1079 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1080 uint8_t* p = _data[i];
1081 uint8_t* q = other->data()[i];
1082 int const lines = sample_size(i).height;
1083 for (int j = 0; j < lines; ++j) {
1084 memcpy (p, q, line_size()[i]);
1086 q += other->stride()[i];
1093 Image::operator= (Image const & other)
1095 if (this == &other) {
1106 Image::swap (Image & other)
1108 std::swap (_size, other._size);
1109 std::swap (_pixel_format, other._pixel_format);
1111 for (int i = 0; i < 4; ++i) {
1112 std::swap (_data[i], other._data[i]);
1113 std::swap (_line_size[i], other._line_size[i]);
1114 std::swap (_stride[i], other._stride[i]);
1117 std::swap (_alignment, other._alignment);
1123 for (int i = 0; i < planes(); ++i) {
1128 av_free (_line_size);
1134 Image::data () const
1141 Image::line_size () const
1148 Image::stride () const
1155 Image::size () const
1162 Image::alignment () const
1169 merge (list<PositionImage> images, Image::Alignment alignment)
1171 if (images.empty ()) {
1175 if (images.size() == 1) {
1176 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1177 return images.front();
1180 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1181 for (auto const& i: images) {
1182 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1185 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1186 merged->make_transparent ();
1187 for (auto const& i: images) {
1188 merged->alpha_blend (i.image, i.position - all.position());
1191 return PositionImage (merged, all.position ());
1196 operator== (Image const & a, Image const & b)
1198 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1202 for (int c = 0; c < a.planes(); ++c) {
1203 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]) {
1207 uint8_t* p = a.data()[c];
1208 uint8_t* q = b.data()[c];
1209 int const lines = a.sample_size(c).height;
1210 for (int y = 0; y < lines; ++y) {
1211 if (memcmp (p, q, a.line_size()[c]) != 0) {
1225 * @param f Amount to fade by; 0 is black, 1 is no fade.
1228 Image::fade (float f)
1230 /* U/V black value for 8-bit colour */
1231 static int const eight_bit_uv = (1 << 7) - 1;
1232 /* U/V black value for 10-bit colour */
1233 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1235 switch (_pixel_format) {
1236 case AV_PIX_FMT_YUV420P:
1239 uint8_t* p = data()[0];
1240 int const lines = sample_size(0).height;
1241 for (int y = 0; y < lines; ++y) {
1243 for (int x = 0; x < line_size()[0]; ++x) {
1244 *q = int(float(*q) * f);
1251 for (int c = 1; c < 3; ++c) {
1252 uint8_t* p = data()[c];
1253 int const lines = sample_size(c).height;
1254 for (int y = 0; y < lines; ++y) {
1256 for (int x = 0; x < line_size()[c]; ++x) {
1257 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1267 case AV_PIX_FMT_RGB24:
1270 uint8_t* p = data()[0];
1271 int const lines = sample_size(0).height;
1272 for (int y = 0; y < lines; ++y) {
1274 for (int x = 0; x < line_size()[0]; ++x) {
1275 *q = int (float (*q) * f);
1283 case AV_PIX_FMT_XYZ12LE:
1284 case AV_PIX_FMT_RGB48LE:
1285 /* 16-bit little-endian */
1286 for (int c = 0; c < 3; ++c) {
1287 int const stride_pixels = stride()[c] / 2;
1288 int const line_size_pixels = line_size()[c] / 2;
1289 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1290 int const lines = sample_size(c).height;
1291 for (int y = 0; y < lines; ++y) {
1293 for (int x = 0; x < line_size_pixels; ++x) {
1294 *q = int (float (*q) * f);
1302 case AV_PIX_FMT_YUV422P10LE:
1306 int const stride_pixels = stride()[0] / 2;
1307 int const line_size_pixels = line_size()[0] / 2;
1308 uint16_t* p = reinterpret_cast<uint16_t*> (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_pixels; ++x) {
1313 *q = int(float(*q) * f);
1321 for (int c = 1; c < 3; ++c) {
1322 int const stride_pixels = stride()[c] / 2;
1323 int const line_size_pixels = line_size()[c] / 2;
1324 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1325 int const lines = sample_size(c).height;
1326 for (int y = 0; y < lines; ++y) {
1328 for (int x = 0; x < line_size_pixels; ++x) {
1329 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1340 throw PixelFormatError ("fade()", _pixel_format);
1345 shared_ptr<const Image>
1346 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1348 if (image->alignment() == alignment) {
1352 return make_shared<Image>(image, alignment);
1357 Image::memory_used () const
1360 for (int i = 0; i < planes(); ++i) {
1361 m += _stride[i] * sample_size(i).height;
1386 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1388 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1389 size_t size = mem->size + length;
1392 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1394 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1398 throw EncodeError (N_("could not allocate memory for PNG"));
1401 memcpy (mem->data + mem->size, data, length);
1402 mem->size += length;
1407 png_flush (png_structp)
1414 png_error_fn (png_structp png_ptr, char const * message)
1416 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1421 Image::png_error (char const * message)
1423 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1428 Image::as_png () const
1430 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1431 DCPOMATIC_ASSERT (planes() == 1);
1432 if (pixel_format() != AV_PIX_FMT_RGBA) {
1433 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png();
1436 /* error handling? */
1437 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1439 throw EncodeError (N_("could not create PNG write struct"));
1444 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1446 png_infop info_ptr = png_create_info_struct(png_ptr);
1448 png_destroy_write_struct (&png_ptr, &info_ptr);
1449 throw EncodeError (N_("could not create PNG info struct"));
1452 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);
1454 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1455 for (int i = 0; i < size().height; ++i) {
1456 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1459 png_write_info (png_ptr, info_ptr);
1460 png_write_image (png_ptr, row_pointers);
1461 png_write_end (png_ptr, info_ptr);
1463 png_destroy_write_struct (&png_ptr, &info_ptr);
1464 png_free (png_ptr, row_pointers);
1466 return dcp::ArrayData (state.data, state.size);
1471 Image::video_range_to_full_range ()
1473 switch (_pixel_format) {
1474 case AV_PIX_FMT_RGB24:
1476 float const factor = 256.0 / 219.0;
1477 uint8_t* p = data()[0];
1478 int const lines = sample_size(0).height;
1479 for (int y = 0; y < lines; ++y) {
1481 for (int x = 0; x < line_size()[0]; ++x) {
1482 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1489 case AV_PIX_FMT_RGB48LE:
1491 float const factor = 65536.0 / 56064.0;
1492 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1493 int const lines = sample_size(0).height;
1494 for (int y = 0; y < lines; ++y) {
1496 int const line_size_pixels = line_size()[0] / 2;
1497 for (int x = 0; x < line_size_pixels; ++x) {
1498 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1501 p += stride()[0] / 2;
1505 case AV_PIX_FMT_GBRP12LE:
1507 float const factor = 4096.0 / 3504.0;
1508 for (int c = 0; c < 3; ++c) {
1509 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1510 int const lines = sample_size(c).height;
1511 for (int y = 0; y < lines; ++y) {
1513 int const line_size_pixels = line_size()[c] / 2;
1514 for (int x = 0; x < line_size_pixels; ++x) {
1515 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1523 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);