2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 /** @file src/image.cc
23 * @brief A class to describe a video image.
27 #include "compose.hpp"
28 #include "dcpomatic_socket.h"
29 #include "exceptions.h"
34 #include <dcp/rgb_xyz.h>
35 #include <dcp/transfer_function.h>
37 #include <libavutil/frame.h>
38 #include <libavutil/pixdesc.h>
39 #include <libavutil/pixfmt.h>
40 #include <libswscale/swscale.h>
43 #if HAVE_VALGRIND_MEMCHECK_H
44 #include <valgrind/memcheck.h>
55 using std::make_shared;
58 using std::runtime_error;
59 using std::shared_ptr;
64 /** The memory alignment, in bytes, used for each row of an image if aligment is requested */
69 Image::vertical_factor (int n) const
75 auto d = av_pix_fmt_desc_get(_pixel_format);
77 throw PixelFormatError ("line_factor()", _pixel_format);
80 return lrintf(powf(2.0f, d->log2_chroma_h));
84 Image::horizontal_factor (int n) const
90 auto d = av_pix_fmt_desc_get(_pixel_format);
92 throw PixelFormatError ("sample_size()", _pixel_format);
95 return lrintf(powf(2.0f, d->log2_chroma_w));
98 /** @param n Component index.
99 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
102 Image::sample_size (int n) const
105 lrint (ceil(static_cast<double>(size().width) / horizontal_factor (n))),
106 lrint (ceil(static_cast<double>(size().height) / vertical_factor (n)))
110 /** @return Number of planes */
112 Image::planes () const
114 auto d = av_pix_fmt_desc_get(_pixel_format);
116 throw PixelFormatError ("planes()", _pixel_format);
119 if (_pixel_format == AV_PIX_FMT_PAL8) {
123 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
127 return d->nb_components;
133 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
135 return p & ~ ((1 << desc->log2_chroma_w) - 1);
141 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
143 return p & ~ ((1 << desc->log2_chroma_h) - 1);
147 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
148 * @param crop Amount to crop by.
149 * @param inter_size Size to scale the cropped image to.
150 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
151 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
152 * @param video_range Video range of the image.
153 * @param out_format Output pixel format.
154 * @param out_aligned true to make the output image aligned.
155 * @param out_video_range Video range to use for the output image.
156 * @param fast Try to be fast at the possible expense of quality; at present this means using
157 * fast bilinear rather than bicubic scaling.
160 Image::crop_scale_window (
162 dcp::Size inter_size,
164 dcp::YUVToRGB yuv_to_rgb,
165 VideoRange video_range,
166 AVPixelFormat out_format,
167 VideoRange out_video_range,
172 /* Empirical testing suggests that sws_scale() will crash if
173 the input image is not aligned.
175 DCPOMATIC_ASSERT (aligned ());
177 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
178 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
180 auto out = make_shared<Image>(out_format, out_size, out_aligned);
183 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
185 throw PixelFormatError ("crop_scale_window()", _pixel_format);
188 /* Round down so that we crop only the number of pixels that is straightforward
189 * considering any subsampling.
192 round_width_for_subsampling(crop.left, in_desc),
193 round_width_for_subsampling(crop.right, in_desc),
194 round_height_for_subsampling(crop.top, in_desc),
195 round_height_for_subsampling(crop.bottom, in_desc)
198 /* Also check that we aren't cropping more image than there actually is */
199 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
200 corrected_crop.left = 0;
201 corrected_crop.right = size().width - 4;
204 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
205 corrected_crop.top = 0;
206 corrected_crop.bottom = size().height - 4;
209 /* Size of the image after any crop */
210 auto const cropped_size = corrected_crop.apply (size());
212 /* Scale context for a scale from cropped_size to inter_size */
213 auto scale_context = sws_getContext (
214 cropped_size.width, cropped_size.height, pixel_format(),
215 inter_size.width, inter_size.height, out_format,
216 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
219 if (!scale_context) {
220 throw runtime_error (N_("Could not allocate SwsContext"));
223 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
224 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
229 /* The 3rd parameter here is:
230 0 -> source range MPEG (i.e. "video", 16-235)
231 1 -> source range JPEG (i.e. "full", 0-255)
233 0 -> destination range MPEG (i.e. "video", 16-235)
234 1 -> destination range JPEG (i.e. "full", 0-255)
236 But remember: sws_setColorspaceDetails ignores these
237 parameters unless the both source and destination images
238 are isYUV or isGray. (If either is not, it uses video range).
240 sws_setColorspaceDetails (
242 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
243 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
247 /* Prepare input data pointers with crop */
248 uint8_t* scale_in_data[planes()];
249 for (int c = 0; c < planes(); ++c) {
250 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
251 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
254 auto out_desc = av_pix_fmt_desc_get (out_format);
256 throw PixelFormatError ("crop_scale_window()", out_format);
259 /* Corner of the image within out_size */
260 Position<int> const corner (
261 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
262 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
265 uint8_t* scale_out_data[out->planes()];
266 for (int c = 0; c < out->planes(); ++c) {
267 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
268 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
273 scale_in_data, stride(),
274 0, cropped_size.height,
275 scale_out_data, out->stride()
278 sws_freeContext (scale_context);
280 if (corrected_crop != Crop() && cropped_size == inter_size) {
281 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
282 data behind in our image. Clear it out. It may get to the point where we should just stop
283 trying to be clever with cropping.
285 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
292 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
294 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
297 /** @param out_size Size to scale to.
298 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
299 * @param out_format Output pixel format.
300 * @param out_aligned true to make an aligned output image.
301 * @param fast Try to be fast at the possible expense of quality; at present this means using
302 * fast bilinear rather than bicubic scaling.
305 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
307 /* Empirical testing suggests that sws_scale() will crash if
308 the input image is not aligned.
310 DCPOMATIC_ASSERT (aligned ());
312 auto scaled = make_shared<Image>(out_format, out_size, out_aligned);
313 auto scale_context = sws_getContext (
314 size().width, size().height, pixel_format(),
315 out_size.width, out_size.height, out_format,
316 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
319 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
320 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
325 /* The 3rd parameter here is:
326 0 -> source range MPEG (i.e. "video", 16-235)
327 1 -> source range JPEG (i.e. "full", 0-255)
329 0 -> destination range MPEG (i.e. "video", 16-235)
330 1 -> destination range JPEG (i.e. "full", 0-255)
332 But remember: sws_setColorspaceDetails ignores these
333 parameters unless the corresponding image isYUV or isGray.
334 (If it's neither, it uses video range).
336 sws_setColorspaceDetails (
338 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
339 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
347 scaled->data(), scaled->stride()
350 sws_freeContext (scale_context);
355 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
357 Image::yuv_16_black (uint16_t v, bool alpha)
359 memset (data()[0], 0, sample_size(0).height * stride()[0]);
360 for (int i = 1; i < 3; ++i) {
361 auto p = reinterpret_cast<int16_t*> (data()[i]);
362 int const lines = sample_size(i).height;
363 for (int y = 0; y < lines; ++y) {
364 /* We divide by 2 here because we are writing 2 bytes at a time */
365 for (int x = 0; x < line_size()[i] / 2; ++x) {
368 p += stride()[i] / 2;
373 memset (data()[3], 0, sample_size(3).height * stride()[3]);
378 Image::swap_16 (uint16_t v)
380 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
384 Image::make_part_black (int x, int w)
386 switch (_pixel_format) {
387 case AV_PIX_FMT_RGB24:
388 case AV_PIX_FMT_ARGB:
389 case AV_PIX_FMT_RGBA:
390 case AV_PIX_FMT_ABGR:
391 case AV_PIX_FMT_BGRA:
392 case AV_PIX_FMT_RGB555LE:
393 case AV_PIX_FMT_RGB48LE:
394 case AV_PIX_FMT_RGB48BE:
395 case AV_PIX_FMT_XYZ12LE:
397 int const h = sample_size(0).height;
398 int const bpp = bytes_per_pixel(0);
399 int const s = stride()[0];
400 uint8_t* p = data()[0];
401 for (int y = 0; y < h; y++) {
402 memset (p + x * bpp, 0, w * bpp);
409 throw PixelFormatError ("make_part_black()", _pixel_format);
416 /* U/V black value for 8-bit colour */
417 static uint8_t const eight_bit_uv = (1 << 7) - 1;
418 /* U/V black value for 9-bit colour */
419 static uint16_t const nine_bit_uv = (1 << 8) - 1;
420 /* U/V black value for 10-bit colour */
421 static uint16_t const ten_bit_uv = (1 << 9) - 1;
422 /* U/V black value for 16-bit colour */
423 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
425 switch (_pixel_format) {
426 case AV_PIX_FMT_YUV420P:
427 case AV_PIX_FMT_YUV422P:
428 case AV_PIX_FMT_YUV444P:
429 case AV_PIX_FMT_YUV411P:
430 memset (data()[0], 0, sample_size(0).height * stride()[0]);
431 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
432 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
435 case AV_PIX_FMT_YUVJ420P:
436 case AV_PIX_FMT_YUVJ422P:
437 case AV_PIX_FMT_YUVJ444P:
438 memset (data()[0], 0, sample_size(0).height * stride()[0]);
439 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
440 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
443 case AV_PIX_FMT_YUV422P9LE:
444 case AV_PIX_FMT_YUV444P9LE:
445 yuv_16_black (nine_bit_uv, false);
448 case AV_PIX_FMT_YUV422P9BE:
449 case AV_PIX_FMT_YUV444P9BE:
450 yuv_16_black (swap_16 (nine_bit_uv), false);
453 case AV_PIX_FMT_YUV422P10LE:
454 case AV_PIX_FMT_YUV444P10LE:
455 yuv_16_black (ten_bit_uv, false);
458 case AV_PIX_FMT_YUV422P16LE:
459 case AV_PIX_FMT_YUV444P16LE:
460 yuv_16_black (sixteen_bit_uv, false);
463 case AV_PIX_FMT_YUV444P10BE:
464 case AV_PIX_FMT_YUV422P10BE:
465 yuv_16_black (swap_16 (ten_bit_uv), false);
468 case AV_PIX_FMT_YUVA420P9BE:
469 case AV_PIX_FMT_YUVA422P9BE:
470 case AV_PIX_FMT_YUVA444P9BE:
471 yuv_16_black (swap_16 (nine_bit_uv), true);
474 case AV_PIX_FMT_YUVA420P9LE:
475 case AV_PIX_FMT_YUVA422P9LE:
476 case AV_PIX_FMT_YUVA444P9LE:
477 yuv_16_black (nine_bit_uv, true);
480 case AV_PIX_FMT_YUVA420P10BE:
481 case AV_PIX_FMT_YUVA422P10BE:
482 case AV_PIX_FMT_YUVA444P10BE:
483 yuv_16_black (swap_16 (ten_bit_uv), true);
486 case AV_PIX_FMT_YUVA420P10LE:
487 case AV_PIX_FMT_YUVA422P10LE:
488 case AV_PIX_FMT_YUVA444P10LE:
489 yuv_16_black (ten_bit_uv, true);
492 case AV_PIX_FMT_YUVA420P16BE:
493 case AV_PIX_FMT_YUVA422P16BE:
494 case AV_PIX_FMT_YUVA444P16BE:
495 yuv_16_black (swap_16 (sixteen_bit_uv), true);
498 case AV_PIX_FMT_YUVA420P16LE:
499 case AV_PIX_FMT_YUVA422P16LE:
500 case AV_PIX_FMT_YUVA444P16LE:
501 yuv_16_black (sixteen_bit_uv, true);
504 case AV_PIX_FMT_RGB24:
505 case AV_PIX_FMT_ARGB:
506 case AV_PIX_FMT_RGBA:
507 case AV_PIX_FMT_ABGR:
508 case AV_PIX_FMT_BGRA:
509 case AV_PIX_FMT_RGB555LE:
510 case AV_PIX_FMT_RGB48LE:
511 case AV_PIX_FMT_RGB48BE:
512 case AV_PIX_FMT_XYZ12LE:
513 memset (data()[0], 0, sample_size(0).height * stride()[0]);
516 case AV_PIX_FMT_UYVY422:
518 int const Y = sample_size(0).height;
519 int const X = line_size()[0];
520 uint8_t* p = data()[0];
521 for (int y = 0; y < Y; ++y) {
522 for (int x = 0; x < X / 4; ++x) {
523 *p++ = eight_bit_uv; // Cb
525 *p++ = eight_bit_uv; // Cr
533 throw PixelFormatError ("make_black()", _pixel_format);
538 Image::make_transparent ()
540 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
541 throw PixelFormatError ("make_transparent()", _pixel_format);
544 memset (data()[0], 0, sample_size(0).height * stride()[0]);
548 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
550 /* We're blending RGBA or BGRA images */
551 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
552 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
553 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
555 int const other_bpp = 4;
557 int start_tx = position.x;
561 start_ox = -start_tx;
565 int start_ty = position.y;
569 start_oy = -start_ty;
573 switch (_pixel_format) {
574 case AV_PIX_FMT_RGB24:
576 /* Going onto RGB24. First byte is red, second green, third blue */
577 int const this_bpp = 3;
578 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
579 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
580 uint8_t* op = other->data()[0] + oy * other->stride()[0];
581 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
582 float const alpha = float (op[3]) / 255;
583 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
584 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
585 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
593 case AV_PIX_FMT_BGRA:
595 int const this_bpp = 4;
596 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
597 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
598 uint8_t* op = other->data()[0] + oy * other->stride()[0];
599 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
600 float const alpha = float (op[3]) / 255;
601 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
602 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
603 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
604 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
612 case AV_PIX_FMT_RGBA:
614 int const this_bpp = 4;
615 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
616 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
617 uint8_t* op = other->data()[0] + oy * other->stride()[0];
618 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
619 float const alpha = float (op[3]) / 255;
620 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
621 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
622 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
623 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
631 case AV_PIX_FMT_RGB48LE:
633 int const this_bpp = 6;
634 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
635 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
636 uint8_t* op = other->data()[0] + oy * other->stride()[0];
637 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
638 float const alpha = float (op[3]) / 255;
639 /* Blend high bytes */
640 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
641 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
642 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
650 case AV_PIX_FMT_XYZ12LE:
652 auto conv = dcp::ColourConversion::srgb_to_xyz();
653 double fast_matrix[9];
654 dcp::combined_rgb_to_xyz (conv, fast_matrix);
655 double const * lut_in = conv.in()->lut (8, false);
656 double const * lut_out = conv.out()->lut (16, true);
657 int const this_bpp = 6;
658 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
659 uint16_t* tp = reinterpret_cast<uint16_t*> (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;
664 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
665 double const r = lut_in[op[red]];
666 double const g = lut_in[op[1]];
667 double const b = lut_in[op[blue]];
669 /* RGB to XYZ, including Bradford transform and DCI companding */
670 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
671 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
672 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
674 /* Out gamma LUT and blend */
675 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
676 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
677 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
685 case AV_PIX_FMT_YUV420P:
687 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
688 dcp::Size const ts = size();
689 dcp::Size const os = yuv->size();
690 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
691 int const hty = ty / 2;
692 int const hoy = oy / 2;
693 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
694 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
695 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
696 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
697 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
698 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
699 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
700 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
701 float const a = float(alpha[3]) / 255;
702 *tY = *oY * a + *tY * (1 - a);
703 *tU = *oU * a + *tU * (1 - a);
704 *tV = *oV * a + *tV * (1 - a);
720 case AV_PIX_FMT_YUV420P10:
722 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
723 dcp::Size const ts = size();
724 dcp::Size const os = yuv->size();
725 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
726 int const hty = ty / 2;
727 int const hoy = oy / 2;
728 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
729 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
730 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
731 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
732 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
733 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
734 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
735 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
736 float const a = float(alpha[3]) / 255;
737 *tY = *oY * a + *tY * (1 - a);
738 *tU = *oU * a + *tU * (1 - a);
739 *tV = *oV * a + *tV * (1 - a);
755 case AV_PIX_FMT_YUV422P10LE:
757 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
758 dcp::Size const ts = size();
759 dcp::Size const os = yuv->size();
760 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
761 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
762 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
763 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
764 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
765 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
766 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
767 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
768 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
769 float const a = float(alpha[3]) / 255;
770 *tY = *oY * a + *tY * (1 - a);
771 *tU = *oU * a + *tU * (1 - a);
772 *tV = *oV * a + *tV * (1 - a);
789 throw PixelFormatError ("alpha_blend()", _pixel_format);
794 Image::copy (shared_ptr<const Image> other, Position<int> position)
796 /* Only implemented for RGB24 onto RGB24 so far */
797 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
798 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
800 int const N = min (position.x + other->size().width, size().width) - position.x;
801 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
802 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
803 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
804 memcpy (tp, op, N * 3);
809 Image::read_from_socket (shared_ptr<Socket> socket)
811 for (int i = 0; i < planes(); ++i) {
812 uint8_t* p = data()[i];
813 int const lines = sample_size(i).height;
814 for (int y = 0; y < lines; ++y) {
815 socket->read (p, line_size()[i]);
822 Image::write_to_socket (shared_ptr<Socket> socket) const
824 for (int i = 0; i < planes(); ++i) {
825 uint8_t* p = data()[i];
826 int const lines = sample_size(i).height;
827 for (int y = 0; y < lines; ++y) {
828 socket->write (p, line_size()[i]);
835 Image::bytes_per_pixel (int c) const
837 auto d = av_pix_fmt_desc_get(_pixel_format);
839 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
846 float bpp[4] = { 0, 0, 0, 0 };
848 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
849 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
850 if (d->nb_components > 1) {
851 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
853 if (d->nb_components > 2) {
854 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
856 if (d->nb_components > 3) {
857 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
860 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
861 if (d->nb_components > 1) {
862 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
864 if (d->nb_components > 2) {
865 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
867 if (d->nb_components > 3) {
868 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
872 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
873 /* Not planar; sum them up */
874 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
880 /** Construct a Image of a given size and format, allocating memory
883 * @param p Pixel format.
884 * @param s Size in pixels.
885 * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
887 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
898 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
899 _data[0] = _data[1] = _data[2] = _data[3] = 0;
901 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
902 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
904 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
905 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
907 for (int i = 0; i < planes(); ++i) {
908 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
909 _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
911 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
912 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
913 Hence on the last pixel of the last line it reads over the end of
914 the actual data by 1 byte. If the width of an image is a multiple
915 of the stride alignment there will be no padding at the end of image lines.
916 OS X crashes on this illegal read, though other operating systems don't
917 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
918 for that instruction to read safely.
920 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
921 over-reads by more then _avx. I can't follow the code to work out how much,
922 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
923 testing suggests that it works.
925 In addition to these concerns, we may read/write as much as a whole extra line
926 at the end of each plane in cases where we are messing with offsets in order to
927 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
929 As an example: we may write to images starting at an offset so we get some padding.
930 Hence we want to write in the following pattern:
932 block start write start line end
933 |..(padding)..|<------line-size------------->|..(padding)..|
934 |..(padding)..|<------line-size------------->|..(padding)..|
935 |..(padding)..|<------line-size------------->|..(padding)..|
937 where line-size is of the smaller (inter_size) image and the full padded line length is that of
938 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
939 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
940 specified *stride*. This does not matter until we get to the last line:
942 block start write start line end
943 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
944 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
945 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
948 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
949 #if HAVE_VALGRIND_MEMCHECK_H
950 /* The data between the end of the line size and the stride is undefined but processed by
951 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
953 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
958 Image::Image (Image const & other)
959 : std::enable_shared_from_this<Image>(other)
960 , _size (other._size)
961 , _pixel_format (other._pixel_format)
962 , _aligned (other._aligned)
966 for (int i = 0; i < planes(); ++i) {
967 uint8_t* p = _data[i];
968 uint8_t* q = other._data[i];
969 int const lines = sample_size(i).height;
970 for (int j = 0; j < lines; ++j) {
971 memcpy (p, q, _line_size[i]);
973 q += other.stride()[i];
978 Image::Image (AVFrame* frame)
979 : _size (frame->width, frame->height)
980 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
983 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
987 for (int i = 0; i < planes(); ++i) {
988 uint8_t* p = _data[i];
989 uint8_t* q = frame->data[i];
990 int const lines = sample_size(i).height;
991 for (int j = 0; j < lines; ++j) {
992 memcpy (p, q, _line_size[i]);
994 /* AVFrame's linesize is what we call `stride' */
995 q += frame->linesize[i];
1000 Image::Image (shared_ptr<const Image> other, bool aligned)
1001 : _size (other->_size)
1002 , _pixel_format (other->_pixel_format)
1003 , _aligned (aligned)
1007 for (int i = 0; i < planes(); ++i) {
1008 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1009 uint8_t* p = _data[i];
1010 uint8_t* q = other->data()[i];
1011 int const lines = sample_size(i).height;
1012 for (int j = 0; j < lines; ++j) {
1013 memcpy (p, q, line_size()[i]);
1015 q += other->stride()[i];
1021 Image::operator= (Image const & other)
1023 if (this == &other) {
1033 Image::swap (Image & other)
1035 std::swap (_size, other._size);
1036 std::swap (_pixel_format, other._pixel_format);
1038 for (int i = 0; i < 4; ++i) {
1039 std::swap (_data[i], other._data[i]);
1040 std::swap (_line_size[i], other._line_size[i]);
1041 std::swap (_stride[i], other._stride[i]);
1044 std::swap (_aligned, other._aligned);
1049 for (int i = 0; i < planes(); ++i) {
1054 av_free (_line_size);
1059 Image::data () const
1065 Image::line_size () const
1071 Image::stride () const
1077 Image::size () const
1083 Image::aligned () const
1090 merge (list<PositionImage> images)
1092 if (images.empty ()) {
1096 if (images.size() == 1) {
1097 return images.front ();
1100 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1101 for (auto const& i: images) {
1102 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1105 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
1106 merged->make_transparent ();
1107 for (auto const& i: images) {
1108 merged->alpha_blend (i.image, i.position - all.position());
1111 return PositionImage (merged, all.position ());
1116 operator== (Image const & a, Image const & b)
1118 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1122 for (int c = 0; c < a.planes(); ++c) {
1123 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]) {
1127 uint8_t* p = a.data()[c];
1128 uint8_t* q = b.data()[c];
1129 int const lines = a.sample_size(c).height;
1130 for (int y = 0; y < lines; ++y) {
1131 if (memcmp (p, q, a.line_size()[c]) != 0) {
1144 * @param f Amount to fade by; 0 is black, 1 is no fade.
1147 Image::fade (float f)
1149 /* U/V black value for 8-bit colour */
1150 static int const eight_bit_uv = (1 << 7) - 1;
1151 /* U/V black value for 10-bit colour */
1152 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1154 switch (_pixel_format) {
1155 case AV_PIX_FMT_YUV420P:
1158 uint8_t* p = data()[0];
1159 int const lines = sample_size(0).height;
1160 for (int y = 0; y < lines; ++y) {
1162 for (int x = 0; x < line_size()[0]; ++x) {
1163 *q = int(float(*q) * f);
1170 for (int c = 1; c < 3; ++c) {
1171 uint8_t* p = data()[c];
1172 int const lines = sample_size(c).height;
1173 for (int y = 0; y < lines; ++y) {
1175 for (int x = 0; x < line_size()[c]; ++x) {
1176 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1186 case AV_PIX_FMT_RGB24:
1189 uint8_t* p = data()[0];
1190 int const lines = sample_size(0).height;
1191 for (int y = 0; y < lines; ++y) {
1193 for (int x = 0; x < line_size()[0]; ++x) {
1194 *q = int (float (*q) * f);
1202 case AV_PIX_FMT_XYZ12LE:
1203 case AV_PIX_FMT_RGB48LE:
1204 /* 16-bit little-endian */
1205 for (int c = 0; c < 3; ++c) {
1206 int const stride_pixels = stride()[c] / 2;
1207 int const line_size_pixels = line_size()[c] / 2;
1208 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1209 int const lines = sample_size(c).height;
1210 for (int y = 0; y < lines; ++y) {
1212 for (int x = 0; x < line_size_pixels; ++x) {
1213 *q = int (float (*q) * f);
1221 case AV_PIX_FMT_YUV422P10LE:
1225 int const stride_pixels = stride()[0] / 2;
1226 int const line_size_pixels = line_size()[0] / 2;
1227 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1228 int const lines = sample_size(0).height;
1229 for (int y = 0; y < lines; ++y) {
1231 for (int x = 0; x < line_size_pixels; ++x) {
1232 *q = int(float(*q) * f);
1240 for (int c = 1; c < 3; ++c) {
1241 int const stride_pixels = stride()[c] / 2;
1242 int const line_size_pixels = line_size()[c] / 2;
1243 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1244 int const lines = sample_size(c).height;
1245 for (int y = 0; y < lines; ++y) {
1247 for (int x = 0; x < line_size_pixels; ++x) {
1248 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1259 throw PixelFormatError ("fade()", _pixel_format);
1263 shared_ptr<const Image>
1264 Image::ensure_aligned (shared_ptr<const Image> image)
1266 if (image->aligned()) {
1270 return make_shared<Image>(image, true);
1274 Image::memory_used () const
1277 for (int i = 0; i < planes(); ++i) {
1278 m += _stride[i] * sample_size(i).height;
1301 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1303 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1304 size_t size = mem->size + length;
1307 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1309 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1313 throw EncodeError (N_("could not allocate memory for PNG"));
1316 memcpy (mem->data + mem->size, data, length);
1317 mem->size += length;
1321 png_flush (png_structp)
1327 png_error_fn (png_structp png_ptr, char const * message)
1329 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1333 Image::png_error (char const * message)
1335 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1339 Image::as_png () const
1341 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1342 DCPOMATIC_ASSERT (planes() == 1);
1343 if (pixel_format() != AV_PIX_FMT_RGBA) {
1344 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1347 /* error handling? */
1348 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1350 throw EncodeError (N_("could not create PNG write struct"));
1355 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1357 png_infop info_ptr = png_create_info_struct(png_ptr);
1359 png_destroy_write_struct (&png_ptr, &info_ptr);
1360 throw EncodeError (N_("could not create PNG info struct"));
1363 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);
1365 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1366 for (int i = 0; i < size().height; ++i) {
1367 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1370 png_write_info (png_ptr, info_ptr);
1371 png_write_image (png_ptr, row_pointers);
1372 png_write_end (png_ptr, info_ptr);
1374 png_destroy_write_struct (&png_ptr, &info_ptr);
1375 png_free (png_ptr, row_pointers);
1377 return dcp::ArrayData (state.data, state.size);
1382 Image::video_range_to_full_range ()
1384 switch (_pixel_format) {
1385 case AV_PIX_FMT_RGB24:
1387 float const factor = 256.0 / 219.0;
1388 uint8_t* p = data()[0];
1389 int const lines = sample_size(0).height;
1390 for (int y = 0; y < lines; ++y) {
1392 for (int x = 0; x < line_size()[0]; ++x) {
1393 *q = int((*q - 16) * factor);
1400 case AV_PIX_FMT_GBRP12LE:
1402 float const factor = 4096.0 / 3504.0;
1403 for (int c = 0; c < 3; ++c) {
1404 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1405 int const lines = sample_size(c).height;
1406 for (int y = 0; y < lines; ++y) {
1408 int const line_size_pixels = line_size()[c] / 2;
1409 for (int x = 0; x < line_size_pixels; ++x) {
1410 *q = int((*q - 256) * factor);
1418 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);