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))
985 for (int i = 0; i < planes(); ++i) {
986 uint8_t* p = _data[i];
987 uint8_t* q = frame->data[i];
988 int const lines = sample_size(i).height;
989 for (int j = 0; j < lines; ++j) {
990 memcpy (p, q, _line_size[i]);
992 /* AVFrame's linesize is what we call `stride' */
993 q += frame->linesize[i];
998 Image::Image (shared_ptr<const Image> other, bool aligned)
999 : _size (other->_size)
1000 , _pixel_format (other->_pixel_format)
1001 , _aligned (aligned)
1005 for (int i = 0; i < planes(); ++i) {
1006 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1007 uint8_t* p = _data[i];
1008 uint8_t* q = other->data()[i];
1009 int const lines = sample_size(i).height;
1010 for (int j = 0; j < lines; ++j) {
1011 memcpy (p, q, line_size()[i]);
1013 q += other->stride()[i];
1019 Image::operator= (Image const & other)
1021 if (this == &other) {
1031 Image::swap (Image & other)
1033 std::swap (_size, other._size);
1034 std::swap (_pixel_format, other._pixel_format);
1036 for (int i = 0; i < 4; ++i) {
1037 std::swap (_data[i], other._data[i]);
1038 std::swap (_line_size[i], other._line_size[i]);
1039 std::swap (_stride[i], other._stride[i]);
1042 std::swap (_aligned, other._aligned);
1047 for (int i = 0; i < planes(); ++i) {
1052 av_free (_line_size);
1057 Image::data () const
1063 Image::line_size () const
1069 Image::stride () const
1075 Image::size () const
1081 Image::aligned () const
1088 merge (list<PositionImage> images)
1090 if (images.empty ()) {
1094 if (images.size() == 1) {
1095 return images.front ();
1098 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1099 for (auto const& i: images) {
1100 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1103 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
1104 merged->make_transparent ();
1105 for (auto const& i: images) {
1106 merged->alpha_blend (i.image, i.position - all.position());
1109 return PositionImage (merged, all.position ());
1114 operator== (Image const & a, Image const & b)
1116 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1120 for (int c = 0; c < a.planes(); ++c) {
1121 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]) {
1125 uint8_t* p = a.data()[c];
1126 uint8_t* q = b.data()[c];
1127 int const lines = a.sample_size(c).height;
1128 for (int y = 0; y < lines; ++y) {
1129 if (memcmp (p, q, a.line_size()[c]) != 0) {
1142 * @param f Amount to fade by; 0 is black, 1 is no fade.
1145 Image::fade (float f)
1147 /* U/V black value for 8-bit colour */
1148 static int const eight_bit_uv = (1 << 7) - 1;
1149 /* U/V black value for 10-bit colour */
1150 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1152 switch (_pixel_format) {
1153 case AV_PIX_FMT_YUV420P:
1156 uint8_t* p = data()[0];
1157 int const lines = sample_size(0).height;
1158 for (int y = 0; y < lines; ++y) {
1160 for (int x = 0; x < line_size()[0]; ++x) {
1161 *q = int(float(*q) * f);
1168 for (int c = 1; c < 3; ++c) {
1169 uint8_t* p = data()[c];
1170 int const lines = sample_size(c).height;
1171 for (int y = 0; y < lines; ++y) {
1173 for (int x = 0; x < line_size()[c]; ++x) {
1174 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1184 case AV_PIX_FMT_RGB24:
1187 uint8_t* p = data()[0];
1188 int const lines = sample_size(0).height;
1189 for (int y = 0; y < lines; ++y) {
1191 for (int x = 0; x < line_size()[0]; ++x) {
1192 *q = int (float (*q) * f);
1200 case AV_PIX_FMT_XYZ12LE:
1201 case AV_PIX_FMT_RGB48LE:
1202 /* 16-bit little-endian */
1203 for (int c = 0; c < 3; ++c) {
1204 int const stride_pixels = stride()[c] / 2;
1205 int const line_size_pixels = line_size()[c] / 2;
1206 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1207 int const lines = sample_size(c).height;
1208 for (int y = 0; y < lines; ++y) {
1210 for (int x = 0; x < line_size_pixels; ++x) {
1211 *q = int (float (*q) * f);
1219 case AV_PIX_FMT_YUV422P10LE:
1223 int const stride_pixels = stride()[0] / 2;
1224 int const line_size_pixels = line_size()[0] / 2;
1225 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1226 int const lines = sample_size(0).height;
1227 for (int y = 0; y < lines; ++y) {
1229 for (int x = 0; x < line_size_pixels; ++x) {
1230 *q = int(float(*q) * f);
1238 for (int c = 1; c < 3; ++c) {
1239 int const stride_pixels = stride()[c] / 2;
1240 int const line_size_pixels = line_size()[c] / 2;
1241 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1242 int const lines = sample_size(c).height;
1243 for (int y = 0; y < lines; ++y) {
1245 for (int x = 0; x < line_size_pixels; ++x) {
1246 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1257 throw PixelFormatError ("fade()", _pixel_format);
1261 shared_ptr<const Image>
1262 Image::ensure_aligned (shared_ptr<const Image> image)
1264 if (image->aligned()) {
1268 return make_shared<Image>(image, true);
1272 Image::memory_used () const
1275 for (int i = 0; i < planes(); ++i) {
1276 m += _stride[i] * sample_size(i).height;
1299 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1301 auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1302 size_t size = mem->size + length;
1305 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1307 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1311 throw EncodeError (N_("could not allocate memory for PNG"));
1314 memcpy (mem->data + mem->size, data, length);
1315 mem->size += length;
1319 png_flush (png_structp)
1325 png_error_fn (png_structp png_ptr, char const * message)
1327 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1331 Image::png_error (char const * message)
1333 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1337 Image::as_png () const
1339 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1340 DCPOMATIC_ASSERT (planes() == 1);
1341 if (pixel_format() != AV_PIX_FMT_RGBA) {
1342 return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1345 /* error handling? */
1346 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1348 throw EncodeError (N_("could not create PNG write struct"));
1353 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1355 png_infop info_ptr = png_create_info_struct(png_ptr);
1357 png_destroy_write_struct (&png_ptr, &info_ptr);
1358 throw EncodeError (N_("could not create PNG info struct"));
1361 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);
1363 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1364 for (int i = 0; i < size().height; ++i) {
1365 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1368 png_write_info (png_ptr, info_ptr);
1369 png_write_image (png_ptr, row_pointers);
1370 png_write_end (png_ptr, info_ptr);
1372 png_destroy_write_struct (&png_ptr, &info_ptr);
1373 png_free (png_ptr, row_pointers);
1375 return dcp::ArrayData (state.data, state.size);
1380 Image::video_range_to_full_range ()
1382 switch (_pixel_format) {
1383 case AV_PIX_FMT_RGB24:
1385 float const factor = 256.0 / 219.0;
1386 uint8_t* p = data()[0];
1387 int const lines = sample_size(0).height;
1388 for (int y = 0; y < lines; ++y) {
1390 for (int x = 0; x < line_size()[0]; ++x) {
1391 *q = int((*q - 16) * factor);
1398 case AV_PIX_FMT_GBRP12LE:
1400 float const factor = 4096.0 / 3504.0;
1401 for (int c = 0; c < 3; ++c) {
1402 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1403 int const lines = sample_size(c).height;
1404 for (int y = 0; y < lines; ++y) {
1406 int const line_size_pixels = line_size()[c] / 2;
1407 for (int x = 0; x < line_size_pixels; ++x) {
1408 *q = int((*q - 256) * factor);
1416 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);