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 "dcpomatic_socket.h"
31 #include <dcp/rgb_xyz.h>
32 #include <dcp/transfer_function.h>
34 #include <libswscale/swscale.h>
35 #include <libavutil/pixfmt.h>
36 #include <libavutil/pixdesc.h>
37 #include <libavutil/frame.h>
39 #if HAVE_VALGRIND_MEMCHECK_H
40 #include <valgrind/memcheck.h>
52 using std::runtime_error;
53 using boost::shared_ptr;
57 Image::vertical_factor (int n) const
63 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
65 throw PixelFormatError ("line_factor()", _pixel_format);
68 return pow (2.0f, d->log2_chroma_h);
72 Image::horizontal_factor (int n) const
78 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
80 throw PixelFormatError ("sample_size()", _pixel_format);
83 return pow (2.0f, d->log2_chroma_w);
86 /** @param n Component index.
87 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
90 Image::sample_size (int n) const
93 lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
94 lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
98 /** @return Number of planes */
100 Image::planes () const
102 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
104 throw PixelFormatError ("planes()", _pixel_format);
107 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
111 return d->nb_components;
114 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
115 * @param crop Amount to crop by.
116 * @param inter_size Size to scale the cropped image to.
117 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
118 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
119 * @param out_format Output pixel format.
120 * @param out_aligned true to make the output image aligned.
121 * @param fast Try to be fast at the possible expense of quality; at present this means using
122 * fast bilinear rather than bicubic scaling.
125 Image::crop_scale_window (
126 Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
129 /* Empirical testing suggests that sws_scale() will crash if
130 the input image is not aligned.
132 DCPOMATIC_ASSERT (aligned ());
134 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
135 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
137 /* Here's an image of out_size. Below we may write to it starting at an offset so we get some padding.
138 Hence we want to write in the following pattern:
140 block start write start line end
141 |..(padding)..|<------line-size------------->|..(padding)..|
142 |..(padding)..|<------line-size------------->|..(padding)..|
143 |..(padding)..|<------line-size------------->|..(padding)..|
145 where line-size is of the smaller (inter_size) image and the full padded line length is that of
146 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
147 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
148 specified *stride*. This does not matter until we get to the last line:
150 block start write start line end
151 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
152 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
153 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
156 To get around this, we ask Image to overallocate its buffers by the overrun.
159 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned, (out_size.width - inter_size.width) / 2));
162 /* Size of the image after any crop */
163 dcp::Size const cropped_size = crop.apply (size ());
165 /* Scale context for a scale from cropped_size to inter_size */
166 struct SwsContext* scale_context = sws_getContext (
167 cropped_size.width, cropped_size.height, pixel_format(),
168 inter_size.width, inter_size.height, out_format,
169 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
172 if (!scale_context) {
173 throw runtime_error (N_("Could not allocate SwsContext"));
176 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
177 int const lut[dcp::YUV_TO_RGB_COUNT] = {
182 sws_setColorspaceDetails (
184 sws_getCoefficients (lut[yuv_to_rgb]), 0,
185 sws_getCoefficients (lut[yuv_to_rgb]), 0,
189 AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
191 throw PixelFormatError ("crop_scale_window()", _pixel_format);
194 /* Prepare input data pointers with crop */
195 uint8_t* scale_in_data[planes()];
196 for (int c = 0; c < planes(); ++c) {
197 /* To work out the crop in bytes, start by multiplying
198 the crop by the (average) bytes per pixel. Then
199 round down so that we don't crop a subsampled pixel until
200 we've cropped all of its Y-channel pixels.
202 int const x = lrintf (bytes_per_pixel(c) * crop.left) & ~ ((int) in_desc->log2_chroma_w);
203 scale_in_data[c] = data()[c] + x + stride()[c] * (crop.top / vertical_factor(c));
206 /* Corner of the image within out_size */
207 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
209 AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
211 throw PixelFormatError ("crop_scale_window()", out_format);
214 uint8_t* scale_out_data[out->planes()];
215 for (int c = 0; c < out->planes(); ++c) {
216 /* See the note in the crop loop above */
217 int const x = lrintf (out->bytes_per_pixel(c) * corner.x) & ~ ((int) out_desc->log2_chroma_w);
218 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
223 scale_in_data, stride(),
224 0, cropped_size.height,
225 scale_out_data, out->stride()
228 sws_freeContext (scale_context);
234 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
236 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
239 /** @param out_size Size to scale to.
240 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
241 * @param out_format Output pixel format.
242 * @param out_aligned true to make an aligned output image.
243 * @param fast Try to be fast at the possible expense of quality; at present this means using
244 * fast bilinear rather than bicubic scaling.
247 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
249 /* Empirical testing suggests that sws_scale() will crash if
250 the input image is not aligned.
252 DCPOMATIC_ASSERT (aligned ());
254 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
256 struct SwsContext* scale_context = sws_getContext (
257 size().width, size().height, pixel_format(),
258 out_size.width, out_size.height, out_format,
259 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
262 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
263 int const lut[dcp::YUV_TO_RGB_COUNT] = {
268 sws_setColorspaceDetails (
270 sws_getCoefficients (lut[yuv_to_rgb]), 0,
271 sws_getCoefficients (lut[yuv_to_rgb]), 0,
279 scaled->data(), scaled->stride()
282 sws_freeContext (scale_context);
287 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
289 Image::yuv_16_black (uint16_t v, bool alpha)
291 memset (data()[0], 0, sample_size(0).height * stride()[0]);
292 for (int i = 1; i < 3; ++i) {
293 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
294 int const lines = sample_size(i).height;
295 for (int y = 0; y < lines; ++y) {
296 /* We divide by 2 here because we are writing 2 bytes at a time */
297 for (int x = 0; x < line_size()[i] / 2; ++x) {
300 p += stride()[i] / 2;
305 memset (data()[3], 0, sample_size(3).height * stride()[3]);
310 Image::swap_16 (uint16_t v)
312 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
318 /* U/V black value for 8-bit colour */
319 static uint8_t const eight_bit_uv = (1 << 7) - 1;
320 /* U/V black value for 9-bit colour */
321 static uint16_t const nine_bit_uv = (1 << 8) - 1;
322 /* U/V black value for 10-bit colour */
323 static uint16_t const ten_bit_uv = (1 << 9) - 1;
324 /* U/V black value for 16-bit colour */
325 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
327 switch (_pixel_format) {
328 case AV_PIX_FMT_YUV420P:
329 case AV_PIX_FMT_YUV422P:
330 case AV_PIX_FMT_YUV444P:
331 case AV_PIX_FMT_YUV411P:
332 memset (data()[0], 0, sample_size(0).height * stride()[0]);
333 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
334 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
337 case AV_PIX_FMT_YUVJ420P:
338 case AV_PIX_FMT_YUVJ422P:
339 case AV_PIX_FMT_YUVJ444P:
340 memset (data()[0], 0, sample_size(0).height * stride()[0]);
341 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
342 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
345 case AV_PIX_FMT_YUV422P9LE:
346 case AV_PIX_FMT_YUV444P9LE:
347 yuv_16_black (nine_bit_uv, false);
350 case AV_PIX_FMT_YUV422P9BE:
351 case AV_PIX_FMT_YUV444P9BE:
352 yuv_16_black (swap_16 (nine_bit_uv), false);
355 case AV_PIX_FMT_YUV422P10LE:
356 case AV_PIX_FMT_YUV444P10LE:
357 yuv_16_black (ten_bit_uv, false);
360 case AV_PIX_FMT_YUV422P16LE:
361 case AV_PIX_FMT_YUV444P16LE:
362 yuv_16_black (sixteen_bit_uv, false);
365 case AV_PIX_FMT_YUV444P10BE:
366 case AV_PIX_FMT_YUV422P10BE:
367 yuv_16_black (swap_16 (ten_bit_uv), false);
370 case AV_PIX_FMT_YUVA420P9BE:
371 case AV_PIX_FMT_YUVA422P9BE:
372 case AV_PIX_FMT_YUVA444P9BE:
373 yuv_16_black (swap_16 (nine_bit_uv), true);
376 case AV_PIX_FMT_YUVA420P9LE:
377 case AV_PIX_FMT_YUVA422P9LE:
378 case AV_PIX_FMT_YUVA444P9LE:
379 yuv_16_black (nine_bit_uv, true);
382 case AV_PIX_FMT_YUVA420P10BE:
383 case AV_PIX_FMT_YUVA422P10BE:
384 case AV_PIX_FMT_YUVA444P10BE:
385 yuv_16_black (swap_16 (ten_bit_uv), true);
388 case AV_PIX_FMT_YUVA420P10LE:
389 case AV_PIX_FMT_YUVA422P10LE:
390 case AV_PIX_FMT_YUVA444P10LE:
391 yuv_16_black (ten_bit_uv, true);
394 case AV_PIX_FMT_YUVA420P16BE:
395 case AV_PIX_FMT_YUVA422P16BE:
396 case AV_PIX_FMT_YUVA444P16BE:
397 yuv_16_black (swap_16 (sixteen_bit_uv), true);
400 case AV_PIX_FMT_YUVA420P16LE:
401 case AV_PIX_FMT_YUVA422P16LE:
402 case AV_PIX_FMT_YUVA444P16LE:
403 yuv_16_black (sixteen_bit_uv, true);
406 case AV_PIX_FMT_RGB24:
407 case AV_PIX_FMT_ARGB:
408 case AV_PIX_FMT_RGBA:
409 case AV_PIX_FMT_ABGR:
410 case AV_PIX_FMT_BGRA:
411 case AV_PIX_FMT_RGB555LE:
412 case AV_PIX_FMT_RGB48LE:
413 case AV_PIX_FMT_RGB48BE:
414 case AV_PIX_FMT_XYZ12LE:
415 memset (data()[0], 0, sample_size(0).height * stride()[0]);
418 case AV_PIX_FMT_UYVY422:
420 int const Y = sample_size(0).height;
421 int const X = line_size()[0];
422 uint8_t* p = data()[0];
423 for (int y = 0; y < Y; ++y) {
424 for (int x = 0; x < X / 4; ++x) {
425 *p++ = eight_bit_uv; // Cb
427 *p++ = eight_bit_uv; // Cr
435 throw PixelFormatError ("make_black()", _pixel_format);
440 Image::make_transparent ()
442 if (_pixel_format != AV_PIX_FMT_BGRA) {
443 throw PixelFormatError ("make_transparent()", _pixel_format);
446 memset (data()[0], 0, sample_size(0).height * stride()[0]);
450 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
452 /* We're blending BGRA images; first byte is blue, second byte is green, third byte red, fourth byte alpha */
453 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA);
454 int const other_bpp = 4;
456 int start_tx = position.x;
460 start_ox = -start_tx;
464 int start_ty = position.y;
468 start_oy = -start_ty;
472 switch (_pixel_format) {
473 case AV_PIX_FMT_RGB24:
475 /* Going onto RGB24. First byte is red, second green, third blue */
476 int const this_bpp = 3;
477 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
478 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
479 uint8_t* op = other->data()[0] + oy * other->stride()[0];
480 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
481 float const alpha = float (op[3]) / 255;
482 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
483 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
484 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
492 case AV_PIX_FMT_BGRA:
494 int const this_bpp = 4;
495 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
496 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
497 uint8_t* op = other->data()[0] + oy * other->stride()[0];
498 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
499 float const alpha = float (op[3]) / 255;
500 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
501 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
502 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
503 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
511 case AV_PIX_FMT_RGBA:
513 int const this_bpp = 4;
514 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
515 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
516 uint8_t* op = other->data()[0] + oy * other->stride()[0];
517 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
518 float const alpha = float (op[3]) / 255;
519 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
520 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
521 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
522 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
530 case AV_PIX_FMT_RGB48LE:
532 int const this_bpp = 6;
533 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
534 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
535 uint8_t* op = other->data()[0] + oy * other->stride()[0];
536 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
537 float const alpha = float (op[3]) / 255;
538 /* Blend high bytes */
539 tp[1] = op[2] * alpha + tp[1] * (1 - alpha);
540 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
541 tp[5] = op[0] * alpha + tp[5] * (1 - alpha);
549 case AV_PIX_FMT_XYZ12LE:
551 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
552 double fast_matrix[9];
553 dcp::combined_rgb_to_xyz (conv, fast_matrix);
554 double const * lut_in = conv.in()->lut (8, false);
555 double const * lut_out = conv.out()->lut (16, true);
556 int const this_bpp = 6;
557 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
558 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
559 uint8_t* op = other->data()[0] + oy * other->stride()[0];
560 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
561 float const alpha = float (op[3]) / 255;
563 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
564 double const r = lut_in[op[2]];
565 double const g = lut_in[op[1]];
566 double const b = lut_in[op[0]];
568 /* RGB to XYZ, including Bradford transform and DCI companding */
569 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
570 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
571 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
573 /* Out gamma LUT and blend */
574 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
575 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
576 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
584 case AV_PIX_FMT_YUV420P:
586 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
587 dcp::Size const ts = size();
588 dcp::Size const os = yuv->size();
589 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
590 int const hty = ty / 2;
591 int const hoy = oy / 2;
592 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
593 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
594 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
595 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
596 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
597 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
598 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
599 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
600 float const a = float(alpha[3]) / 255;
601 *tY = *oY * a + *tY * (1 - a);
602 *tU = *oU * a + *tU * (1 - a);
603 *tV = *oV * a + *tV * (1 - a);
619 case AV_PIX_FMT_YUV420P10:
621 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
622 dcp::Size const ts = size();
623 dcp::Size const os = yuv->size();
624 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
625 int const hty = ty / 2;
626 int const hoy = oy / 2;
627 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
628 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
629 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
630 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
631 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
632 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
633 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
634 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
635 float const a = float(alpha[3]) / 255;
636 *tY = *oY * a + *tY * (1 - a);
637 *tU = *oU * a + *tU * (1 - a);
638 *tV = *oV * a + *tV * (1 - a);
654 case AV_PIX_FMT_YUV422P10LE:
656 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
657 dcp::Size const ts = size();
658 dcp::Size const os = yuv->size();
659 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
660 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
661 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
662 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
663 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
664 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
665 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
666 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
667 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
668 float const a = float(alpha[3]) / 255;
669 *tY = *oY * a + *tY * (1 - a);
670 *tU = *oU * a + *tU * (1 - a);
671 *tV = *oV * a + *tV * (1 - a);
688 throw PixelFormatError ("alpha_blend()", _pixel_format);
693 Image::copy (shared_ptr<const Image> other, Position<int> position)
695 /* Only implemented for RGB24 onto RGB24 so far */
696 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
697 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
699 int const N = min (position.x + other->size().width, size().width) - position.x;
700 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
701 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
702 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
703 memcpy (tp, op, N * 3);
708 Image::read_from_socket (shared_ptr<Socket> socket)
710 for (int i = 0; i < planes(); ++i) {
711 uint8_t* p = data()[i];
712 int const lines = sample_size(i).height;
713 for (int y = 0; y < lines; ++y) {
714 socket->read (p, line_size()[i]);
721 Image::write_to_socket (shared_ptr<Socket> socket) const
723 for (int i = 0; i < planes(); ++i) {
724 uint8_t* p = data()[i];
725 int const lines = sample_size(i).height;
726 for (int y = 0; y < lines; ++y) {
727 socket->write (p, line_size()[i]);
734 Image::bytes_per_pixel (int c) const
736 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
738 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
745 float bpp[4] = { 0, 0, 0, 0 };
747 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
748 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
749 if (d->nb_components > 1) {
750 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
752 if (d->nb_components > 2) {
753 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
755 if (d->nb_components > 3) {
756 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
759 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
760 if (d->nb_components > 1) {
761 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
763 if (d->nb_components > 2) {
764 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
766 if (d->nb_components > 3) {
767 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
771 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
772 /* Not planar; sum them up */
773 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
779 /** Construct a Image of a given size and format, allocating memory
782 * @param p Pixel format.
783 * @param s Size in pixels.
784 * @param aligned true to make each row of this image aligned to a 32-byte boundary.
785 * @param extra_pixels Amount of extra "run-off" memory to allocate at the end of each plane in pixels.
787 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned, int extra_pixels)
791 , _extra_pixels (extra_pixels)
799 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
800 _data[0] = _data[1] = _data[2] = _data[3] = 0;
802 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
803 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
805 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
806 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
808 for (int i = 0; i < planes(); ++i) {
809 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
810 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
812 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
813 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
814 Hence on the last pixel of the last line it reads over the end of
815 the actual data by 1 byte. If the width of an image is a multiple
816 of the stride alignment there will be no padding at the end of image lines.
817 OS X crashes on this illegal read, though other operating systems don't
818 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
819 for that instruction to read safely.
821 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
822 over-reads by more then _avx. I can't follow the code to work out how much,
823 so I'll just over-allocate by 32 bytes and have done with it. Empirical
824 testing suggests that it works.
826 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
827 #if HAVE_VALGRIND_MEMCHECK_H
828 /* The data between the end of the line size and the stride is undefined but processed by
829 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
831 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
836 Image::Image (Image const & other)
837 : boost::enable_shared_from_this<Image>(other)
838 , _size (other._size)
839 , _pixel_format (other._pixel_format)
840 , _aligned (other._aligned)
841 , _extra_pixels (other._extra_pixels)
845 for (int i = 0; i < planes(); ++i) {
846 uint8_t* p = _data[i];
847 uint8_t* q = other._data[i];
848 int const lines = sample_size(i).height;
849 for (int j = 0; j < lines; ++j) {
850 memcpy (p, q, _line_size[i]);
852 q += other.stride()[i];
857 Image::Image (AVFrame* frame)
858 : _size (frame->width, frame->height)
859 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
865 for (int i = 0; i < planes(); ++i) {
866 uint8_t* p = _data[i];
867 uint8_t* q = frame->data[i];
868 int const lines = sample_size(i).height;
869 for (int j = 0; j < lines; ++j) {
870 memcpy (p, q, _line_size[i]);
872 /* AVFrame's linesize is what we call `stride' */
873 q += frame->linesize[i];
878 Image::Image (shared_ptr<const Image> other, bool aligned)
879 : _size (other->_size)
880 , _pixel_format (other->_pixel_format)
882 , _extra_pixels (other->_extra_pixels)
886 for (int i = 0; i < planes(); ++i) {
887 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
888 uint8_t* p = _data[i];
889 uint8_t* q = other->data()[i];
890 int const lines = sample_size(i).height;
891 for (int j = 0; j < lines; ++j) {
892 memcpy (p, q, line_size()[i]);
894 q += other->stride()[i];
900 Image::operator= (Image const & other)
902 if (this == &other) {
912 Image::swap (Image & other)
914 std::swap (_size, other._size);
915 std::swap (_pixel_format, other._pixel_format);
917 for (int i = 0; i < 4; ++i) {
918 std::swap (_data[i], other._data[i]);
919 std::swap (_line_size[i], other._line_size[i]);
920 std::swap (_stride[i], other._stride[i]);
923 std::swap (_aligned, other._aligned);
924 std::swap (_extra_pixels, other._extra_pixels);
927 /** Destroy a Image */
930 for (int i = 0; i < planes(); ++i) {
935 av_free (_line_size);
946 Image::line_size () const
952 Image::stride () const
964 Image::aligned () const
970 merge (list<PositionImage> images)
972 if (images.empty ()) {
973 return PositionImage ();
976 if (images.size() == 1) {
977 return images.front ();
980 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
981 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
982 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
985 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
986 merged->make_transparent ();
987 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
988 merged->alpha_blend (i->image, i->position - all.position());
991 return PositionImage (merged, all.position ());
995 operator== (Image const & a, Image const & b)
997 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1001 for (int c = 0; c < a.planes(); ++c) {
1002 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]) {
1006 uint8_t* p = a.data()[c];
1007 uint8_t* q = b.data()[c];
1008 int const lines = a.sample_size(c).height;
1009 for (int y = 0; y < lines; ++y) {
1010 if (memcmp (p, q, a.line_size()[c]) != 0) {
1023 * @param f Amount to fade by; 0 is black, 1 is no fade.
1026 Image::fade (float f)
1028 switch (_pixel_format) {
1029 case AV_PIX_FMT_YUV420P:
1030 case AV_PIX_FMT_YUV422P:
1031 case AV_PIX_FMT_YUV444P:
1032 case AV_PIX_FMT_YUV411P:
1033 case AV_PIX_FMT_YUVJ420P:
1034 case AV_PIX_FMT_YUVJ422P:
1035 case AV_PIX_FMT_YUVJ444P:
1036 case AV_PIX_FMT_RGB24:
1037 case AV_PIX_FMT_ARGB:
1038 case AV_PIX_FMT_RGBA:
1039 case AV_PIX_FMT_ABGR:
1040 case AV_PIX_FMT_BGRA:
1041 case AV_PIX_FMT_RGB555LE:
1043 for (int c = 0; c < 3; ++c) {
1044 uint8_t* p = data()[c];
1045 int const lines = sample_size(c).height;
1046 for (int y = 0; y < lines; ++y) {
1048 for (int x = 0; x < line_size()[c]; ++x) {
1049 *q = int (float (*q) * f);
1057 case AV_PIX_FMT_YUV422P9LE:
1058 case AV_PIX_FMT_YUV444P9LE:
1059 case AV_PIX_FMT_YUV422P10LE:
1060 case AV_PIX_FMT_YUV444P10LE:
1061 case AV_PIX_FMT_YUV422P16LE:
1062 case AV_PIX_FMT_YUV444P16LE:
1063 case AV_PIX_FMT_YUVA420P9LE:
1064 case AV_PIX_FMT_YUVA422P9LE:
1065 case AV_PIX_FMT_YUVA444P9LE:
1066 case AV_PIX_FMT_YUVA420P10LE:
1067 case AV_PIX_FMT_YUVA422P10LE:
1068 case AV_PIX_FMT_YUVA444P10LE:
1069 case AV_PIX_FMT_RGB48LE:
1070 case AV_PIX_FMT_XYZ12LE:
1071 /* 16-bit little-endian */
1072 for (int c = 0; c < 3; ++c) {
1073 int const stride_pixels = stride()[c] / 2;
1074 int const line_size_pixels = line_size()[c] / 2;
1075 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1076 int const lines = sample_size(c).height;
1077 for (int y = 0; y < lines; ++y) {
1079 for (int x = 0; x < line_size_pixels; ++x) {
1080 *q = int (float (*q) * f);
1088 case AV_PIX_FMT_YUV422P9BE:
1089 case AV_PIX_FMT_YUV444P9BE:
1090 case AV_PIX_FMT_YUV444P10BE:
1091 case AV_PIX_FMT_YUV422P10BE:
1092 case AV_PIX_FMT_YUVA420P9BE:
1093 case AV_PIX_FMT_YUVA422P9BE:
1094 case AV_PIX_FMT_YUVA444P9BE:
1095 case AV_PIX_FMT_YUVA420P10BE:
1096 case AV_PIX_FMT_YUVA422P10BE:
1097 case AV_PIX_FMT_YUVA444P10BE:
1098 case AV_PIX_FMT_YUVA420P16BE:
1099 case AV_PIX_FMT_YUVA422P16BE:
1100 case AV_PIX_FMT_YUVA444P16BE:
1101 case AV_PIX_FMT_RGB48BE:
1102 /* 16-bit big-endian */
1103 for (int c = 0; c < 3; ++c) {
1104 int const stride_pixels = stride()[c] / 2;
1105 int const line_size_pixels = line_size()[c] / 2;
1106 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1107 int const lines = sample_size(c).height;
1108 for (int y = 0; y < lines; ++y) {
1110 for (int x = 0; x < line_size_pixels; ++x) {
1111 *q = swap_16 (int (float (swap_16 (*q)) * f));
1119 case AV_PIX_FMT_UYVY422:
1121 int const Y = sample_size(0).height;
1122 int const X = line_size()[0];
1123 uint8_t* p = data()[0];
1124 for (int y = 0; y < Y; ++y) {
1125 for (int x = 0; x < X; ++x) {
1126 *p = int (float (*p) * f);
1134 throw PixelFormatError ("fade()", _pixel_format);
1138 shared_ptr<const Image>
1139 Image::ensure_aligned (shared_ptr<const Image> image)
1141 if (image->aligned()) {
1145 return shared_ptr<Image> (new Image (image, true));
1149 Image::memory_used () const
1152 for (int i = 0; i < planes(); ++i) {
1153 m += _stride[i] * sample_size(i).height;
1159 Image::as_png () const