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 RGBA or BGRA images */
483 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
484 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
485 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
487 int const other_bpp = 4;
489 int start_tx = position.x;
493 start_ox = -start_tx;
497 int start_ty = position.y;
501 start_oy = -start_ty;
505 switch (_pixel_format) {
506 case AV_PIX_FMT_RGB24:
508 /* Going onto RGB24. First byte is red, second green, third blue */
509 int const this_bpp = 3;
510 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
511 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
512 uint8_t* op = other->data()[0] + oy * other->stride()[0];
513 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
514 float const alpha = float (op[3]) / 255;
515 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
516 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
517 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
525 case AV_PIX_FMT_BGRA:
527 int const this_bpp = 4;
528 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
529 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
530 uint8_t* op = other->data()[0] + oy * other->stride()[0];
531 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
532 float const alpha = float (op[3]) / 255;
533 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
534 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
535 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
536 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
544 case AV_PIX_FMT_RGBA:
546 int const this_bpp = 4;
547 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
548 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
549 uint8_t* op = other->data()[0] + oy * other->stride()[0];
550 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
551 float const alpha = float (op[3]) / 255;
552 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
553 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
554 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
555 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
563 case AV_PIX_FMT_RGB48LE:
565 int const this_bpp = 6;
566 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
567 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
568 uint8_t* op = other->data()[0] + oy * other->stride()[0];
569 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
570 float const alpha = float (op[3]) / 255;
571 /* Blend high bytes */
572 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
573 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
574 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
582 case AV_PIX_FMT_XYZ12LE:
584 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
585 double fast_matrix[9];
586 dcp::combined_rgb_to_xyz (conv, fast_matrix);
587 double const * lut_in = conv.in()->lut (8, false);
588 double const * lut_out = conv.out()->lut (16, true);
589 int const this_bpp = 6;
590 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
591 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
592 uint8_t* op = other->data()[0] + oy * other->stride()[0];
593 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
594 float const alpha = float (op[3]) / 255;
596 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
597 double const r = lut_in[op[red]];
598 double const g = lut_in[op[1]];
599 double const b = lut_in[op[blue]];
601 /* RGB to XYZ, including Bradford transform and DCI companding */
602 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
603 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
604 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
606 /* Out gamma LUT and blend */
607 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
608 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
609 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
617 case AV_PIX_FMT_YUV420P:
619 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
620 dcp::Size const ts = size();
621 dcp::Size const os = yuv->size();
622 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
623 int const hty = ty / 2;
624 int const hoy = oy / 2;
625 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
626 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
627 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
628 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
629 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
630 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
631 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
632 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
633 float const a = float(alpha[3]) / 255;
634 *tY = *oY * a + *tY * (1 - a);
635 *tU = *oU * a + *tU * (1 - a);
636 *tV = *oV * a + *tV * (1 - a);
652 case AV_PIX_FMT_YUV420P10:
654 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
655 dcp::Size const ts = size();
656 dcp::Size const os = yuv->size();
657 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
658 int const hty = ty / 2;
659 int const hoy = oy / 2;
660 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
661 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
662 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * 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] + (hoy * yuv->stride()[1]))) + start_ox / 2;
665 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * 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);
687 case AV_PIX_FMT_YUV422P10LE:
689 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
690 dcp::Size const ts = size();
691 dcp::Size const os = yuv->size();
692 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
693 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
694 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
695 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
696 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
697 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
698 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
699 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
700 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
701 float const a = float(alpha[3]) / 255;
702 *tY = *oY * a + *tY * (1 - a);
703 *tU = *oU * a + *tU * (1 - a);
704 *tV = *oV * a + *tV * (1 - a);
721 throw PixelFormatError ("alpha_blend()", _pixel_format);
726 Image::copy (shared_ptr<const Image> other, Position<int> position)
728 /* Only implemented for RGB24 onto RGB24 so far */
729 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
730 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
732 int const N = min (position.x + other->size().width, size().width) - position.x;
733 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
734 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
735 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
736 memcpy (tp, op, N * 3);
741 Image::read_from_socket (shared_ptr<Socket> socket)
743 for (int i = 0; i < planes(); ++i) {
744 uint8_t* p = data()[i];
745 int const lines = sample_size(i).height;
746 for (int y = 0; y < lines; ++y) {
747 socket->read (p, line_size()[i]);
754 Image::write_to_socket (shared_ptr<Socket> socket) const
756 for (int i = 0; i < planes(); ++i) {
757 uint8_t* p = data()[i];
758 int const lines = sample_size(i).height;
759 for (int y = 0; y < lines; ++y) {
760 socket->write (p, line_size()[i]);
767 Image::bytes_per_pixel (int c) const
769 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
771 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
778 float bpp[4] = { 0, 0, 0, 0 };
780 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
781 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
782 if (d->nb_components > 1) {
783 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
785 if (d->nb_components > 2) {
786 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
788 if (d->nb_components > 3) {
789 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
792 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
793 if (d->nb_components > 1) {
794 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
796 if (d->nb_components > 2) {
797 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
799 if (d->nb_components > 3) {
800 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
804 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
805 /* Not planar; sum them up */
806 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
812 /** Construct a Image of a given size and format, allocating memory
815 * @param p Pixel format.
816 * @param s Size in pixels.
817 * @param aligned true to make each row of this image aligned to a 32-byte boundary.
818 * @param extra_pixels Amount of extra "run-off" memory to allocate at the end of each plane in pixels.
820 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned, int extra_pixels)
824 , _extra_pixels (extra_pixels)
832 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
833 _data[0] = _data[1] = _data[2] = _data[3] = 0;
835 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
836 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
838 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
839 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
841 for (int i = 0; i < planes(); ++i) {
842 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
843 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
845 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
846 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
847 Hence on the last pixel of the last line it reads over the end of
848 the actual data by 1 byte. If the width of an image is a multiple
849 of the stride alignment there will be no padding at the end of image lines.
850 OS X crashes on this illegal read, though other operating systems don't
851 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
852 for that instruction to read safely.
854 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
855 over-reads by more then _avx. I can't follow the code to work out how much,
856 so I'll just over-allocate by 32 bytes and have done with it. Empirical
857 testing suggests that it works.
859 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
860 #if HAVE_VALGRIND_MEMCHECK_H
861 /* The data between the end of the line size and the stride is undefined but processed by
862 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
864 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * sample_size(i).height + _extra_pixels * bytes_per_pixel(i) + 32);
869 Image::Image (Image const & other)
870 : boost::enable_shared_from_this<Image>(other)
871 , _size (other._size)
872 , _pixel_format (other._pixel_format)
873 , _aligned (other._aligned)
874 , _extra_pixels (other._extra_pixels)
878 for (int i = 0; i < planes(); ++i) {
879 uint8_t* p = _data[i];
880 uint8_t* q = other._data[i];
881 int const lines = sample_size(i).height;
882 for (int j = 0; j < lines; ++j) {
883 memcpy (p, q, _line_size[i]);
885 q += other.stride()[i];
890 Image::Image (AVFrame* frame)
891 : _size (frame->width, frame->height)
892 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
898 for (int i = 0; i < planes(); ++i) {
899 uint8_t* p = _data[i];
900 uint8_t* q = frame->data[i];
901 int const lines = sample_size(i).height;
902 for (int j = 0; j < lines; ++j) {
903 memcpy (p, q, _line_size[i]);
905 /* AVFrame's linesize is what we call `stride' */
906 q += frame->linesize[i];
911 Image::Image (shared_ptr<const Image> other, bool aligned)
912 : _size (other->_size)
913 , _pixel_format (other->_pixel_format)
915 , _extra_pixels (other->_extra_pixels)
919 for (int i = 0; i < planes(); ++i) {
920 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
921 uint8_t* p = _data[i];
922 uint8_t* q = other->data()[i];
923 int const lines = sample_size(i).height;
924 for (int j = 0; j < lines; ++j) {
925 memcpy (p, q, line_size()[i]);
927 q += other->stride()[i];
933 Image::operator= (Image const & other)
935 if (this == &other) {
945 Image::swap (Image & other)
947 std::swap (_size, other._size);
948 std::swap (_pixel_format, other._pixel_format);
950 for (int i = 0; i < 4; ++i) {
951 std::swap (_data[i], other._data[i]);
952 std::swap (_line_size[i], other._line_size[i]);
953 std::swap (_stride[i], other._stride[i]);
956 std::swap (_aligned, other._aligned);
957 std::swap (_extra_pixels, other._extra_pixels);
960 /** Destroy a Image */
963 for (int i = 0; i < planes(); ++i) {
968 av_free (_line_size);
979 Image::line_size () const
985 Image::stride () const
997 Image::aligned () const
1003 merge (list<PositionImage> images)
1005 if (images.empty ()) {
1006 return PositionImage ();
1009 if (images.size() == 1) {
1010 return images.front ();
1013 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1014 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1015 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
1018 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
1019 merged->make_transparent ();
1020 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1021 merged->alpha_blend (i->image, i->position - all.position());
1024 return PositionImage (merged, all.position ());
1028 operator== (Image const & a, Image const & b)
1030 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1034 for (int c = 0; c < a.planes(); ++c) {
1035 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]) {
1039 uint8_t* p = a.data()[c];
1040 uint8_t* q = b.data()[c];
1041 int const lines = a.sample_size(c).height;
1042 for (int y = 0; y < lines; ++y) {
1043 if (memcmp (p, q, a.line_size()[c]) != 0) {
1056 * @param f Amount to fade by; 0 is black, 1 is no fade.
1059 Image::fade (float f)
1061 switch (_pixel_format) {
1062 case AV_PIX_FMT_YUV420P:
1063 case AV_PIX_FMT_YUV422P:
1064 case AV_PIX_FMT_YUV444P:
1065 case AV_PIX_FMT_YUV411P:
1066 case AV_PIX_FMT_YUVJ420P:
1067 case AV_PIX_FMT_YUVJ422P:
1068 case AV_PIX_FMT_YUVJ444P:
1069 case AV_PIX_FMT_RGB24:
1070 case AV_PIX_FMT_ARGB:
1071 case AV_PIX_FMT_RGBA:
1072 case AV_PIX_FMT_ABGR:
1073 case AV_PIX_FMT_BGRA:
1074 case AV_PIX_FMT_RGB555LE:
1076 for (int c = 0; c < 3; ++c) {
1077 uint8_t* p = data()[c];
1078 int const lines = sample_size(c).height;
1079 for (int y = 0; y < lines; ++y) {
1081 for (int x = 0; x < line_size()[c]; ++x) {
1082 *q = int (float (*q) * f);
1090 case AV_PIX_FMT_YUV422P9LE:
1091 case AV_PIX_FMT_YUV444P9LE:
1092 case AV_PIX_FMT_YUV422P10LE:
1093 case AV_PIX_FMT_YUV444P10LE:
1094 case AV_PIX_FMT_YUV422P16LE:
1095 case AV_PIX_FMT_YUV444P16LE:
1096 case AV_PIX_FMT_YUVA420P9LE:
1097 case AV_PIX_FMT_YUVA422P9LE:
1098 case AV_PIX_FMT_YUVA444P9LE:
1099 case AV_PIX_FMT_YUVA420P10LE:
1100 case AV_PIX_FMT_YUVA422P10LE:
1101 case AV_PIX_FMT_YUVA444P10LE:
1102 case AV_PIX_FMT_RGB48LE:
1103 case AV_PIX_FMT_XYZ12LE:
1104 /* 16-bit little-endian */
1105 for (int c = 0; c < 3; ++c) {
1106 int const stride_pixels = stride()[c] / 2;
1107 int const line_size_pixels = line_size()[c] / 2;
1108 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1109 int const lines = sample_size(c).height;
1110 for (int y = 0; y < lines; ++y) {
1112 for (int x = 0; x < line_size_pixels; ++x) {
1113 *q = int (float (*q) * f);
1121 case AV_PIX_FMT_YUV422P9BE:
1122 case AV_PIX_FMT_YUV444P9BE:
1123 case AV_PIX_FMT_YUV444P10BE:
1124 case AV_PIX_FMT_YUV422P10BE:
1125 case AV_PIX_FMT_YUVA420P9BE:
1126 case AV_PIX_FMT_YUVA422P9BE:
1127 case AV_PIX_FMT_YUVA444P9BE:
1128 case AV_PIX_FMT_YUVA420P10BE:
1129 case AV_PIX_FMT_YUVA422P10BE:
1130 case AV_PIX_FMT_YUVA444P10BE:
1131 case AV_PIX_FMT_YUVA420P16BE:
1132 case AV_PIX_FMT_YUVA422P16BE:
1133 case AV_PIX_FMT_YUVA444P16BE:
1134 case AV_PIX_FMT_RGB48BE:
1135 /* 16-bit big-endian */
1136 for (int c = 0; c < 3; ++c) {
1137 int const stride_pixels = stride()[c] / 2;
1138 int const line_size_pixels = line_size()[c] / 2;
1139 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1140 int const lines = sample_size(c).height;
1141 for (int y = 0; y < lines; ++y) {
1143 for (int x = 0; x < line_size_pixels; ++x) {
1144 *q = swap_16 (int (float (swap_16 (*q)) * f));
1152 case AV_PIX_FMT_UYVY422:
1154 int const Y = sample_size(0).height;
1155 int const X = line_size()[0];
1156 uint8_t* p = data()[0];
1157 for (int y = 0; y < Y; ++y) {
1158 for (int x = 0; x < X; ++x) {
1159 *p = int (float (*p) * f);
1167 throw PixelFormatError ("fade()", _pixel_format);
1171 shared_ptr<const Image>
1172 Image::ensure_aligned (shared_ptr<const Image> image)
1174 if (image->aligned()) {
1178 return shared_ptr<Image> (new Image (image, true));
1182 Image::memory_used () const
1185 for (int i = 0; i < planes(); ++i) {
1186 m += _stride[i] * sample_size(i).height;
1209 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1211 Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1212 size_t size = mem->size + length;
1215 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1217 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1221 throw EncodeError (N_("could not allocate memory for PNG"));
1224 memcpy (mem->data + mem->size, data, length);
1225 mem->size += length;
1229 png_flush (png_structp)
1235 png_error_fn (png_structp png_ptr, char const * message)
1237 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1241 Image::png_error (char const * message)
1243 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1247 Image::as_png () const
1249 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1250 DCPOMATIC_ASSERT (planes() == 1);
1251 if (pixel_format() != AV_PIX_FMT_RGBA) {
1252 return convert_pixel_format(dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1255 /* error handling? */
1256 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1258 throw EncodeError (N_("could not create PNG write struct"));
1263 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1265 png_infop info_ptr = png_create_info_struct(png_ptr);
1267 png_destroy_write_struct (&png_ptr, &info_ptr);
1268 throw EncodeError (N_("could not create PNG info struct"));
1271 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);
1273 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1274 for (int i = 0; i < size().height; ++i) {
1275 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1278 png_write_info (png_ptr, info_ptr);
1279 png_write_image (png_ptr, row_pointers);
1280 png_write_end (png_ptr, info_ptr);
1282 png_destroy_write_struct (&png_ptr, &info_ptr);
1283 png_free (png_ptr, row_pointers);
1285 return dcp::Data (state.data, state.size);