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 aligment is requested */
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));
110 /** @param n Component index.
111 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
114 Image::sample_size (int n) const
117 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
118 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
122 /** @return Number of planes */
124 Image::planes () const
126 auto d = av_pix_fmt_desc_get(_pixel_format);
128 throw PixelFormatError ("planes()", _pixel_format);
131 if (_pixel_format == AV_PIX_FMT_PAL8) {
135 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
139 return d->nb_components;
145 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
147 return p & ~ ((1 << desc->log2_chroma_w) - 1);
153 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
155 return p & ~ ((1 << desc->log2_chroma_h) - 1);
159 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
160 * @param crop Amount to crop by.
161 * @param inter_size Size to scale the cropped image to.
162 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
163 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
164 * @param video_range Video range of the image.
165 * @param out_format Output pixel format.
166 * @param out_aligned true to make the output image aligned.
167 * @param out_video_range Video range to use for the output image.
168 * @param fast Try to be fast at the possible expense of quality; at present this means using
169 * fast bilinear rather than bicubic scaling.
172 Image::crop_scale_window (
174 dcp::Size inter_size,
176 dcp::YUVToRGB yuv_to_rgb,
177 VideoRange video_range,
178 AVPixelFormat out_format,
179 VideoRange out_video_range,
184 /* Empirical testing suggests that sws_scale() will crash if
185 the input image is not aligned.
187 DCPOMATIC_ASSERT (aligned ());
189 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
190 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
192 auto out = make_shared<Image>(out_format, out_size, out_aligned);
195 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
197 throw PixelFormatError ("crop_scale_window()", _pixel_format);
200 /* Round down so that we crop only the number of pixels that is straightforward
201 * considering any subsampling.
204 round_width_for_subsampling(crop.left, in_desc),
205 round_width_for_subsampling(crop.right, in_desc),
206 round_height_for_subsampling(crop.top, in_desc),
207 round_height_for_subsampling(crop.bottom, in_desc)
210 /* Also check that we aren't cropping more image than there actually is */
211 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
212 corrected_crop.left = 0;
213 corrected_crop.right = size().width - 4;
216 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
217 corrected_crop.top = 0;
218 corrected_crop.bottom = size().height - 4;
221 /* Size of the image after any crop */
222 auto const cropped_size = corrected_crop.apply (size());
224 /* Scale context for a scale from cropped_size to inter_size */
225 auto scale_context = sws_getContext (
226 cropped_size.width, cropped_size.height, pixel_format(),
227 inter_size.width, inter_size.height, out_format,
228 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
231 if (!scale_context) {
232 throw runtime_error (N_("Could not allocate SwsContext"));
235 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
236 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
241 /* The 3rd parameter here is:
242 0 -> source range MPEG (i.e. "video", 16-235)
243 1 -> source range JPEG (i.e. "full", 0-255)
245 0 -> destination range MPEG (i.e. "video", 16-235)
246 1 -> destination range JPEG (i.e. "full", 0-255)
248 But remember: sws_setColorspaceDetails ignores these
249 parameters unless the both source and destination images
250 are isYUV or isGray. (If either is not, it uses video range).
252 sws_setColorspaceDetails (
254 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
255 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
259 /* Prepare input data pointers with crop */
260 uint8_t* scale_in_data[planes()];
261 for (int c = 0; c < planes(); ++c) {
262 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
263 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
266 auto out_desc = av_pix_fmt_desc_get (out_format);
268 throw PixelFormatError ("crop_scale_window()", out_format);
271 /* Corner of the image within out_size */
272 Position<int> const corner (
273 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
274 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
277 uint8_t* scale_out_data[out->planes()];
278 for (int c = 0; c < out->planes(); ++c) {
279 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
280 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
285 scale_in_data, stride(),
286 0, cropped_size.height,
287 scale_out_data, out->stride()
290 sws_freeContext (scale_context);
292 if (corrected_crop != Crop() && cropped_size == inter_size) {
293 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
294 data behind in our image. Clear it out. It may get to the point where we should just stop
295 trying to be clever with cropping.
297 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
304 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
306 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
309 /** @param out_size Size to scale to.
310 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
311 * @param out_format Output pixel format.
312 * @param out_aligned true to make an aligned output image.
313 * @param fast Try to be fast at the possible expense of quality; at present this means using
314 * fast bilinear rather than bicubic scaling.
317 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
319 /* Empirical testing suggests that sws_scale() will crash if
320 the input image is not aligned.
322 DCPOMATIC_ASSERT (aligned ());
324 auto scaled = make_shared<Image>(out_format, out_size, out_aligned);
325 auto scale_context = sws_getContext (
326 size().width, size().height, pixel_format(),
327 out_size.width, out_size.height, out_format,
328 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
331 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
332 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
337 /* The 3rd parameter here is:
338 0 -> source range MPEG (i.e. "video", 16-235)
339 1 -> source range JPEG (i.e. "full", 0-255)
341 0 -> destination range MPEG (i.e. "video", 16-235)
342 1 -> destination range JPEG (i.e. "full", 0-255)
344 But remember: sws_setColorspaceDetails ignores these
345 parameters unless the corresponding image isYUV or isGray.
346 (If it's neither, it uses video range).
348 sws_setColorspaceDetails (
350 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
351 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
359 scaled->data(), scaled->stride()
362 sws_freeContext (scale_context);
367 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
369 Image::yuv_16_black (uint16_t v, bool alpha)
371 memset (data()[0], 0, sample_size(0).height * stride()[0]);
372 for (int i = 1; i < 3; ++i) {
373 auto p = reinterpret_cast<int16_t*> (data()[i]);
374 int const lines = sample_size(i).height;
375 for (int y = 0; y < lines; ++y) {
376 /* We divide by 2 here because we are writing 2 bytes at a time */
377 for (int x = 0; x < line_size()[i] / 2; ++x) {
380 p += stride()[i] / 2;
385 memset (data()[3], 0, sample_size(3).height * stride()[3]);
390 Image::swap_16 (uint16_t v)
392 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
396 Image::make_part_black (int const start, int const width)
398 auto y_part = [&]() {
399 int const bpp = bytes_per_pixel(0);
400 int const h = sample_size(0).height;
401 int const s = stride()[0];
403 for (int y = 0; y < h; ++y) {
404 memset (p + start * bpp, 0, width * bpp);
409 switch (_pixel_format) {
410 case AV_PIX_FMT_RGB24:
411 case AV_PIX_FMT_ARGB:
412 case AV_PIX_FMT_RGBA:
413 case AV_PIX_FMT_ABGR:
414 case AV_PIX_FMT_BGRA:
415 case AV_PIX_FMT_RGB555LE:
416 case AV_PIX_FMT_RGB48LE:
417 case AV_PIX_FMT_RGB48BE:
418 case AV_PIX_FMT_XYZ12LE:
420 int const h = sample_size(0).height;
421 int const bpp = bytes_per_pixel(0);
422 int const s = stride()[0];
423 uint8_t* p = data()[0];
424 for (int y = 0; y < h; y++) {
425 memset (p + start * bpp, 0, width * bpp);
430 case AV_PIX_FMT_YUV420P:
433 for (int i = 1; i < 3; ++i) {
435 int const h = sample_size(i).height;
436 for (int y = 0; y < h; ++y) {
437 for (int x = start / 2; x < (start + width) / 2; ++x) {
445 case AV_PIX_FMT_YUV422P10LE:
448 for (int i = 1; i < 3; ++i) {
449 auto p = reinterpret_cast<int16_t*>(data()[i]);
450 int const h = sample_size(i).height;
451 for (int y = 0; y < h; ++y) {
452 for (int x = start / 2; x < (start + width) / 2; ++x) {
455 p += stride()[i] / 2;
461 throw PixelFormatError ("make_part_black()", _pixel_format);
468 switch (_pixel_format) {
469 case AV_PIX_FMT_YUV420P:
470 case AV_PIX_FMT_YUV422P:
471 case AV_PIX_FMT_YUV444P:
472 case AV_PIX_FMT_YUV411P:
473 memset (data()[0], 0, sample_size(0).height * stride()[0]);
474 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
475 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
478 case AV_PIX_FMT_YUVJ420P:
479 case AV_PIX_FMT_YUVJ422P:
480 case AV_PIX_FMT_YUVJ444P:
481 memset (data()[0], 0, sample_size(0).height * stride()[0]);
482 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
483 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
486 case AV_PIX_FMT_YUV422P9LE:
487 case AV_PIX_FMT_YUV444P9LE:
488 yuv_16_black (nine_bit_uv, false);
491 case AV_PIX_FMT_YUV422P9BE:
492 case AV_PIX_FMT_YUV444P9BE:
493 yuv_16_black (swap_16 (nine_bit_uv), false);
496 case AV_PIX_FMT_YUV422P10LE:
497 case AV_PIX_FMT_YUV444P10LE:
498 yuv_16_black (ten_bit_uv, false);
501 case AV_PIX_FMT_YUV422P16LE:
502 case AV_PIX_FMT_YUV444P16LE:
503 yuv_16_black (sixteen_bit_uv, false);
506 case AV_PIX_FMT_YUV444P10BE:
507 case AV_PIX_FMT_YUV422P10BE:
508 yuv_16_black (swap_16 (ten_bit_uv), false);
511 case AV_PIX_FMT_YUVA420P9BE:
512 case AV_PIX_FMT_YUVA422P9BE:
513 case AV_PIX_FMT_YUVA444P9BE:
514 yuv_16_black (swap_16 (nine_bit_uv), true);
517 case AV_PIX_FMT_YUVA420P9LE:
518 case AV_PIX_FMT_YUVA422P9LE:
519 case AV_PIX_FMT_YUVA444P9LE:
520 yuv_16_black (nine_bit_uv, true);
523 case AV_PIX_FMT_YUVA420P10BE:
524 case AV_PIX_FMT_YUVA422P10BE:
525 case AV_PIX_FMT_YUVA444P10BE:
526 yuv_16_black (swap_16 (ten_bit_uv), true);
529 case AV_PIX_FMT_YUVA420P10LE:
530 case AV_PIX_FMT_YUVA422P10LE:
531 case AV_PIX_FMT_YUVA444P10LE:
532 yuv_16_black (ten_bit_uv, true);
535 case AV_PIX_FMT_YUVA420P16BE:
536 case AV_PIX_FMT_YUVA422P16BE:
537 case AV_PIX_FMT_YUVA444P16BE:
538 yuv_16_black (swap_16 (sixteen_bit_uv), true);
541 case AV_PIX_FMT_YUVA420P16LE:
542 case AV_PIX_FMT_YUVA422P16LE:
543 case AV_PIX_FMT_YUVA444P16LE:
544 yuv_16_black (sixteen_bit_uv, true);
547 case AV_PIX_FMT_RGB24:
548 case AV_PIX_FMT_ARGB:
549 case AV_PIX_FMT_RGBA:
550 case AV_PIX_FMT_ABGR:
551 case AV_PIX_FMT_BGRA:
552 case AV_PIX_FMT_RGB555LE:
553 case AV_PIX_FMT_RGB48LE:
554 case AV_PIX_FMT_RGB48BE:
555 case AV_PIX_FMT_XYZ12LE:
556 memset (data()[0], 0, sample_size(0).height * stride()[0]);
559 case AV_PIX_FMT_UYVY422:
561 int const Y = sample_size(0).height;
562 int const X = line_size()[0];
563 uint8_t* p = data()[0];
564 for (int y = 0; y < Y; ++y) {
565 for (int x = 0; x < X / 4; ++x) {
566 *p++ = eight_bit_uv; // Cb
568 *p++ = eight_bit_uv; // Cr
576 throw PixelFormatError ("make_black()", _pixel_format);
581 Image::make_transparent ()
583 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
584 throw PixelFormatError ("make_transparent()", _pixel_format);
587 memset (data()[0], 0, sample_size(0).height * stride()[0]);
591 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
593 /* We're blending RGBA or BGRA images */
594 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
595 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
596 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
598 int const other_bpp = 4;
600 int start_tx = position.x;
604 start_ox = -start_tx;
608 int start_ty = position.y;
612 start_oy = -start_ty;
616 switch (_pixel_format) {
617 case AV_PIX_FMT_RGB24:
619 /* Going onto RGB24. First byte is red, second green, third blue */
620 int const this_bpp = 3;
621 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
622 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
623 uint8_t* op = other->data()[0] + oy * other->stride()[0];
624 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
625 float const alpha = float (op[3]) / 255;
626 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
627 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
628 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
636 case AV_PIX_FMT_BGRA:
638 int const this_bpp = 4;
639 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
640 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
641 uint8_t* op = other->data()[0] + oy * other->stride()[0];
642 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
643 float const alpha = float (op[3]) / 255;
644 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
645 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
646 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
647 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
655 case AV_PIX_FMT_RGBA:
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[red] * alpha + tp[0] * (1 - alpha);
664 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
665 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
666 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
674 case AV_PIX_FMT_RGB48LE:
676 int const this_bpp = 6;
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 /* Blend high bytes */
683 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
684 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
685 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
693 case AV_PIX_FMT_XYZ12LE:
695 auto conv = dcp::ColourConversion::srgb_to_xyz();
696 double fast_matrix[9];
697 dcp::combined_rgb_to_xyz (conv, fast_matrix);
698 double const * lut_in = conv.in()->lut (8, false);
699 double const * lut_out = conv.out()->lut (16, true);
700 int const this_bpp = 6;
701 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
702 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
703 uint8_t* op = other->data()[0] + oy * other->stride()[0];
704 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
705 float const alpha = float (op[3]) / 255;
707 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
708 double const r = lut_in[op[red]];
709 double const g = lut_in[op[1]];
710 double const b = lut_in[op[blue]];
712 /* RGB to XYZ, including Bradford transform and DCI companding */
713 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
714 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
715 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
717 /* Out gamma LUT and blend */
718 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
719 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
720 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
728 case AV_PIX_FMT_YUV420P:
730 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
731 dcp::Size const ts = size();
732 dcp::Size const os = yuv->size();
733 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
734 int const hty = ty / 2;
735 int const hoy = oy / 2;
736 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
737 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
738 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
739 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
740 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
741 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
742 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
743 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
744 float const a = float(alpha[3]) / 255;
745 *tY = *oY * a + *tY * (1 - a);
746 *tU = *oU * a + *tU * (1 - a);
747 *tV = *oV * a + *tV * (1 - a);
763 case AV_PIX_FMT_YUV420P10:
765 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
766 dcp::Size const ts = size();
767 dcp::Size const os = yuv->size();
768 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
769 int const hty = ty / 2;
770 int const hoy = oy / 2;
771 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
772 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
773 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
774 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
775 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
776 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
777 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
778 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
779 float const a = float(alpha[3]) / 255;
780 *tY = *oY * a + *tY * (1 - a);
781 *tU = *oU * a + *tU * (1 - a);
782 *tV = *oV * a + *tV * (1 - a);
798 case AV_PIX_FMT_YUV422P10LE:
800 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
801 dcp::Size const ts = size();
802 dcp::Size const os = yuv->size();
803 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
804 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
805 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
806 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
807 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
808 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
809 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
810 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
811 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
812 float const a = float(alpha[3]) / 255;
813 *tY = *oY * a + *tY * (1 - a);
814 *tU = *oU * a + *tU * (1 - a);
815 *tV = *oV * a + *tV * (1 - a);
832 throw PixelFormatError ("alpha_blend()", _pixel_format);
837 Image::copy (shared_ptr<const Image> other, Position<int> position)
839 /* Only implemented for RGB24 onto RGB24 so far */
840 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
841 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
843 int const N = min (position.x + other->size().width, size().width) - position.x;
844 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
845 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
846 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
847 memcpy (tp, op, N * 3);
852 Image::read_from_socket (shared_ptr<Socket> socket)
854 for (int i = 0; i < planes(); ++i) {
855 uint8_t* p = data()[i];
856 int const lines = sample_size(i).height;
857 for (int y = 0; y < lines; ++y) {
858 socket->read (p, line_size()[i]);
865 Image::write_to_socket (shared_ptr<Socket> socket) const
867 for (int i = 0; i < planes(); ++i) {
868 uint8_t* p = data()[i];
869 int const lines = sample_size(i).height;
870 for (int y = 0; y < lines; ++y) {
871 socket->write (p, line_size()[i]);
878 Image::bytes_per_pixel (int c) const
880 auto d = av_pix_fmt_desc_get(_pixel_format);
882 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
889 float bpp[4] = { 0, 0, 0, 0 };
891 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
892 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
893 if (d->nb_components > 1) {
894 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
896 if (d->nb_components > 2) {
897 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
899 if (d->nb_components > 3) {
900 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
903 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
904 if (d->nb_components > 1) {
905 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
907 if (d->nb_components > 2) {
908 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
910 if (d->nb_components > 3) {
911 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
915 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
916 /* Not planar; sum them up */
917 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
923 /** Construct a Image of a given size and format, allocating memory
926 * @param p Pixel format.
927 * @param s Size in pixels.
928 * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
930 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
941 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
942 _data[0] = _data[1] = _data[2] = _data[3] = 0;
944 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
945 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
947 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
948 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
950 for (int i = 0; i < planes(); ++i) {
951 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
952 _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
954 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
955 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
956 Hence on the last pixel of the last line it reads over the end of
957 the actual data by 1 byte. If the width of an image is a multiple
958 of the stride alignment there will be no padding at the end of image lines.
959 OS X crashes on this illegal read, though other operating systems don't
960 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
961 for that instruction to read safely.
963 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
964 over-reads by more then _avx. I can't follow the code to work out how much,
965 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
966 testing suggests that it works.
968 In addition to these concerns, we may read/write as much as a whole extra line
969 at the end of each plane in cases where we are messing with offsets in order to
970 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
972 As an example: we may write to images starting at an offset so we get some padding.
973 Hence we want to write in the following pattern:
975 block start write start line end
976 |..(padding)..|<------line-size------------->|..(padding)..|
977 |..(padding)..|<------line-size------------->|..(padding)..|
978 |..(padding)..|<------line-size------------->|..(padding)..|
980 where line-size is of the smaller (inter_size) image and the full padded line length is that of
981 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
982 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
983 specified *stride*. This does not matter until we get to the last line:
985 block start write start line end
986 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
987 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
988 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
991 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
992 #if HAVE_VALGRIND_MEMCHECK_H
993 /* The data between the end of the line size and the stride is undefined but processed by
994 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
996 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1001 Image::Image (Image const & other)
1002 : std::enable_shared_from_this<Image>(other)
1003 , _size (other._size)
1004 , _pixel_format (other._pixel_format)
1005 , _aligned (other._aligned)
1009 for (int i = 0; i < planes(); ++i) {
1010 uint8_t* p = _data[i];
1011 uint8_t* q = other._data[i];
1012 int const lines = sample_size(i).height;
1013 for (int j = 0; j < lines; ++j) {
1014 memcpy (p, q, _line_size[i]);
1016 q += other.stride()[i];
1021 Image::Image (AVFrame const * frame)
1022 : _size (frame->width, frame->height)
1023 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1026 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1030 for (int i = 0; i < planes(); ++i) {
1031 uint8_t* p = _data[i];
1032 uint8_t* q = frame->data[i];
1033 int const lines = sample_size(i).height;
1034 for (int j = 0; j < lines; ++j) {
1035 memcpy (p, q, _line_size[i]);
1037 /* AVFrame's linesize is what we call `stride' */
1038 q += frame->linesize[i];
1043 Image::Image (shared_ptr<const Image> other, bool aligned)
1044 : _size (other->_size)
1045 , _pixel_format (other->_pixel_format)
1046 , _aligned (aligned)
1050 for (int i = 0; i < planes(); ++i) {
1051 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1052 uint8_t* p = _data[i];
1053 uint8_t* q = other->data()[i];
1054 int const lines = sample_size(i).height;
1055 for (int j = 0; j < lines; ++j) {
1056 memcpy (p, q, line_size()[i]);
1058 q += other->stride()[i];
1064 Image::operator= (Image const & other)
1066 if (this == &other) {
1076 Image::swap (Image & other)
1078 std::swap (_size, other._size);
1079 std::swap (_pixel_format, other._pixel_format);
1081 for (int i = 0; i < 4; ++i) {
1082 std::swap (_data[i], other._data[i]);
1083 std::swap (_line_size[i], other._line_size[i]);
1084 std::swap (_stride[i], other._stride[i]);
1087 std::swap (_aligned, other._aligned);
1092 for (int i = 0; i < planes(); ++i) {
1097 av_free (_line_size);
1102 Image::data () const
1108 Image::line_size () const
1114 Image::stride () const
1120 Image::size () const
1126 Image::aligned () const
1133 merge (list<PositionImage> images)
1135 if (images.empty ()) {
1139 if (images.size() == 1) {
1140 return images.front ();
1143 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1144 for (auto const& i: images) {
1145 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1148 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
1149 merged->make_transparent ();
1150 for (auto const& i: images) {
1151 merged->alpha_blend (i.image, i.position - all.position());
1154 return PositionImage (merged, all.position ());
1159 operator== (Image const & a, Image const & b)
1161 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1165 for (int c = 0; c < a.planes(); ++c) {
1166 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]) {
1170 uint8_t* p = a.data()[c];
1171 uint8_t* q = b.data()[c];
1172 int const lines = a.sample_size(c).height;
1173 for (int y = 0; y < lines; ++y) {
1174 if (memcmp (p, q, a.line_size()[c]) != 0) {
1187 * @param f Amount to fade by; 0 is black, 1 is no fade.
1190 Image::fade (float f)
1192 /* U/V black value for 8-bit colour */
1193 static int const eight_bit_uv = (1 << 7) - 1;
1194 /* U/V black value for 10-bit colour */
1195 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1197 switch (_pixel_format) {
1198 case AV_PIX_FMT_YUV420P:
1201 uint8_t* p = data()[0];
1202 int const lines = sample_size(0).height;
1203 for (int y = 0; y < lines; ++y) {
1205 for (int x = 0; x < line_size()[0]; ++x) {
1206 *q = int(float(*q) * f);
1213 for (int c = 1; c < 3; ++c) {
1214 uint8_t* p = data()[c];
1215 int const lines = sample_size(c).height;
1216 for (int y = 0; y < lines; ++y) {
1218 for (int x = 0; x < line_size()[c]; ++x) {
1219 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1229 case AV_PIX_FMT_RGB24:
1232 uint8_t* p = data()[0];
1233 int const lines = sample_size(0).height;
1234 for (int y = 0; y < lines; ++y) {
1236 for (int x = 0; x < line_size()[0]; ++x) {
1237 *q = int (float (*q) * f);
1245 case AV_PIX_FMT_XYZ12LE:
1246 case AV_PIX_FMT_RGB48LE:
1247 /* 16-bit little-endian */
1248 for (int c = 0; c < 3; ++c) {
1249 int const stride_pixels = stride()[c] / 2;
1250 int const line_size_pixels = line_size()[c] / 2;
1251 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1252 int const lines = sample_size(c).height;
1253 for (int y = 0; y < lines; ++y) {
1255 for (int x = 0; x < line_size_pixels; ++x) {
1256 *q = int (float (*q) * f);
1264 case AV_PIX_FMT_YUV422P10LE:
1268 int const stride_pixels = stride()[0] / 2;
1269 int const line_size_pixels = line_size()[0] / 2;
1270 uint16_t* p = reinterpret_cast<uint16_t*> (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_pixels; ++x) {
1275 *q = int(float(*q) * f);
1283 for (int c = 1; c < 3; ++c) {
1284 int const stride_pixels = stride()[c] / 2;
1285 int const line_size_pixels = line_size()[c] / 2;
1286 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1287 int const lines = sample_size(c).height;
1288 for (int y = 0; y < lines; ++y) {
1290 for (int x = 0; x < line_size_pixels; ++x) {
1291 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1302 throw PixelFormatError ("fade()", _pixel_format);
1306 shared_ptr<const Image>
1307 Image::ensure_aligned (shared_ptr<const Image> image)
1309 if (image->aligned()) {
1313 return make_shared<Image>(image, true);
1317 Image::memory_used () const
1320 for (int i = 0; i < planes(); ++i) {
1321 m += _stride[i] * sample_size(i).height;
1344 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1346 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1347 size_t size = mem->size + length;
1350 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1352 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1356 throw EncodeError (N_("could not allocate memory for PNG"));
1359 memcpy (mem->data + mem->size, data, length);
1360 mem->size += length;
1364 png_flush (png_structp)
1370 png_error_fn (png_structp png_ptr, char const * message)
1372 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1376 Image::png_error (char const * message)
1378 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1382 Image::as_png () const
1384 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1385 DCPOMATIC_ASSERT (planes() == 1);
1386 if (pixel_format() != AV_PIX_FMT_RGBA) {
1387 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1390 /* error handling? */
1391 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1393 throw EncodeError (N_("could not create PNG write struct"));
1398 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1400 png_infop info_ptr = png_create_info_struct(png_ptr);
1402 png_destroy_write_struct (&png_ptr, &info_ptr);
1403 throw EncodeError (N_("could not create PNG info struct"));
1406 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);
1408 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1409 for (int i = 0; i < size().height; ++i) {
1410 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1413 png_write_info (png_ptr, info_ptr);
1414 png_write_image (png_ptr, row_pointers);
1415 png_write_end (png_ptr, info_ptr);
1417 png_destroy_write_struct (&png_ptr, &info_ptr);
1418 png_free (png_ptr, row_pointers);
1420 return dcp::ArrayData (state.data, state.size);
1425 Image::video_range_to_full_range ()
1427 switch (_pixel_format) {
1428 case AV_PIX_FMT_RGB24:
1430 float const factor = 256.0 / 219.0;
1431 uint8_t* p = data()[0];
1432 int const lines = sample_size(0).height;
1433 for (int y = 0; y < lines; ++y) {
1435 for (int x = 0; x < line_size()[0]; ++x) {
1436 *q = int((*q - 16) * factor);
1443 case AV_PIX_FMT_GBRP12LE:
1445 float const factor = 4096.0 / 3504.0;
1446 for (int c = 0; c < 3; ++c) {
1447 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1448 int const lines = sample_size(c).height;
1449 for (int y = 0; y < lines; ++y) {
1451 int const line_size_pixels = line_size()[c] / 2;
1452 for (int x = 0; x < line_size_pixels; ++x) {
1453 *q = int((*q - 256) * factor);
1461 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);