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 Image::vertical_factor (int n) const
65 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
67 throw PixelFormatError ("line_factor()", _pixel_format);
70 return pow (2.0f, d->log2_chroma_h);
74 Image::horizontal_factor (int n) const
80 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
82 throw PixelFormatError ("sample_size()", _pixel_format);
85 return pow (2.0f, d->log2_chroma_w);
88 /** @param n Component index.
89 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
92 Image::sample_size (int n) const
95 lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
96 lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
100 /** @return Number of planes */
102 Image::planes () const
104 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
106 throw PixelFormatError ("planes()", _pixel_format);
109 if (_pixel_format == AV_PIX_FMT_PAL8) {
113 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
117 return d->nb_components;
120 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
121 * @param crop Amount to crop by.
122 * @param inter_size Size to scale the cropped image to.
123 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
124 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
125 * @param out_format Output pixel format.
126 * @param out_aligned true to make the output image aligned.
127 * @param fast Try to be fast at the possible expense of quality; at present this means using
128 * fast bilinear rather than bicubic scaling.
131 Image::crop_scale_window (
132 Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
135 /* Empirical testing suggests that sws_scale() will crash if
136 the input image is not aligned.
138 DCPOMATIC_ASSERT (aligned ());
140 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
141 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
143 /* Here's an image of out_size. Below we may write to it starting at an offset so we get some padding.
144 Hence we want to write in the following pattern:
146 block start write start line end
147 |..(padding)..|<------line-size------------->|..(padding)..|
148 |..(padding)..|<------line-size------------->|..(padding)..|
149 |..(padding)..|<------line-size------------->|..(padding)..|
151 where line-size is of the smaller (inter_size) image and the full padded line length is that of
152 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
153 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
154 specified *stride*. This does not matter until we get to the last line:
156 block start write start line end
157 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
158 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
159 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
162 To get around this, we ask Image to overallocate its buffers by the overrun.
165 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned, (out_size.width - inter_size.width) / 2));
168 /* Size of the image after any crop */
169 dcp::Size const cropped_size = crop.apply (size ());
171 /* Scale context for a scale from cropped_size to inter_size */
172 struct SwsContext* scale_context = sws_getContext (
173 cropped_size.width, cropped_size.height, pixel_format(),
174 inter_size.width, inter_size.height, out_format,
175 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
178 if (!scale_context) {
179 throw runtime_error (N_("Could not allocate SwsContext"));
182 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
183 int const lut[dcp::YUV_TO_RGB_COUNT] = {
188 /* The 3rd parameter here is:
189 0 -> source range MPEG (i.e. "video", 16-235)
190 1 -> source range JPEG (i.e. "full", 0-255)
192 0 -> destination range MPEG (i.e. "video", 16-235)
193 1 -> destination range JPEG (i.e. "full", 0-255)
195 But remember: sws_setColorspaceDetails ignores
196 these parameters unless the image isYUV or isGray
197 (if it's neither, it uses video range for source
200 sws_setColorspaceDetails (
202 sws_getCoefficients (lut[yuv_to_rgb]), 0,
203 sws_getCoefficients (lut[yuv_to_rgb]), 0,
207 AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
209 throw PixelFormatError ("crop_scale_window()", _pixel_format);
212 /* Prepare input data pointers with crop */
213 uint8_t* scale_in_data[planes()];
214 for (int c = 0; c < planes(); ++c) {
215 /* To work out the crop in bytes, start by multiplying
216 the crop by the (average) bytes per pixel. Then
217 round down so that we don't crop a subsampled pixel until
218 we've cropped all of its Y-channel pixels.
220 int const x = lrintf (bytes_per_pixel(c) * crop.left) & ~ ((int) in_desc->log2_chroma_w);
221 scale_in_data[c] = data()[c] + x + stride()[c] * (crop.top / vertical_factor(c));
224 /* Corner of the image within out_size */
225 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
227 AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
229 throw PixelFormatError ("crop_scale_window()", out_format);
232 uint8_t* scale_out_data[out->planes()];
233 for (int c = 0; c < out->planes(); ++c) {
234 /* See the note in the crop loop above */
235 int const x = lrintf (out->bytes_per_pixel(c) * corner.x) & ~ ((int) out_desc->log2_chroma_w);
236 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
241 scale_in_data, stride(),
242 0, cropped_size.height,
243 scale_out_data, out->stride()
246 sws_freeContext (scale_context);
252 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
254 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
257 /** @param out_size Size to scale to.
258 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
259 * @param out_format Output pixel format.
260 * @param out_aligned true to make an aligned output image.
261 * @param fast Try to be fast at the possible expense of quality; at present this means using
262 * fast bilinear rather than bicubic scaling.
265 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
267 /* Empirical testing suggests that sws_scale() will crash if
268 the input image is not aligned.
270 DCPOMATIC_ASSERT (aligned ());
272 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
274 struct SwsContext* scale_context = sws_getContext (
275 size().width, size().height, pixel_format(),
276 out_size.width, out_size.height, out_format,
277 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
280 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
281 int const lut[dcp::YUV_TO_RGB_COUNT] = {
286 /* The 3rd parameter here is:
287 0 -> source range MPEG (i.e. "video", 16-235)
288 1 -> source range JPEG (i.e. "full", 0-255)
290 0 -> destination range MPEG (i.e. "video", 16-235)
291 1 -> destination range JPEG (i.e. "full", 0-255)
293 But remember: sws_setColorspaceDetails ignores
294 these parameters unless the image isYUV or isGray
295 (if it's neither, it uses video range for source
298 sws_setColorspaceDetails (
300 sws_getCoefficients (lut[yuv_to_rgb]), 0,
301 sws_getCoefficients (lut[yuv_to_rgb]), 0,
309 scaled->data(), scaled->stride()
312 sws_freeContext (scale_context);
317 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
319 Image::yuv_16_black (uint16_t v, bool alpha)
321 memset (data()[0], 0, sample_size(0).height * stride()[0]);
322 for (int i = 1; i < 3; ++i) {
323 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
324 int const lines = sample_size(i).height;
325 for (int y = 0; y < lines; ++y) {
326 /* We divide by 2 here because we are writing 2 bytes at a time */
327 for (int x = 0; x < line_size()[i] / 2; ++x) {
330 p += stride()[i] / 2;
335 memset (data()[3], 0, sample_size(3).height * stride()[3]);
340 Image::swap_16 (uint16_t v)
342 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
348 /* U/V black value for 8-bit colour */
349 static uint8_t const eight_bit_uv = (1 << 7) - 1;
350 /* U/V black value for 9-bit colour */
351 static uint16_t const nine_bit_uv = (1 << 8) - 1;
352 /* U/V black value for 10-bit colour */
353 static uint16_t const ten_bit_uv = (1 << 9) - 1;
354 /* U/V black value for 16-bit colour */
355 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
357 switch (_pixel_format) {
358 case AV_PIX_FMT_YUV420P:
359 case AV_PIX_FMT_YUV422P:
360 case AV_PIX_FMT_YUV444P:
361 case AV_PIX_FMT_YUV411P:
362 memset (data()[0], 0, sample_size(0).height * stride()[0]);
363 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
364 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
367 case AV_PIX_FMT_YUVJ420P:
368 case AV_PIX_FMT_YUVJ422P:
369 case AV_PIX_FMT_YUVJ444P:
370 memset (data()[0], 0, sample_size(0).height * stride()[0]);
371 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
372 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
375 case AV_PIX_FMT_YUV422P9LE:
376 case AV_PIX_FMT_YUV444P9LE:
377 yuv_16_black (nine_bit_uv, false);
380 case AV_PIX_FMT_YUV422P9BE:
381 case AV_PIX_FMT_YUV444P9BE:
382 yuv_16_black (swap_16 (nine_bit_uv), false);
385 case AV_PIX_FMT_YUV422P10LE:
386 case AV_PIX_FMT_YUV444P10LE:
387 yuv_16_black (ten_bit_uv, false);
390 case AV_PIX_FMT_YUV422P16LE:
391 case AV_PIX_FMT_YUV444P16LE:
392 yuv_16_black (sixteen_bit_uv, false);
395 case AV_PIX_FMT_YUV444P10BE:
396 case AV_PIX_FMT_YUV422P10BE:
397 yuv_16_black (swap_16 (ten_bit_uv), false);
400 case AV_PIX_FMT_YUVA420P9BE:
401 case AV_PIX_FMT_YUVA422P9BE:
402 case AV_PIX_FMT_YUVA444P9BE:
403 yuv_16_black (swap_16 (nine_bit_uv), true);
406 case AV_PIX_FMT_YUVA420P9LE:
407 case AV_PIX_FMT_YUVA422P9LE:
408 case AV_PIX_FMT_YUVA444P9LE:
409 yuv_16_black (nine_bit_uv, true);
412 case AV_PIX_FMT_YUVA420P10BE:
413 case AV_PIX_FMT_YUVA422P10BE:
414 case AV_PIX_FMT_YUVA444P10BE:
415 yuv_16_black (swap_16 (ten_bit_uv), true);
418 case AV_PIX_FMT_YUVA420P10LE:
419 case AV_PIX_FMT_YUVA422P10LE:
420 case AV_PIX_FMT_YUVA444P10LE:
421 yuv_16_black (ten_bit_uv, true);
424 case AV_PIX_FMT_YUVA420P16BE:
425 case AV_PIX_FMT_YUVA422P16BE:
426 case AV_PIX_FMT_YUVA444P16BE:
427 yuv_16_black (swap_16 (sixteen_bit_uv), true);
430 case AV_PIX_FMT_YUVA420P16LE:
431 case AV_PIX_FMT_YUVA422P16LE:
432 case AV_PIX_FMT_YUVA444P16LE:
433 yuv_16_black (sixteen_bit_uv, true);
436 case AV_PIX_FMT_RGB24:
437 case AV_PIX_FMT_ARGB:
438 case AV_PIX_FMT_RGBA:
439 case AV_PIX_FMT_ABGR:
440 case AV_PIX_FMT_BGRA:
441 case AV_PIX_FMT_RGB555LE:
442 case AV_PIX_FMT_RGB48LE:
443 case AV_PIX_FMT_RGB48BE:
444 case AV_PIX_FMT_XYZ12LE:
445 memset (data()[0], 0, sample_size(0).height * stride()[0]);
448 case AV_PIX_FMT_UYVY422:
450 int const Y = sample_size(0).height;
451 int const X = line_size()[0];
452 uint8_t* p = data()[0];
453 for (int y = 0; y < Y; ++y) {
454 for (int x = 0; x < X / 4; ++x) {
455 *p++ = eight_bit_uv; // Cb
457 *p++ = eight_bit_uv; // Cr
465 throw PixelFormatError ("make_black()", _pixel_format);
470 Image::make_transparent ()
472 if (_pixel_format != AV_PIX_FMT_BGRA) {
473 throw PixelFormatError ("make_transparent()", _pixel_format);
476 memset (data()[0], 0, sample_size(0).height * stride()[0]);
480 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
482 /* We're blending BGRA images; first byte is blue, second byte is green, third byte red, fourth byte alpha */
483 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA);
484 int const other_bpp = 4;
486 int start_tx = position.x;
490 start_ox = -start_tx;
494 int start_ty = position.y;
498 start_oy = -start_ty;
502 switch (_pixel_format) {
503 case AV_PIX_FMT_RGB24:
505 /* Going onto RGB24. First byte is red, second green, third blue */
506 int const this_bpp = 3;
507 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
508 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
509 uint8_t* op = other->data()[0] + oy * other->stride()[0];
510 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
511 float const alpha = float (op[3]) / 255;
512 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
513 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
514 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
522 case AV_PIX_FMT_BGRA:
524 int const this_bpp = 4;
525 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
526 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
527 uint8_t* op = other->data()[0] + oy * other->stride()[0];
528 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
529 float const alpha = float (op[3]) / 255;
530 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
531 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
532 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
533 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
541 case AV_PIX_FMT_RGBA:
543 int const this_bpp = 4;
544 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
545 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
546 uint8_t* op = other->data()[0] + oy * other->stride()[0];
547 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
548 float const alpha = float (op[3]) / 255;
549 tp[0] = op[2] * alpha + tp[0] * (1 - alpha);
550 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
551 tp[2] = op[0] * alpha + tp[2] * (1 - alpha);
552 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
560 case AV_PIX_FMT_RGB48LE:
562 int const this_bpp = 6;
563 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
564 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
565 uint8_t* op = other->data()[0] + oy * other->stride()[0];
566 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
567 float const alpha = float (op[3]) / 255;
568 /* Blend high bytes */
569 tp[1] = op[2] * alpha + tp[1] * (1 - alpha);
570 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
571 tp[5] = op[0] * alpha + tp[5] * (1 - alpha);
579 case AV_PIX_FMT_XYZ12LE:
581 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
582 double fast_matrix[9];
583 dcp::combined_rgb_to_xyz (conv, fast_matrix);
584 double const * lut_in = conv.in()->lut (8, false);
585 double const * lut_out = conv.out()->lut (16, true);
586 int const this_bpp = 6;
587 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
588 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
589 uint8_t* op = other->data()[0] + oy * other->stride()[0];
590 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
591 float const alpha = float (op[3]) / 255;
593 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
594 double const r = lut_in[op[2]];
595 double const g = lut_in[op[1]];
596 double const b = lut_in[op[0]];
598 /* RGB to XYZ, including Bradford transform and DCI companding */
599 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
600 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
601 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
603 /* Out gamma LUT and blend */
604 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
605 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
606 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
614 case AV_PIX_FMT_YUV420P:
616 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
617 dcp::Size const ts = size();
618 dcp::Size const os = yuv->size();
619 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
620 int const hty = ty / 2;
621 int const hoy = oy / 2;
622 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
623 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
624 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
625 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
626 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
627 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
628 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
629 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
630 float const a = float(alpha[3]) / 255;
631 *tY = *oY * a + *tY * (1 - a);
632 *tU = *oU * a + *tU * (1 - a);
633 *tV = *oV * a + *tV * (1 - a);
649 case AV_PIX_FMT_YUV420P10:
651 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
652 dcp::Size const ts = size();
653 dcp::Size const os = yuv->size();
654 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
655 int const hty = ty / 2;
656 int const hoy = oy / 2;
657 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
658 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
659 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
660 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
661 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
662 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
663 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
664 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
665 float const a = float(alpha[3]) / 255;
666 *tY = *oY * a + *tY * (1 - a);
667 *tU = *oU * a + *tU * (1 - a);
668 *tV = *oV * a + *tV * (1 - a);
684 case AV_PIX_FMT_YUV422P10LE:
686 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
687 dcp::Size const ts = size();
688 dcp::Size const os = yuv->size();
689 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
690 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
691 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
692 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
693 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
694 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
695 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
696 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
697 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
698 float const a = float(alpha[3]) / 255;
699 *tY = *oY * a + *tY * (1 - a);
700 *tU = *oU * a + *tU * (1 - a);
701 *tV = *oV * a + *tV * (1 - a);
718 throw PixelFormatError ("alpha_blend()", _pixel_format);
723 Image::copy (shared_ptr<const Image> other, Position<int> position)
725 /* Only implemented for RGB24 onto RGB24 so far */
726 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
727 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
729 int const N = min (position.x + other->size().width, size().width) - position.x;
730 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
731 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
732 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
733 memcpy (tp, op, N * 3);
738 Image::read_from_socket (shared_ptr<Socket> socket)
740 for (int i = 0; i < planes(); ++i) {
741 uint8_t* p = data()[i];
742 int const lines = sample_size(i).height;
743 for (int y = 0; y < lines; ++y) {
744 socket->read (p, line_size()[i]);
751 Image::write_to_socket (shared_ptr<Socket> socket) const
753 for (int i = 0; i < planes(); ++i) {
754 uint8_t* p = data()[i];
755 int const lines = sample_size(i).height;
756 for (int y = 0; y < lines; ++y) {
757 socket->write (p, line_size()[i]);
764 Image::bytes_per_pixel (int c) const
766 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
768 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
775 float bpp[4] = { 0, 0, 0, 0 };
777 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
778 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
779 if (d->nb_components > 1) {
780 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
782 if (d->nb_components > 2) {
783 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
785 if (d->nb_components > 3) {
786 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
789 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
790 if (d->nb_components > 1) {
791 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
793 if (d->nb_components > 2) {
794 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
796 if (d->nb_components > 3) {
797 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
801 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
802 /* Not planar; sum them up */
803 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
809 /** Construct a Image of a given size and format, allocating memory
812 * @param p Pixel format.
813 * @param s Size in pixels.
814 * @param aligned true to make each row of this image aligned to a 32-byte boundary.
815 * @param extra_pixels Amount of extra "run-off" memory to allocate at the end of each plane in pixels.
817 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned, int extra_pixels)
821 , _extra_pixels (extra_pixels)
829 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
830 _data[0] = _data[1] = _data[2] = _data[3] = 0;
832 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
833 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
835 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
836 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
838 for (int i = 0; i < planes(); ++i) {
839 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
840 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
842 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
843 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
844 Hence on the last pixel of the last line it reads over the end of
845 the actual data by 1 byte. If the width of an image is a multiple
846 of the stride alignment there will be no padding at the end of image lines.
847 OS X crashes on this illegal read, though other operating systems don't
848 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
849 for that instruction to read safely.
851 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
852 over-reads by more then _avx. I can't follow the code to work out how much,
853 so I'll just over-allocate by 32 bytes and have done with it. Empirical
854 testing suggests that it works.
856 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
857 #if HAVE_VALGRIND_MEMCHECK_H
858 /* The data between the end of the line size and the stride is undefined but processed by
859 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
861 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
866 Image::Image (Image const & other)
867 : boost::enable_shared_from_this<Image>(other)
868 , _size (other._size)
869 , _pixel_format (other._pixel_format)
870 , _aligned (other._aligned)
871 , _extra_pixels (other._extra_pixels)
875 for (int i = 0; i < planes(); ++i) {
876 uint8_t* p = _data[i];
877 uint8_t* q = other._data[i];
878 int const lines = sample_size(i).height;
879 for (int j = 0; j < lines; ++j) {
880 memcpy (p, q, _line_size[i]);
882 q += other.stride()[i];
887 Image::Image (AVFrame* frame)
888 : _size (frame->width, frame->height)
889 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
895 for (int i = 0; i < planes(); ++i) {
896 uint8_t* p = _data[i];
897 uint8_t* q = frame->data[i];
898 int const lines = sample_size(i).height;
899 for (int j = 0; j < lines; ++j) {
900 memcpy (p, q, _line_size[i]);
902 /* AVFrame's linesize is what we call `stride' */
903 q += frame->linesize[i];
908 Image::Image (shared_ptr<const Image> other, bool aligned)
909 : _size (other->_size)
910 , _pixel_format (other->_pixel_format)
912 , _extra_pixels (other->_extra_pixels)
916 for (int i = 0; i < planes(); ++i) {
917 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
918 uint8_t* p = _data[i];
919 uint8_t* q = other->data()[i];
920 int const lines = sample_size(i).height;
921 for (int j = 0; j < lines; ++j) {
922 memcpy (p, q, line_size()[i]);
924 q += other->stride()[i];
930 Image::operator= (Image const & other)
932 if (this == &other) {
942 Image::swap (Image & other)
944 std::swap (_size, other._size);
945 std::swap (_pixel_format, other._pixel_format);
947 for (int i = 0; i < 4; ++i) {
948 std::swap (_data[i], other._data[i]);
949 std::swap (_line_size[i], other._line_size[i]);
950 std::swap (_stride[i], other._stride[i]);
953 std::swap (_aligned, other._aligned);
954 std::swap (_extra_pixels, other._extra_pixels);
957 /** Destroy a Image */
960 for (int i = 0; i < planes(); ++i) {
965 av_free (_line_size);
976 Image::line_size () const
982 Image::stride () const
994 Image::aligned () const
1000 merge (list<PositionImage> images)
1002 if (images.empty ()) {
1003 return PositionImage ();
1006 if (images.size() == 1) {
1007 return images.front ();
1010 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1011 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1012 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
1015 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
1016 merged->make_transparent ();
1017 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1018 merged->alpha_blend (i->image, i->position - all.position());
1021 return PositionImage (merged, all.position ());
1025 operator== (Image const & a, Image const & b)
1027 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1031 for (int c = 0; c < a.planes(); ++c) {
1032 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]) {
1036 uint8_t* p = a.data()[c];
1037 uint8_t* q = b.data()[c];
1038 int const lines = a.sample_size(c).height;
1039 for (int y = 0; y < lines; ++y) {
1040 if (memcmp (p, q, a.line_size()[c]) != 0) {
1053 * @param f Amount to fade by; 0 is black, 1 is no fade.
1056 Image::fade (float f)
1058 switch (_pixel_format) {
1059 case AV_PIX_FMT_YUV420P:
1060 case AV_PIX_FMT_YUV422P:
1061 case AV_PIX_FMT_YUV444P:
1062 case AV_PIX_FMT_YUV411P:
1063 case AV_PIX_FMT_YUVJ420P:
1064 case AV_PIX_FMT_YUVJ422P:
1065 case AV_PIX_FMT_YUVJ444P:
1066 case AV_PIX_FMT_RGB24:
1067 case AV_PIX_FMT_ARGB:
1068 case AV_PIX_FMT_RGBA:
1069 case AV_PIX_FMT_ABGR:
1070 case AV_PIX_FMT_BGRA:
1071 case AV_PIX_FMT_RGB555LE:
1073 for (int c = 0; c < 3; ++c) {
1074 uint8_t* p = data()[c];
1075 int const lines = sample_size(c).height;
1076 for (int y = 0; y < lines; ++y) {
1078 for (int x = 0; x < line_size()[c]; ++x) {
1079 *q = int (float (*q) * f);
1087 case AV_PIX_FMT_YUV422P9LE:
1088 case AV_PIX_FMT_YUV444P9LE:
1089 case AV_PIX_FMT_YUV422P10LE:
1090 case AV_PIX_FMT_YUV444P10LE:
1091 case AV_PIX_FMT_YUV422P16LE:
1092 case AV_PIX_FMT_YUV444P16LE:
1093 case AV_PIX_FMT_YUVA420P9LE:
1094 case AV_PIX_FMT_YUVA422P9LE:
1095 case AV_PIX_FMT_YUVA444P9LE:
1096 case AV_PIX_FMT_YUVA420P10LE:
1097 case AV_PIX_FMT_YUVA422P10LE:
1098 case AV_PIX_FMT_YUVA444P10LE:
1099 case AV_PIX_FMT_RGB48LE:
1100 case AV_PIX_FMT_XYZ12LE:
1101 /* 16-bit little-endian */
1102 for (int c = 0; c < 3; ++c) {
1103 int const stride_pixels = stride()[c] / 2;
1104 int const line_size_pixels = line_size()[c] / 2;
1105 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1106 int const lines = sample_size(c).height;
1107 for (int y = 0; y < lines; ++y) {
1109 for (int x = 0; x < line_size_pixels; ++x) {
1110 *q = int (float (*q) * f);
1118 case AV_PIX_FMT_YUV422P9BE:
1119 case AV_PIX_FMT_YUV444P9BE:
1120 case AV_PIX_FMT_YUV444P10BE:
1121 case AV_PIX_FMT_YUV422P10BE:
1122 case AV_PIX_FMT_YUVA420P9BE:
1123 case AV_PIX_FMT_YUVA422P9BE:
1124 case AV_PIX_FMT_YUVA444P9BE:
1125 case AV_PIX_FMT_YUVA420P10BE:
1126 case AV_PIX_FMT_YUVA422P10BE:
1127 case AV_PIX_FMT_YUVA444P10BE:
1128 case AV_PIX_FMT_YUVA420P16BE:
1129 case AV_PIX_FMT_YUVA422P16BE:
1130 case AV_PIX_FMT_YUVA444P16BE:
1131 case AV_PIX_FMT_RGB48BE:
1132 /* 16-bit big-endian */
1133 for (int c = 0; c < 3; ++c) {
1134 int const stride_pixels = stride()[c] / 2;
1135 int const line_size_pixels = line_size()[c] / 2;
1136 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1137 int const lines = sample_size(c).height;
1138 for (int y = 0; y < lines; ++y) {
1140 for (int x = 0; x < line_size_pixels; ++x) {
1141 *q = swap_16 (int (float (swap_16 (*q)) * f));
1149 case AV_PIX_FMT_UYVY422:
1151 int const Y = sample_size(0).height;
1152 int const X = line_size()[0];
1153 uint8_t* p = data()[0];
1154 for (int y = 0; y < Y; ++y) {
1155 for (int x = 0; x < X; ++x) {
1156 *p = int (float (*p) * f);
1164 throw PixelFormatError ("fade()", _pixel_format);
1168 shared_ptr<const Image>
1169 Image::ensure_aligned (shared_ptr<const Image> image)
1171 if (image->aligned()) {
1175 return shared_ptr<Image> (new Image (image, true));
1179 Image::memory_used () const
1182 for (int i = 0; i < planes(); ++i) {
1183 m += _stride[i] * sample_size(i).height;
1206 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1208 Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1209 size_t size = mem->size + length;
1212 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1214 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1218 throw EncodeError (N_("could not allocate memory for PNG"));
1221 memcpy (mem->data + mem->size, data, length);
1222 mem->size += length;
1226 png_flush (png_structp)
1232 png_error_fn (png_structp png_ptr, char const * message)
1234 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1238 Image::png_error (char const * message)
1240 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1244 Image::as_png () const
1246 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1247 DCPOMATIC_ASSERT (planes() == 1);
1248 DCPOMATIC_ASSERT (pixel_format() == AV_PIX_FMT_BGRA);
1250 /* error handling? */
1251 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1253 throw EncodeError (N_("could not create PNG write struct"));
1258 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1260 png_infop info_ptr = png_create_info_struct(png_ptr);
1262 png_destroy_write_struct (&png_ptr, &info_ptr);
1263 throw EncodeError (N_("could not create PNG info struct"));
1266 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);
1268 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1269 for (int i = 0; i < size().height; ++i) {
1270 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1273 png_write_info (png_ptr, info_ptr);
1274 png_write_image (png_ptr, row_pointers);
1275 png_write_end (png_ptr, info_ptr);
1277 png_destroy_write_struct (&png_ptr, &info_ptr);
1278 png_free (png_ptr, row_pointers);
1280 return dcp::Data (state.data, state.size);