2 Copyright (C) 2012-2016 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/>.
21 /** @file src/image.cc
22 * @brief A class to describe a video image.
26 #include "exceptions.h"
30 #include "compose.hpp"
31 #include "dcpomatic_socket.h"
32 #include <dcp/rgb_xyz.h>
33 #include <dcp/transfer_function.h>
35 #include <libswscale/swscale.h>
36 #include <libavutil/pixfmt.h>
37 #include <libavutil/pixdesc.h>
38 #include <libavutil/frame.h>
41 #if HAVE_VALGRIND_MEMCHECK_H
42 #include <valgrind/memcheck.h>
54 using std::runtime_error;
55 using boost::shared_ptr;
59 /** The memory alignment, in bytes, used for each row of an image if aligment is requested */
64 Image::vertical_factor (int n) const
70 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
72 throw PixelFormatError ("line_factor()", _pixel_format);
75 return lrintf(powf(2.0f, d->log2_chroma_h));
79 Image::horizontal_factor (int n) const
85 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
87 throw PixelFormatError ("sample_size()", _pixel_format);
90 return lrintf(powf(2.0f, d->log2_chroma_w));
93 /** @param n Component index.
94 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
97 Image::sample_size (int n) const
100 lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
101 lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
105 /** @return Number of planes */
107 Image::planes () const
109 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
111 throw PixelFormatError ("planes()", _pixel_format);
114 if (_pixel_format == AV_PIX_FMT_PAL8) {
118 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
122 return d->nb_components;
128 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
130 return p & ~ ((1 << desc->log2_chroma_w) - 1);
136 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
138 return p & ~ ((1 << desc->log2_chroma_h) - 1);
142 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
143 * @param crop Amount to crop by.
144 * @param inter_size Size to scale the cropped image to.
145 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
146 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
147 * @param out_format Output pixel format.
148 * @param out_aligned true to make the output image aligned.
149 * @param fast Try to be fast at the possible expense of quality; at present this means using
150 * fast bilinear rather than bicubic scaling.
153 Image::crop_scale_window (
154 Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
157 /* Empirical testing suggests that sws_scale() will crash if
158 the input image is not aligned.
160 DCPOMATIC_ASSERT (aligned ());
162 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
163 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
165 shared_ptr<Image> out (new Image(out_format, out_size, out_aligned));
168 AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
170 throw PixelFormatError ("crop_scale_window()", _pixel_format);
173 /* Round down so that we crop only the number of pixels that is straightforward
174 * considering any subsampling.
177 round_width_for_subsampling(crop.left, in_desc),
178 round_width_for_subsampling(crop.right, in_desc),
179 round_height_for_subsampling(crop.top, in_desc),
180 round_height_for_subsampling(crop.bottom, in_desc)
183 /* Also check that we aren't cropping more image than there actually is */
184 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
185 corrected_crop.left = 0;
186 corrected_crop.right = size().width - 4;
189 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
190 corrected_crop.top = 0;
191 corrected_crop.bottom = size().height - 4;
194 /* Size of the image after any crop */
195 dcp::Size const cropped_size = corrected_crop.apply (size());
197 /* Hack: if we're not doing quite the crop that we were asked for, and we carry on scaling
198 * to the inter_size we were asked for, there is a small but noticeable wobble in the image
199 * luminance (#1872). This hack means we will jump in steps of the subsampling distance
200 * in both crop and scale.
202 inter_size.width = round_width_for_subsampling(inter_size.width, in_desc);
203 inter_size.height = round_width_for_subsampling(inter_size.height, in_desc);
205 /* Scale context for a scale from cropped_size to inter_size */
206 struct SwsContext* scale_context = sws_getContext (
207 cropped_size.width, cropped_size.height, pixel_format(),
208 inter_size.width, inter_size.height, out_format,
209 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
212 if (!scale_context) {
213 throw runtime_error (N_("Could not allocate SwsContext"));
216 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
217 int const lut[dcp::YUV_TO_RGB_COUNT] = {
222 /* The 3rd parameter here is:
223 0 -> source range MPEG (i.e. "video", 16-235)
224 1 -> source range JPEG (i.e. "full", 0-255)
226 0 -> destination range MPEG (i.e. "video", 16-235)
227 1 -> destination range JPEG (i.e. "full", 0-255)
229 But remember: sws_setColorspaceDetails ignores
230 these parameters unless the image isYUV or isGray
231 (if it's neither, it uses video range for source
234 sws_setColorspaceDetails (
236 sws_getCoefficients (lut[yuv_to_rgb]), 0,
237 sws_getCoefficients (lut[yuv_to_rgb]), 0,
241 /* Prepare input data pointers with crop */
242 uint8_t* scale_in_data[planes()];
243 for (int c = 0; c < planes(); ++c) {
244 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
245 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
248 AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
250 throw PixelFormatError ("crop_scale_window()", out_format);
253 /* Corner of the image within out_size */
254 Position<int> const corner (
255 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
256 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
259 uint8_t* scale_out_data[out->planes()];
260 for (int c = 0; c < out->planes(); ++c) {
261 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
262 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
267 scale_in_data, stride(),
268 0, cropped_size.height,
269 scale_out_data, out->stride()
272 sws_freeContext (scale_context);
274 if (corrected_crop != Crop() && cropped_size == inter_size) {
275 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
276 data behind in our image. Clear it out. It may get to the point where we should just stop
277 trying to be clever with cropping.
279 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
286 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
288 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
291 /** @param out_size Size to scale to.
292 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
293 * @param out_format Output pixel format.
294 * @param out_aligned true to make an aligned output image.
295 * @param fast Try to be fast at the possible expense of quality; at present this means using
296 * fast bilinear rather than bicubic scaling.
299 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
301 /* Empirical testing suggests that sws_scale() will crash if
302 the input image is not aligned.
304 DCPOMATIC_ASSERT (aligned ());
306 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
308 struct SwsContext* scale_context = sws_getContext (
309 size().width, size().height, pixel_format(),
310 out_size.width, out_size.height, out_format,
311 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
314 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
315 int const lut[dcp::YUV_TO_RGB_COUNT] = {
320 /* The 3rd parameter here is:
321 0 -> source range MPEG (i.e. "video", 16-235)
322 1 -> source range JPEG (i.e. "full", 0-255)
324 0 -> destination range MPEG (i.e. "video", 16-235)
325 1 -> destination range JPEG (i.e. "full", 0-255)
327 But remember: sws_setColorspaceDetails ignores
328 these parameters unless the image isYUV or isGray
329 (if it's neither, it uses video range for source
332 sws_setColorspaceDetails (
334 sws_getCoefficients (lut[yuv_to_rgb]), 0,
335 sws_getCoefficients (lut[yuv_to_rgb]), 0,
343 scaled->data(), scaled->stride()
346 sws_freeContext (scale_context);
351 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
353 Image::yuv_16_black (uint16_t v, bool alpha)
355 memset (data()[0], 0, sample_size(0).height * stride()[0]);
356 for (int i = 1; i < 3; ++i) {
357 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
358 int const lines = sample_size(i).height;
359 for (int y = 0; y < lines; ++y) {
360 /* We divide by 2 here because we are writing 2 bytes at a time */
361 for (int x = 0; x < line_size()[i] / 2; ++x) {
364 p += stride()[i] / 2;
369 memset (data()[3], 0, sample_size(3).height * stride()[3]);
374 Image::swap_16 (uint16_t v)
376 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
380 Image::make_part_black (int x, int w)
382 switch (_pixel_format) {
383 case AV_PIX_FMT_RGB24:
384 case AV_PIX_FMT_ARGB:
385 case AV_PIX_FMT_RGBA:
386 case AV_PIX_FMT_ABGR:
387 case AV_PIX_FMT_BGRA:
388 case AV_PIX_FMT_RGB555LE:
389 case AV_PIX_FMT_RGB48LE:
390 case AV_PIX_FMT_RGB48BE:
391 case AV_PIX_FMT_XYZ12LE:
393 int const h = sample_size(0).height;
394 int const bpp = bytes_per_pixel(0);
395 int const s = stride()[0];
396 uint8_t* p = data()[0];
397 for (int y = 0; y < h; y++) {
398 memset (p + x * bpp, 0, w * bpp);
405 throw PixelFormatError ("make_part_black()", _pixel_format);
412 /* U/V black value for 8-bit colour */
413 static uint8_t const eight_bit_uv = (1 << 7) - 1;
414 /* U/V black value for 9-bit colour */
415 static uint16_t const nine_bit_uv = (1 << 8) - 1;
416 /* U/V black value for 10-bit colour */
417 static uint16_t const ten_bit_uv = (1 << 9) - 1;
418 /* U/V black value for 16-bit colour */
419 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
421 switch (_pixel_format) {
422 case AV_PIX_FMT_YUV420P:
423 case AV_PIX_FMT_YUV422P:
424 case AV_PIX_FMT_YUV444P:
425 case AV_PIX_FMT_YUV411P:
426 memset (data()[0], 0, sample_size(0).height * stride()[0]);
427 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
428 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
431 case AV_PIX_FMT_YUVJ420P:
432 case AV_PIX_FMT_YUVJ422P:
433 case AV_PIX_FMT_YUVJ444P:
434 memset (data()[0], 0, sample_size(0).height * stride()[0]);
435 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
436 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
439 case AV_PIX_FMT_YUV422P9LE:
440 case AV_PIX_FMT_YUV444P9LE:
441 yuv_16_black (nine_bit_uv, false);
444 case AV_PIX_FMT_YUV422P9BE:
445 case AV_PIX_FMT_YUV444P9BE:
446 yuv_16_black (swap_16 (nine_bit_uv), false);
449 case AV_PIX_FMT_YUV422P10LE:
450 case AV_PIX_FMT_YUV444P10LE:
451 yuv_16_black (ten_bit_uv, false);
454 case AV_PIX_FMT_YUV422P16LE:
455 case AV_PIX_FMT_YUV444P16LE:
456 yuv_16_black (sixteen_bit_uv, false);
459 case AV_PIX_FMT_YUV444P10BE:
460 case AV_PIX_FMT_YUV422P10BE:
461 yuv_16_black (swap_16 (ten_bit_uv), false);
464 case AV_PIX_FMT_YUVA420P9BE:
465 case AV_PIX_FMT_YUVA422P9BE:
466 case AV_PIX_FMT_YUVA444P9BE:
467 yuv_16_black (swap_16 (nine_bit_uv), true);
470 case AV_PIX_FMT_YUVA420P9LE:
471 case AV_PIX_FMT_YUVA422P9LE:
472 case AV_PIX_FMT_YUVA444P9LE:
473 yuv_16_black (nine_bit_uv, true);
476 case AV_PIX_FMT_YUVA420P10BE:
477 case AV_PIX_FMT_YUVA422P10BE:
478 case AV_PIX_FMT_YUVA444P10BE:
479 yuv_16_black (swap_16 (ten_bit_uv), true);
482 case AV_PIX_FMT_YUVA420P10LE:
483 case AV_PIX_FMT_YUVA422P10LE:
484 case AV_PIX_FMT_YUVA444P10LE:
485 yuv_16_black (ten_bit_uv, true);
488 case AV_PIX_FMT_YUVA420P16BE:
489 case AV_PIX_FMT_YUVA422P16BE:
490 case AV_PIX_FMT_YUVA444P16BE:
491 yuv_16_black (swap_16 (sixteen_bit_uv), true);
494 case AV_PIX_FMT_YUVA420P16LE:
495 case AV_PIX_FMT_YUVA422P16LE:
496 case AV_PIX_FMT_YUVA444P16LE:
497 yuv_16_black (sixteen_bit_uv, true);
500 case AV_PIX_FMT_RGB24:
501 case AV_PIX_FMT_ARGB:
502 case AV_PIX_FMT_RGBA:
503 case AV_PIX_FMT_ABGR:
504 case AV_PIX_FMT_BGRA:
505 case AV_PIX_FMT_RGB555LE:
506 case AV_PIX_FMT_RGB48LE:
507 case AV_PIX_FMT_RGB48BE:
508 case AV_PIX_FMT_XYZ12LE:
509 memset (data()[0], 0, sample_size(0).height * stride()[0]);
512 case AV_PIX_FMT_UYVY422:
514 int const Y = sample_size(0).height;
515 int const X = line_size()[0];
516 uint8_t* p = data()[0];
517 for (int y = 0; y < Y; ++y) {
518 for (int x = 0; x < X / 4; ++x) {
519 *p++ = eight_bit_uv; // Cb
521 *p++ = eight_bit_uv; // Cr
529 throw PixelFormatError ("make_black()", _pixel_format);
534 Image::make_transparent ()
536 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
537 throw PixelFormatError ("make_transparent()", _pixel_format);
540 memset (data()[0], 0, sample_size(0).height * stride()[0]);
544 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
546 /* We're blending RGBA or BGRA images */
547 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
548 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
549 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
551 int const other_bpp = 4;
553 int start_tx = position.x;
557 start_ox = -start_tx;
561 int start_ty = position.y;
565 start_oy = -start_ty;
569 switch (_pixel_format) {
570 case AV_PIX_FMT_RGB24:
572 /* Going onto RGB24. First byte is red, second green, third blue */
573 int const this_bpp = 3;
574 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
575 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
576 uint8_t* op = other->data()[0] + oy * other->stride()[0];
577 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
578 float const alpha = float (op[3]) / 255;
579 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
580 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
581 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
589 case AV_PIX_FMT_BGRA:
591 int const this_bpp = 4;
592 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
593 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
594 uint8_t* op = other->data()[0] + oy * other->stride()[0];
595 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
596 float const alpha = float (op[3]) / 255;
597 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
598 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
599 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
600 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
608 case AV_PIX_FMT_RGBA:
610 int const this_bpp = 4;
611 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
612 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
613 uint8_t* op = other->data()[0] + oy * other->stride()[0];
614 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
615 float const alpha = float (op[3]) / 255;
616 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
617 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
618 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
619 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
627 case AV_PIX_FMT_RGB48LE:
629 int const this_bpp = 6;
630 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
631 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
632 uint8_t* op = other->data()[0] + oy * other->stride()[0];
633 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
634 float const alpha = float (op[3]) / 255;
635 /* Blend high bytes */
636 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
637 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
638 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
646 case AV_PIX_FMT_XYZ12LE:
648 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
649 double fast_matrix[9];
650 dcp::combined_rgb_to_xyz (conv, fast_matrix);
651 double const * lut_in = conv.in()->lut (8, false);
652 double const * lut_out = conv.out()->lut (16, true);
653 int const this_bpp = 6;
654 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
655 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
656 uint8_t* op = other->data()[0] + oy * other->stride()[0];
657 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
658 float const alpha = float (op[3]) / 255;
660 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
661 double const r = lut_in[op[red]];
662 double const g = lut_in[op[1]];
663 double const b = lut_in[op[blue]];
665 /* RGB to XYZ, including Bradford transform and DCI companding */
666 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
667 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
668 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
670 /* Out gamma LUT and blend */
671 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
672 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
673 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
681 case AV_PIX_FMT_YUV420P:
683 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
684 dcp::Size const ts = size();
685 dcp::Size const os = yuv->size();
686 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
687 int const hty = ty / 2;
688 int const hoy = oy / 2;
689 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
690 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
691 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
692 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
693 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
694 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
695 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
696 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
697 float const a = float(alpha[3]) / 255;
698 *tY = *oY * a + *tY * (1 - a);
699 *tU = *oU * a + *tU * (1 - a);
700 *tV = *oV * a + *tV * (1 - a);
716 case AV_PIX_FMT_YUV420P10:
718 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
719 dcp::Size const ts = size();
720 dcp::Size const os = yuv->size();
721 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
722 int const hty = ty / 2;
723 int const hoy = oy / 2;
724 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
725 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
726 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
727 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
728 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
729 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
730 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
731 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
732 float const a = float(alpha[3]) / 255;
733 *tY = *oY * a + *tY * (1 - a);
734 *tU = *oU * a + *tU * (1 - a);
735 *tV = *oV * a + *tV * (1 - a);
751 case AV_PIX_FMT_YUV422P10LE:
753 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
754 dcp::Size const ts = size();
755 dcp::Size const os = yuv->size();
756 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
757 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
758 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
759 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
760 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
761 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
762 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
763 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
764 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
765 float const a = float(alpha[3]) / 255;
766 *tY = *oY * a + *tY * (1 - a);
767 *tU = *oU * a + *tU * (1 - a);
768 *tV = *oV * a + *tV * (1 - a);
785 throw PixelFormatError ("alpha_blend()", _pixel_format);
790 Image::copy (shared_ptr<const Image> other, Position<int> position)
792 /* Only implemented for RGB24 onto RGB24 so far */
793 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
794 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
796 int const N = min (position.x + other->size().width, size().width) - position.x;
797 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
798 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
799 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
800 memcpy (tp, op, N * 3);
805 Image::read_from_socket (shared_ptr<Socket> socket)
807 for (int i = 0; i < planes(); ++i) {
808 uint8_t* p = data()[i];
809 int const lines = sample_size(i).height;
810 for (int y = 0; y < lines; ++y) {
811 socket->read (p, line_size()[i]);
818 Image::write_to_socket (shared_ptr<Socket> socket) const
820 for (int i = 0; i < planes(); ++i) {
821 uint8_t* p = data()[i];
822 int const lines = sample_size(i).height;
823 for (int y = 0; y < lines; ++y) {
824 socket->write (p, line_size()[i]);
831 Image::bytes_per_pixel (int c) const
833 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
835 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
842 float bpp[4] = { 0, 0, 0, 0 };
844 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
845 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
846 if (d->nb_components > 1) {
847 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
849 if (d->nb_components > 2) {
850 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
852 if (d->nb_components > 3) {
853 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
856 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
857 if (d->nb_components > 1) {
858 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
860 if (d->nb_components > 2) {
861 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
863 if (d->nb_components > 3) {
864 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
868 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
869 /* Not planar; sum them up */
870 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
876 /** Construct a Image of a given size and format, allocating memory
879 * @param p Pixel format.
880 * @param s Size in pixels.
881 * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
883 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
894 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
895 _data[0] = _data[1] = _data[2] = _data[3] = 0;
897 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
898 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
900 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
901 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
903 for (int i = 0; i < planes(); ++i) {
904 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
905 _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
907 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
908 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
909 Hence on the last pixel of the last line it reads over the end of
910 the actual data by 1 byte. If the width of an image is a multiple
911 of the stride alignment there will be no padding at the end of image lines.
912 OS X crashes on this illegal read, though other operating systems don't
913 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
914 for that instruction to read safely.
916 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
917 over-reads by more then _avx. I can't follow the code to work out how much,
918 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
919 testing suggests that it works.
921 In addition to these concerns, we may read/write as much as a whole extra line
922 at the end of each plane in cases where we are messing with offsets in order to
923 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
925 As an example: we may write to images starting at an offset so we get some padding.
926 Hence we want to write in the following pattern:
928 block start write start line end
929 |..(padding)..|<------line-size------------->|..(padding)..|
930 |..(padding)..|<------line-size------------->|..(padding)..|
931 |..(padding)..|<------line-size------------->|..(padding)..|
933 where line-size is of the smaller (inter_size) image and the full padded line length is that of
934 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
935 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
936 specified *stride*. This does not matter until we get to the last line:
938 block start write start line end
939 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
940 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
941 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
944 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
945 #if HAVE_VALGRIND_MEMCHECK_H
946 /* The data between the end of the line size and the stride is undefined but processed by
947 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
949 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
954 Image::Image (Image const & other)
955 : boost::enable_shared_from_this<Image>(other)
956 , _size (other._size)
957 , _pixel_format (other._pixel_format)
958 , _aligned (other._aligned)
962 for (int i = 0; i < planes(); ++i) {
963 uint8_t* p = _data[i];
964 uint8_t* q = other._data[i];
965 int const lines = sample_size(i).height;
966 for (int j = 0; j < lines; ++j) {
967 memcpy (p, q, _line_size[i]);
969 q += other.stride()[i];
974 Image::Image (AVFrame* frame)
975 : _size (frame->width, frame->height)
976 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
981 for (int i = 0; i < planes(); ++i) {
982 uint8_t* p = _data[i];
983 uint8_t* q = frame->data[i];
984 int const lines = sample_size(i).height;
985 for (int j = 0; j < lines; ++j) {
986 memcpy (p, q, _line_size[i]);
988 /* AVFrame's linesize is what we call `stride' */
989 q += frame->linesize[i];
994 Image::Image (shared_ptr<const Image> other, bool aligned)
995 : _size (other->_size)
996 , _pixel_format (other->_pixel_format)
1001 for (int i = 0; i < planes(); ++i) {
1002 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1003 uint8_t* p = _data[i];
1004 uint8_t* q = other->data()[i];
1005 int const lines = sample_size(i).height;
1006 for (int j = 0; j < lines; ++j) {
1007 memcpy (p, q, line_size()[i]);
1009 q += other->stride()[i];
1015 Image::operator= (Image const & other)
1017 if (this == &other) {
1027 Image::swap (Image & other)
1029 std::swap (_size, other._size);
1030 std::swap (_pixel_format, other._pixel_format);
1032 for (int i = 0; i < 4; ++i) {
1033 std::swap (_data[i], other._data[i]);
1034 std::swap (_line_size[i], other._line_size[i]);
1035 std::swap (_stride[i], other._stride[i]);
1038 std::swap (_aligned, other._aligned);
1041 /** Destroy a Image */
1044 for (int i = 0; i < planes(); ++i) {
1049 av_free (_line_size);
1054 Image::data () const
1060 Image::line_size () const
1066 Image::stride () const
1072 Image::size () const
1078 Image::aligned () const
1084 merge (list<PositionImage> images)
1086 if (images.empty ()) {
1087 return PositionImage ();
1090 if (images.size() == 1) {
1091 return images.front ();
1094 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1095 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1096 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
1099 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
1100 merged->make_transparent ();
1101 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1102 merged->alpha_blend (i->image, i->position - all.position());
1105 return PositionImage (merged, all.position ());
1109 operator== (Image const & a, Image const & b)
1111 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1115 for (int c = 0; c < a.planes(); ++c) {
1116 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]) {
1120 uint8_t* p = a.data()[c];
1121 uint8_t* q = b.data()[c];
1122 int const lines = a.sample_size(c).height;
1123 for (int y = 0; y < lines; ++y) {
1124 if (memcmp (p, q, a.line_size()[c]) != 0) {
1137 * @param f Amount to fade by; 0 is black, 1 is no fade.
1140 Image::fade (float f)
1142 /* U/V black value for 8-bit colour */
1143 static int const eight_bit_uv = (1 << 7) - 1;
1144 /* U/V black value for 10-bit colour */
1145 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1147 switch (_pixel_format) {
1148 case AV_PIX_FMT_YUV420P:
1151 uint8_t* p = data()[0];
1152 int const lines = sample_size(0).height;
1153 for (int y = 0; y < lines; ++y) {
1155 for (int x = 0; x < line_size()[0]; ++x) {
1156 *q = int(float(*q) * f);
1163 for (int c = 1; c < 3; ++c) {
1164 uint8_t* p = data()[c];
1165 int const lines = sample_size(c).height;
1166 for (int y = 0; y < lines; ++y) {
1168 for (int x = 0; x < line_size()[c]; ++x) {
1169 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1179 case AV_PIX_FMT_RGB24:
1182 uint8_t* p = data()[0];
1183 int const lines = sample_size(0).height;
1184 for (int y = 0; y < lines; ++y) {
1186 for (int x = 0; x < line_size()[0]; ++x) {
1187 *q = int (float (*q) * f);
1195 case AV_PIX_FMT_XYZ12LE:
1196 case AV_PIX_FMT_RGB48LE:
1197 /* 16-bit little-endian */
1198 for (int c = 0; c < 3; ++c) {
1199 int const stride_pixels = stride()[c] / 2;
1200 int const line_size_pixels = line_size()[c] / 2;
1201 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1202 int const lines = sample_size(c).height;
1203 for (int y = 0; y < lines; ++y) {
1205 for (int x = 0; x < line_size_pixels; ++x) {
1206 *q = int (float (*q) * f);
1214 case AV_PIX_FMT_YUV422P10LE:
1218 int const stride_pixels = stride()[0] / 2;
1219 int const line_size_pixels = line_size()[0] / 2;
1220 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1221 int const lines = sample_size(0).height;
1222 for (int y = 0; y < lines; ++y) {
1224 for (int x = 0; x < line_size_pixels; ++x) {
1225 *q = int(float(*q) * f);
1233 for (int c = 1; c < 3; ++c) {
1234 int const stride_pixels = stride()[c] / 2;
1235 int const line_size_pixels = line_size()[c] / 2;
1236 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1237 int const lines = sample_size(c).height;
1238 for (int y = 0; y < lines; ++y) {
1240 for (int x = 0; x < line_size_pixels; ++x) {
1241 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1252 throw PixelFormatError ("fade()", _pixel_format);
1256 shared_ptr<const Image>
1257 Image::ensure_aligned (shared_ptr<const Image> image)
1259 if (image->aligned()) {
1263 return shared_ptr<Image> (new Image (image, true));
1267 Image::memory_used () const
1270 for (int i = 0; i < planes(); ++i) {
1271 m += _stride[i] * sample_size(i).height;
1294 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1296 Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1297 size_t size = mem->size + length;
1300 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1302 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1306 throw EncodeError (N_("could not allocate memory for PNG"));
1309 memcpy (mem->data + mem->size, data, length);
1310 mem->size += length;
1314 png_flush (png_structp)
1320 png_error_fn (png_structp png_ptr, char const * message)
1322 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1326 Image::png_error (char const * message)
1328 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1332 Image::as_png () const
1334 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1335 DCPOMATIC_ASSERT (planes() == 1);
1336 if (pixel_format() != AV_PIX_FMT_RGBA) {
1337 return convert_pixel_format(dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1340 /* error handling? */
1341 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1343 throw EncodeError (N_("could not create PNG write struct"));
1348 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1350 png_infop info_ptr = png_create_info_struct(png_ptr);
1352 png_destroy_write_struct (&png_ptr, &info_ptr);
1353 throw EncodeError (N_("could not create PNG info struct"));
1356 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);
1358 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1359 for (int i = 0; i < size().height; ++i) {
1360 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1363 png_write_info (png_ptr, info_ptr);
1364 png_write_image (png_ptr, row_pointers);
1365 png_write_end (png_ptr, info_ptr);
1367 png_destroy_write_struct (&png_ptr, &info_ptr);
1368 png_free (png_ptr, row_pointers);
1370 return dcp::Data (state.data, state.size);