2 Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 /** @file src/image.cc
22 * @brief A class to describe a video image.
26 #include "exceptions.h"
30 #include "compose.hpp"
31 #include "dcpomatic_socket.h"
32 #include <dcp/rgb_xyz.h>
33 #include <dcp/transfer_function.h>
35 #include <libswscale/swscale.h>
36 #include <libavutil/pixfmt.h>
37 #include <libavutil/pixdesc.h>
38 #include <libavutil/frame.h>
41 #if HAVE_VALGRIND_MEMCHECK_H
42 #include <valgrind/memcheck.h>
54 using std::runtime_error;
55 using boost::shared_ptr;
59 /** The memory alignment, in bytes, used for each row of an image if aligment is requested */
64 Image::vertical_factor (int n) const
70 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
72 throw PixelFormatError ("line_factor()", _pixel_format);
75 return lrintf(powf(2.0f, d->log2_chroma_h));
79 Image::horizontal_factor (int n) const
85 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
87 throw PixelFormatError ("sample_size()", _pixel_format);
90 return lrintf(powf(2.0f, d->log2_chroma_w));
93 /** @param n Component index.
94 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
97 Image::sample_size (int n) const
100 lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
101 lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
105 /** @return Number of planes */
107 Image::planes () const
109 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
111 throw PixelFormatError ("planes()", _pixel_format);
114 if (_pixel_format == AV_PIX_FMT_PAL8) {
118 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
122 return d->nb_components;
128 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
130 return p & ~ ((1 << desc->log2_chroma_w) - 1);
136 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
138 return p & ~ ((1 << desc->log2_chroma_h) - 1);
142 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
143 * @param crop Amount to crop by.
144 * @param inter_size Size to scale the cropped image to.
145 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
146 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
147 * @param video_range Video range of the image.
148 * @param out_format Output pixel format.
149 * @param out_aligned true to make the output image aligned.
150 * @param out_video_range Video range to use for the output image.
151 * @param fast Try to be fast at the possible expense of quality; at present this means using
152 * fast bilinear rather than bicubic scaling.
155 Image::crop_scale_window (
157 dcp::Size inter_size,
159 dcp::YUVToRGB yuv_to_rgb,
160 VideoRange video_range,
161 AVPixelFormat out_format,
162 VideoRange out_video_range,
167 /* Empirical testing suggests that sws_scale() will crash if
168 the input image is not aligned.
170 DCPOMATIC_ASSERT (aligned ());
172 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
173 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
175 shared_ptr<Image> out (new Image(out_format, out_size, out_aligned));
178 AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
180 throw PixelFormatError ("crop_scale_window()", _pixel_format);
183 /* Round down so that we crop only the number of pixels that is straightforward
184 * considering any subsampling.
187 round_width_for_subsampling(crop.left, in_desc),
188 round_width_for_subsampling(crop.right, in_desc),
189 round_height_for_subsampling(crop.top, in_desc),
190 round_height_for_subsampling(crop.bottom, in_desc)
193 /* Size of the image after any crop */
194 dcp::Size const cropped_size = rounded_crop.apply (size());
196 /* Scale context for a scale from cropped_size to inter_size */
197 struct SwsContext* scale_context = sws_getContext (
198 cropped_size.width, cropped_size.height, pixel_format(),
199 inter_size.width, inter_size.height, out_format,
200 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
203 if (!scale_context) {
204 throw runtime_error (N_("Could not allocate SwsContext"));
207 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
208 int const lut[dcp::YUV_TO_RGB_COUNT] = {
213 /* The 3rd parameter here is:
214 0 -> source range MPEG (i.e. "video", 16-235)
215 1 -> source range JPEG (i.e. "full", 0-255)
217 0 -> destination range MPEG (i.e. "video", 16-235)
218 1 -> destination range JPEG (i.e. "full", 0-255)
220 But remember: sws_setColorspaceDetails ignores these
221 parameters unless the both source and destination images
222 are isYUV or isGray. (If either is not, it uses video range).
224 sws_setColorspaceDetails (
226 sws_getCoefficients (lut[yuv_to_rgb]), video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
227 sws_getCoefficients (lut[yuv_to_rgb]), out_video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
231 /* Prepare input data pointers with crop */
232 uint8_t* scale_in_data[planes()];
233 for (int c = 0; c < planes(); ++c) {
234 int const x = lrintf(bytes_per_pixel(c) * rounded_crop.left);
235 scale_in_data[c] = data()[c] + x + stride()[c] * (rounded_crop.top / vertical_factor(c));
238 AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
240 throw PixelFormatError ("crop_scale_window()", out_format);
243 /* Corner of the image within out_size */
244 Position<int> const corner (
245 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
246 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
249 uint8_t* scale_out_data[out->planes()];
250 for (int c = 0; c < out->planes(); ++c) {
251 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
252 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
257 scale_in_data, stride(),
258 0, cropped_size.height,
259 scale_out_data, out->stride()
262 sws_freeContext (scale_context);
264 if (rounded_crop != Crop() && cropped_size == inter_size) {
265 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
266 data behind in our image. Clear it out. It may get to the point where we should just stop
267 trying to be clever with cropping.
269 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
276 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
278 return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
281 /** @param out_size Size to scale to.
282 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
283 * @param out_format Output pixel format.
284 * @param out_aligned true to make an aligned output image.
285 * @param fast Try to be fast at the possible expense of quality; at present this means using
286 * fast bilinear rather than bicubic scaling.
289 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
291 /* Empirical testing suggests that sws_scale() will crash if
292 the input image is not aligned.
294 DCPOMATIC_ASSERT (aligned ());
296 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
298 struct SwsContext* scale_context = sws_getContext (
299 size().width, size().height, pixel_format(),
300 out_size.width, out_size.height, out_format,
301 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
304 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
305 int const lut[dcp::YUV_TO_RGB_COUNT] = {
310 /* The 3rd parameter here is:
311 0 -> source range MPEG (i.e. "video", 16-235)
312 1 -> source range JPEG (i.e. "full", 0-255)
314 0 -> destination range MPEG (i.e. "video", 16-235)
315 1 -> destination range JPEG (i.e. "full", 0-255)
317 But remember: sws_setColorspaceDetails ignores these
318 parameters unless the corresponding image isYUV or isGray.
319 (If it's neither, it uses video range).
321 sws_setColorspaceDetails (
323 sws_getCoefficients (lut[yuv_to_rgb]), 0,
324 sws_getCoefficients (lut[yuv_to_rgb]), 0,
332 scaled->data(), scaled->stride()
335 sws_freeContext (scale_context);
340 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
342 Image::yuv_16_black (uint16_t v, bool alpha)
344 memset (data()[0], 0, sample_size(0).height * stride()[0]);
345 for (int i = 1; i < 3; ++i) {
346 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
347 int const lines = sample_size(i).height;
348 for (int y = 0; y < lines; ++y) {
349 /* We divide by 2 here because we are writing 2 bytes at a time */
350 for (int x = 0; x < line_size()[i] / 2; ++x) {
353 p += stride()[i] / 2;
358 memset (data()[3], 0, sample_size(3).height * stride()[3]);
363 Image::swap_16 (uint16_t v)
365 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
369 Image::make_part_black (int x, int w)
371 switch (_pixel_format) {
372 case AV_PIX_FMT_RGB24:
373 case AV_PIX_FMT_ARGB:
374 case AV_PIX_FMT_RGBA:
375 case AV_PIX_FMT_ABGR:
376 case AV_PIX_FMT_BGRA:
377 case AV_PIX_FMT_RGB555LE:
378 case AV_PIX_FMT_RGB48LE:
379 case AV_PIX_FMT_RGB48BE:
380 case AV_PIX_FMT_XYZ12LE:
382 int const h = sample_size(0).height;
383 int const bpp = bytes_per_pixel(0);
384 int const s = stride()[0];
385 uint8_t* p = data()[0];
386 for (int y = 0; y < h; y++) {
387 memset (p + x * bpp, 0, w * bpp);
394 throw PixelFormatError ("make_part_black()", _pixel_format);
401 /* U/V black value for 8-bit colour */
402 static uint8_t const eight_bit_uv = (1 << 7) - 1;
403 /* U/V black value for 9-bit colour */
404 static uint16_t const nine_bit_uv = (1 << 8) - 1;
405 /* U/V black value for 10-bit colour */
406 static uint16_t const ten_bit_uv = (1 << 9) - 1;
407 /* U/V black value for 16-bit colour */
408 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
410 switch (_pixel_format) {
411 case AV_PIX_FMT_YUV420P:
412 case AV_PIX_FMT_YUV422P:
413 case AV_PIX_FMT_YUV444P:
414 case AV_PIX_FMT_YUV411P:
415 memset (data()[0], 0, sample_size(0).height * stride()[0]);
416 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
417 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
420 case AV_PIX_FMT_YUVJ420P:
421 case AV_PIX_FMT_YUVJ422P:
422 case AV_PIX_FMT_YUVJ444P:
423 memset (data()[0], 0, sample_size(0).height * stride()[0]);
424 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
425 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
428 case AV_PIX_FMT_YUV422P9LE:
429 case AV_PIX_FMT_YUV444P9LE:
430 yuv_16_black (nine_bit_uv, false);
433 case AV_PIX_FMT_YUV422P9BE:
434 case AV_PIX_FMT_YUV444P9BE:
435 yuv_16_black (swap_16 (nine_bit_uv), false);
438 case AV_PIX_FMT_YUV422P10LE:
439 case AV_PIX_FMT_YUV444P10LE:
440 yuv_16_black (ten_bit_uv, false);
443 case AV_PIX_FMT_YUV422P16LE:
444 case AV_PIX_FMT_YUV444P16LE:
445 yuv_16_black (sixteen_bit_uv, false);
448 case AV_PIX_FMT_YUV444P10BE:
449 case AV_PIX_FMT_YUV422P10BE:
450 yuv_16_black (swap_16 (ten_bit_uv), false);
453 case AV_PIX_FMT_YUVA420P9BE:
454 case AV_PIX_FMT_YUVA422P9BE:
455 case AV_PIX_FMT_YUVA444P9BE:
456 yuv_16_black (swap_16 (nine_bit_uv), true);
459 case AV_PIX_FMT_YUVA420P9LE:
460 case AV_PIX_FMT_YUVA422P9LE:
461 case AV_PIX_FMT_YUVA444P9LE:
462 yuv_16_black (nine_bit_uv, true);
465 case AV_PIX_FMT_YUVA420P10BE:
466 case AV_PIX_FMT_YUVA422P10BE:
467 case AV_PIX_FMT_YUVA444P10BE:
468 yuv_16_black (swap_16 (ten_bit_uv), true);
471 case AV_PIX_FMT_YUVA420P10LE:
472 case AV_PIX_FMT_YUVA422P10LE:
473 case AV_PIX_FMT_YUVA444P10LE:
474 yuv_16_black (ten_bit_uv, true);
477 case AV_PIX_FMT_YUVA420P16BE:
478 case AV_PIX_FMT_YUVA422P16BE:
479 case AV_PIX_FMT_YUVA444P16BE:
480 yuv_16_black (swap_16 (sixteen_bit_uv), true);
483 case AV_PIX_FMT_YUVA420P16LE:
484 case AV_PIX_FMT_YUVA422P16LE:
485 case AV_PIX_FMT_YUVA444P16LE:
486 yuv_16_black (sixteen_bit_uv, true);
489 case AV_PIX_FMT_RGB24:
490 case AV_PIX_FMT_ARGB:
491 case AV_PIX_FMT_RGBA:
492 case AV_PIX_FMT_ABGR:
493 case AV_PIX_FMT_BGRA:
494 case AV_PIX_FMT_RGB555LE:
495 case AV_PIX_FMT_RGB48LE:
496 case AV_PIX_FMT_RGB48BE:
497 case AV_PIX_FMT_XYZ12LE:
498 memset (data()[0], 0, sample_size(0).height * stride()[0]);
501 case AV_PIX_FMT_UYVY422:
503 int const Y = sample_size(0).height;
504 int const X = line_size()[0];
505 uint8_t* p = data()[0];
506 for (int y = 0; y < Y; ++y) {
507 for (int x = 0; x < X / 4; ++x) {
508 *p++ = eight_bit_uv; // Cb
510 *p++ = eight_bit_uv; // Cr
518 throw PixelFormatError ("make_black()", _pixel_format);
523 Image::make_transparent ()
525 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
526 throw PixelFormatError ("make_transparent()", _pixel_format);
529 memset (data()[0], 0, sample_size(0).height * stride()[0]);
533 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
535 /* We're blending RGBA or BGRA images */
536 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
537 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
538 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
540 int const other_bpp = 4;
542 int start_tx = position.x;
546 start_ox = -start_tx;
550 int start_ty = position.y;
554 start_oy = -start_ty;
558 switch (_pixel_format) {
559 case AV_PIX_FMT_RGB24:
561 /* Going onto RGB24. First byte is red, second green, third blue */
562 int const this_bpp = 3;
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 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
569 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
570 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
578 case AV_PIX_FMT_BGRA:
580 int const this_bpp = 4;
581 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
582 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
583 uint8_t* op = other->data()[0] + oy * other->stride()[0];
584 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
585 float const alpha = float (op[3]) / 255;
586 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
587 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
588 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
589 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
597 case AV_PIX_FMT_RGBA:
599 int const this_bpp = 4;
600 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
601 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
602 uint8_t* op = other->data()[0] + oy * other->stride()[0];
603 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
604 float const alpha = float (op[3]) / 255;
605 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
606 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
607 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
608 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
616 case AV_PIX_FMT_RGB48LE:
618 int const this_bpp = 6;
619 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
620 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
621 uint8_t* op = other->data()[0] + oy * other->stride()[0];
622 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
623 float const alpha = float (op[3]) / 255;
624 /* Blend high bytes */
625 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
626 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
627 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
635 case AV_PIX_FMT_XYZ12LE:
637 dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
638 double fast_matrix[9];
639 dcp::combined_rgb_to_xyz (conv, fast_matrix);
640 double const * lut_in = conv.in()->lut (8, false);
641 double const * lut_out = conv.out()->lut (16, true);
642 int const this_bpp = 6;
643 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
644 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
645 uint8_t* op = other->data()[0] + oy * other->stride()[0];
646 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
647 float const alpha = float (op[3]) / 255;
649 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
650 double const r = lut_in[op[red]];
651 double const g = lut_in[op[1]];
652 double const b = lut_in[op[blue]];
654 /* RGB to XYZ, including Bradford transform and DCI companding */
655 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
656 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
657 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
659 /* Out gamma LUT and blend */
660 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
661 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
662 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
670 case AV_PIX_FMT_YUV420P:
672 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
673 dcp::Size const ts = size();
674 dcp::Size const os = yuv->size();
675 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
676 int const hty = ty / 2;
677 int const hoy = oy / 2;
678 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
679 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
680 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
681 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
682 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
683 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
684 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
685 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
686 float const a = float(alpha[3]) / 255;
687 *tY = *oY * a + *tY * (1 - a);
688 *tU = *oU * a + *tU * (1 - a);
689 *tV = *oV * a + *tV * (1 - a);
705 case AV_PIX_FMT_YUV420P10:
707 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
708 dcp::Size const ts = size();
709 dcp::Size const os = yuv->size();
710 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
711 int const hty = ty / 2;
712 int const hoy = oy / 2;
713 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
714 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
715 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
716 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
717 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
718 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
719 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
720 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
721 float const a = float(alpha[3]) / 255;
722 *tY = *oY * a + *tY * (1 - a);
723 *tU = *oU * a + *tU * (1 - a);
724 *tV = *oV * a + *tV * (1 - a);
740 case AV_PIX_FMT_YUV422P10LE:
742 shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
743 dcp::Size const ts = size();
744 dcp::Size const os = yuv->size();
745 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
746 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
747 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
748 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
749 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
750 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
751 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
752 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
753 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
754 float const a = float(alpha[3]) / 255;
755 *tY = *oY * a + *tY * (1 - a);
756 *tU = *oU * a + *tU * (1 - a);
757 *tV = *oV * a + *tV * (1 - a);
774 throw PixelFormatError ("alpha_blend()", _pixel_format);
779 Image::copy (shared_ptr<const Image> other, Position<int> position)
781 /* Only implemented for RGB24 onto RGB24 so far */
782 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
783 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
785 int const N = min (position.x + other->size().width, size().width) - position.x;
786 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
787 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
788 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
789 memcpy (tp, op, N * 3);
794 Image::read_from_socket (shared_ptr<Socket> socket)
796 for (int i = 0; i < planes(); ++i) {
797 uint8_t* p = data()[i];
798 int const lines = sample_size(i).height;
799 for (int y = 0; y < lines; ++y) {
800 socket->read (p, line_size()[i]);
807 Image::write_to_socket (shared_ptr<Socket> socket) const
809 for (int i = 0; i < planes(); ++i) {
810 uint8_t* p = data()[i];
811 int const lines = sample_size(i).height;
812 for (int y = 0; y < lines; ++y) {
813 socket->write (p, line_size()[i]);
820 Image::bytes_per_pixel (int c) const
822 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
824 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
831 float bpp[4] = { 0, 0, 0, 0 };
833 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
834 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
835 if (d->nb_components > 1) {
836 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
838 if (d->nb_components > 2) {
839 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
841 if (d->nb_components > 3) {
842 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
845 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
846 if (d->nb_components > 1) {
847 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
849 if (d->nb_components > 2) {
850 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
852 if (d->nb_components > 3) {
853 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
857 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
858 /* Not planar; sum them up */
859 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
865 /** Construct a Image of a given size and format, allocating memory
868 * @param p Pixel format.
869 * @param s Size in pixels.
870 * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
872 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
883 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
884 _data[0] = _data[1] = _data[2] = _data[3] = 0;
886 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
887 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
889 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
890 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
892 for (int i = 0; i < planes(); ++i) {
893 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
894 _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
896 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
897 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
898 Hence on the last pixel of the last line it reads over the end of
899 the actual data by 1 byte. If the width of an image is a multiple
900 of the stride alignment there will be no padding at the end of image lines.
901 OS X crashes on this illegal read, though other operating systems don't
902 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
903 for that instruction to read safely.
905 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
906 over-reads by more then _avx. I can't follow the code to work out how much,
907 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
908 testing suggests that it works.
910 In addition to these concerns, we may read/write as much as a whole extra line
911 at the end of each plane in cases where we are messing with offsets in order to
912 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
914 As an example: we may write to images starting at an offset so we get some padding.
915 Hence we want to write in the following pattern:
917 block start write start line end
918 |..(padding)..|<------line-size------------->|..(padding)..|
919 |..(padding)..|<------line-size------------->|..(padding)..|
920 |..(padding)..|<------line-size------------->|..(padding)..|
922 where line-size is of the smaller (inter_size) image and the full padded line length is that of
923 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
924 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
925 specified *stride*. This does not matter until we get to the last line:
927 block start write start line end
928 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
929 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
930 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
933 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
934 #if HAVE_VALGRIND_MEMCHECK_H
935 /* The data between the end of the line size and the stride is undefined but processed by
936 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
938 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
943 Image::Image (Image const & other)
944 : boost::enable_shared_from_this<Image>(other)
945 , _size (other._size)
946 , _pixel_format (other._pixel_format)
947 , _aligned (other._aligned)
951 for (int i = 0; i < planes(); ++i) {
952 uint8_t* p = _data[i];
953 uint8_t* q = other._data[i];
954 int const lines = sample_size(i).height;
955 for (int j = 0; j < lines; ++j) {
956 memcpy (p, q, _line_size[i]);
958 q += other.stride()[i];
963 Image::Image (AVFrame* frame)
964 : _size (frame->width, frame->height)
965 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
970 for (int i = 0; i < planes(); ++i) {
971 uint8_t* p = _data[i];
972 uint8_t* q = frame->data[i];
973 int const lines = sample_size(i).height;
974 for (int j = 0; j < lines; ++j) {
975 memcpy (p, q, _line_size[i]);
977 /* AVFrame's linesize is what we call `stride' */
978 q += frame->linesize[i];
983 Image::Image (shared_ptr<const Image> other, bool aligned)
984 : _size (other->_size)
985 , _pixel_format (other->_pixel_format)
990 for (int i = 0; i < planes(); ++i) {
991 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
992 uint8_t* p = _data[i];
993 uint8_t* q = other->data()[i];
994 int const lines = sample_size(i).height;
995 for (int j = 0; j < lines; ++j) {
996 memcpy (p, q, line_size()[i]);
998 q += other->stride()[i];
1004 Image::operator= (Image const & other)
1006 if (this == &other) {
1016 Image::swap (Image & other)
1018 std::swap (_size, other._size);
1019 std::swap (_pixel_format, other._pixel_format);
1021 for (int i = 0; i < 4; ++i) {
1022 std::swap (_data[i], other._data[i]);
1023 std::swap (_line_size[i], other._line_size[i]);
1024 std::swap (_stride[i], other._stride[i]);
1027 std::swap (_aligned, other._aligned);
1032 for (int i = 0; i < planes(); ++i) {
1037 av_free (_line_size);
1042 Image::data () const
1048 Image::line_size () const
1054 Image::stride () const
1060 Image::size () const
1066 Image::aligned () const
1072 merge (list<PositionImage> images)
1074 if (images.empty ()) {
1075 return PositionImage ();
1078 if (images.size() == 1) {
1079 return images.front ();
1082 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1083 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1084 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
1087 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
1088 merged->make_transparent ();
1089 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
1090 merged->alpha_blend (i->image, i->position - all.position());
1093 return PositionImage (merged, all.position ());
1097 operator== (Image const & a, Image const & b)
1099 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
1103 for (int c = 0; c < a.planes(); ++c) {
1104 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]) {
1108 uint8_t* p = a.data()[c];
1109 uint8_t* q = b.data()[c];
1110 int const lines = a.sample_size(c).height;
1111 for (int y = 0; y < lines; ++y) {
1112 if (memcmp (p, q, a.line_size()[c]) != 0) {
1125 * @param f Amount to fade by; 0 is black, 1 is no fade.
1128 Image::fade (float f)
1130 /* U/V black value for 8-bit colour */
1131 static int const eight_bit_uv = (1 << 7) - 1;
1132 /* U/V black value for 10-bit colour */
1133 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1135 switch (_pixel_format) {
1136 case AV_PIX_FMT_YUV420P:
1139 uint8_t* p = data()[0];
1140 int const lines = sample_size(0).height;
1141 for (int y = 0; y < lines; ++y) {
1143 for (int x = 0; x < line_size()[0]; ++x) {
1144 *q = int(float(*q) * f);
1151 for (int c = 1; c < 3; ++c) {
1152 uint8_t* p = data()[c];
1153 int const lines = sample_size(c).height;
1154 for (int y = 0; y < lines; ++y) {
1156 for (int x = 0; x < line_size()[c]; ++x) {
1157 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1167 case AV_PIX_FMT_RGB24:
1170 uint8_t* p = data()[0];
1171 int const lines = sample_size(0).height;
1172 for (int y = 0; y < lines; ++y) {
1174 for (int x = 0; x < line_size()[0]; ++x) {
1175 *q = int (float (*q) * f);
1183 case AV_PIX_FMT_XYZ12LE:
1184 case AV_PIX_FMT_RGB48LE:
1185 /* 16-bit little-endian */
1186 for (int c = 0; c < 3; ++c) {
1187 int const stride_pixels = stride()[c] / 2;
1188 int const line_size_pixels = line_size()[c] / 2;
1189 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1190 int const lines = sample_size(c).height;
1191 for (int y = 0; y < lines; ++y) {
1193 for (int x = 0; x < line_size_pixels; ++x) {
1194 *q = int (float (*q) * f);
1202 case AV_PIX_FMT_YUV422P10LE:
1206 int const stride_pixels = stride()[0] / 2;
1207 int const line_size_pixels = line_size()[0] / 2;
1208 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1209 int const lines = sample_size(0).height;
1210 for (int y = 0; y < lines; ++y) {
1212 for (int x = 0; x < line_size_pixels; ++x) {
1213 *q = int(float(*q) * f);
1221 for (int c = 1; c < 3; ++c) {
1222 int const stride_pixels = stride()[c] / 2;
1223 int const line_size_pixels = line_size()[c] / 2;
1224 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1225 int const lines = sample_size(c).height;
1226 for (int y = 0; y < lines; ++y) {
1228 for (int x = 0; x < line_size_pixels; ++x) {
1229 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1240 throw PixelFormatError ("fade()", _pixel_format);
1244 shared_ptr<const Image>
1245 Image::ensure_aligned (shared_ptr<const Image> image)
1247 if (image->aligned()) {
1251 return shared_ptr<Image> (new Image (image, true));
1255 Image::memory_used () const
1258 for (int i = 0; i < planes(); ++i) {
1259 m += _stride[i] * sample_size(i).height;
1282 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
1284 Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
1285 size_t size = mem->size + length;
1288 mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
1290 mem->data = reinterpret_cast<uint8_t*>(malloc(size));
1294 throw EncodeError (N_("could not allocate memory for PNG"));
1297 memcpy (mem->data + mem->size, data, length);
1298 mem->size += length;
1302 png_flush (png_structp)
1308 png_error_fn (png_structp png_ptr, char const * message)
1310 reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
1314 Image::png_error (char const * message)
1316 throw EncodeError (String::compose ("Error during PNG write: %1", message));
1320 Image::as_png () const
1322 DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
1323 DCPOMATIC_ASSERT (planes() == 1);
1324 if (pixel_format() != AV_PIX_FMT_RGBA) {
1325 return convert_pixel_format(dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
1328 /* error handling? */
1329 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
1331 throw EncodeError (N_("could not create PNG write struct"));
1336 png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
1338 png_infop info_ptr = png_create_info_struct(png_ptr);
1340 png_destroy_write_struct (&png_ptr, &info_ptr);
1341 throw EncodeError (N_("could not create PNG info struct"));
1344 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);
1346 png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
1347 for (int i = 0; i < size().height; ++i) {
1348 row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
1351 png_write_info (png_ptr, info_ptr);
1352 png_write_image (png_ptr, row_pointers);
1353 png_write_end (png_ptr, info_ptr);
1355 png_destroy_write_struct (&png_ptr, &info_ptr);
1356 png_free (png_ptr, row_pointers);
1358 return dcp::ArrayData (state.data, state.size);
1363 Image::video_range_to_full_range ()
1365 switch (_pixel_format) {
1366 case AV_PIX_FMT_RGB24:
1368 float const factor = 256.0 / 219.0;
1369 uint8_t* p = data()[0];
1370 int const lines = sample_size(0).height;
1371 for (int y = 0; y < lines; ++y) {
1373 for (int x = 0; x < line_size()[0]; ++x) {
1374 *q = int((*q - 16) * factor);
1381 case AV_PIX_FMT_GBRP12LE:
1383 float const factor = 4096.0 / 3504.0;
1384 for (int c = 0; c < 3; ++c) {
1385 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1386 int const lines = sample_size(c).height;
1387 for (int y = 0; y < lines; ++y) {
1389 int const line_size_pixels = line_size()[c] / 2;
1390 for (int x = 0; x < line_size_pixels; ++x) {
1391 *q = int((*q - 256) * factor);
1399 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);