2 Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /** @file src/image.cc
21 * @brief A class to describe a video image.
26 #include <libswscale/swscale.h>
27 #include <libavutil/pixfmt.h>
28 #include <libavutil/pixdesc.h>
31 #include "exceptions.h"
43 using boost::shared_ptr;
47 Image::line_factor (int n) const
53 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
55 throw PixelFormatError ("lines()", _pixel_format);
58 return pow (2.0f, d->log2_chroma_h);
61 /** @param n Component index.
62 * @return Number of lines in the image for the given component.
65 Image::lines (int n) const
67 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
70 /** @return Number of components */
72 Image::components () const
74 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
76 throw PixelFormatError ("components()", _pixel_format);
79 if ((d->flags & PIX_FMT_PLANAR) == 0) {
83 return d->nb_components;
86 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
88 Image::crop_scale_window (Crop crop, dcp::Size inter_size, dcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
91 /* Empirical testing suggests that sws_scale() will crash if
92 the input image is not aligned.
96 assert (out_size.width >= inter_size.width);
97 assert (out_size.height >= inter_size.height);
99 /* Here's an image of out_size */
100 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned));
103 /* Size of the image after any crop */
104 dcp::Size const cropped_size = crop.apply (size ());
106 /* Scale context for a scale from cropped_size to inter_size */
107 struct SwsContext* scale_context = sws_getContext (
108 cropped_size.width, cropped_size.height, pixel_format(),
109 inter_size.width, inter_size.height, out_format,
110 scaler->ffmpeg_id (), 0, 0, 0
113 if (!scale_context) {
114 throw StringError (N_("Could not allocate SwsContext"));
117 /* Prepare input data pointers with crop */
118 uint8_t* scale_in_data[components()];
119 for (int c = 0; c < components(); ++c) {
120 scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c));
123 /* Corner of the image within out_size */
124 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
126 uint8_t* scale_out_data[out->components()];
127 for (int c = 0; c < out->components(); ++c) {
128 scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y;
133 scale_in_data, stride(),
134 0, cropped_size.height,
135 scale_out_data, out->stride()
138 sws_freeContext (scale_context);
144 Image::scale (dcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
147 /* Empirical testing suggests that sws_scale() will crash if
148 the input image is not aligned.
152 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
154 struct SwsContext* scale_context = sws_getContext (
155 size().width, size().height, pixel_format(),
156 out_size.width, out_size.height, out_format,
157 scaler->ffmpeg_id (), 0, 0, 0
164 scaled->data(), scaled->stride()
167 sws_freeContext (scale_context);
173 Image::crop (Crop crop, bool aligned) const
175 dcp::Size cropped_size = crop.apply (size ());
176 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
178 for (int c = 0; c < components(); ++c) {
179 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
180 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
181 up, and we need to make sure that we copy over the width (up to the stride)
182 rather than short of the width; hence the ceil() here.
184 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
186 /* Start of the source line, cropped from the top but not the left */
187 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
188 uint8_t* out_p = out->data()[c];
190 for (int y = 0; y < out->lines(c); ++y) {
191 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
193 out_p += out->stride()[c];
200 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
202 Image::yuv_16_black (uint16_t v, bool alpha)
204 memset (data()[0], 0, lines(0) * stride()[0]);
205 for (int i = 1; i < 3; ++i) {
206 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
207 for (int y = 0; y < lines(i); ++y) {
208 /* We divide by 2 here because we are writing 2 bytes at a time */
209 for (int x = 0; x < line_size()[i] / 2; ++x) {
212 p += stride()[i] / 2;
217 memset (data()[3], 0, lines(3) * stride()[3]);
222 Image::swap_16 (uint16_t v)
224 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
230 /* U/V black value for 8-bit colour */
231 static uint8_t const eight_bit_uv = (1 << 7) - 1;
232 /* U/V black value for 9-bit colour */
233 static uint16_t const nine_bit_uv = (1 << 8) - 1;
234 /* U/V black value for 10-bit colour */
235 static uint16_t const ten_bit_uv = (1 << 9) - 1;
236 /* U/V black value for 16-bit colour */
237 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
239 switch (_pixel_format) {
240 case PIX_FMT_YUV420P:
241 case PIX_FMT_YUV422P:
242 case PIX_FMT_YUV444P:
243 case PIX_FMT_YUV411P:
244 memset (data()[0], 0, lines(0) * stride()[0]);
245 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
246 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
249 case PIX_FMT_YUVJ420P:
250 case PIX_FMT_YUVJ422P:
251 case PIX_FMT_YUVJ444P:
252 memset (data()[0], 0, lines(0) * stride()[0]);
253 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
254 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
257 case PIX_FMT_YUV422P9LE:
258 case PIX_FMT_YUV444P9LE:
259 yuv_16_black (nine_bit_uv, false);
262 case PIX_FMT_YUV422P9BE:
263 case PIX_FMT_YUV444P9BE:
264 yuv_16_black (swap_16 (nine_bit_uv), false);
267 case PIX_FMT_YUV422P10LE:
268 case PIX_FMT_YUV444P10LE:
269 yuv_16_black (ten_bit_uv, false);
272 case PIX_FMT_YUV422P16LE:
273 case PIX_FMT_YUV444P16LE:
274 yuv_16_black (sixteen_bit_uv, false);
277 case PIX_FMT_YUV444P10BE:
278 case PIX_FMT_YUV422P10BE:
279 yuv_16_black (swap_16 (ten_bit_uv), false);
282 case AV_PIX_FMT_YUVA420P9BE:
283 case AV_PIX_FMT_YUVA422P9BE:
284 case AV_PIX_FMT_YUVA444P9BE:
285 yuv_16_black (swap_16 (nine_bit_uv), true);
288 case AV_PIX_FMT_YUVA420P9LE:
289 case AV_PIX_FMT_YUVA422P9LE:
290 case AV_PIX_FMT_YUVA444P9LE:
291 yuv_16_black (nine_bit_uv, true);
294 case AV_PIX_FMT_YUVA420P10BE:
295 case AV_PIX_FMT_YUVA422P10BE:
296 case AV_PIX_FMT_YUVA444P10BE:
297 yuv_16_black (swap_16 (ten_bit_uv), true);
300 case AV_PIX_FMT_YUVA420P10LE:
301 case AV_PIX_FMT_YUVA422P10LE:
302 case AV_PIX_FMT_YUVA444P10LE:
303 yuv_16_black (ten_bit_uv, true);
306 case AV_PIX_FMT_YUVA420P16BE:
307 case AV_PIX_FMT_YUVA422P16BE:
308 case AV_PIX_FMT_YUVA444P16BE:
309 yuv_16_black (swap_16 (sixteen_bit_uv), true);
312 case AV_PIX_FMT_YUVA420P16LE:
313 case AV_PIX_FMT_YUVA422P16LE:
314 case AV_PIX_FMT_YUVA444P16LE:
315 yuv_16_black (sixteen_bit_uv, true);
323 memset (data()[0], 0, lines(0) * stride()[0]);
326 case PIX_FMT_UYVY422:
328 int const Y = lines(0);
329 int const X = line_size()[0];
330 uint8_t* p = data()[0];
331 for (int y = 0; y < Y; ++y) {
332 for (int x = 0; x < X / 4; ++x) {
333 *p++ = eight_bit_uv; // Cb
335 *p++ = eight_bit_uv; // Cr
343 throw PixelFormatError ("make_black()", _pixel_format);
348 Image::make_transparent ()
350 if (_pixel_format != PIX_FMT_RGBA) {
351 throw PixelFormatError ("make_transparent()", _pixel_format);
354 memset (data()[0], 0, lines(0) * stride()[0]);
358 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
363 if (_pixel_format == PIX_FMT_BGRA && other->pixel_format() == PIX_FMT_RGBA) {
366 } else if (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA) {
373 int start_tx = position.x;
377 start_ox = -start_tx;
381 int start_ty = position.y;
385 start_oy = -start_ty;
389 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
390 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * this_bpp;
391 uint8_t* op = other->data()[0] + oy * other->stride()[0];
392 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
393 float const alpha = float (op[3]) / 255;
394 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
395 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
396 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
404 Image::copy (shared_ptr<const Image> other, Position<int> position)
406 /* Only implemented for RGB24 onto RGB24 so far */
407 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
408 assert (position.x >= 0 && position.y >= 0);
410 int const N = min (position.x + other->size().width, size().width) - position.x;
411 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
412 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
413 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
414 memcpy (tp, op, N * 3);
419 Image::read_from_socket (shared_ptr<Socket> socket)
421 for (int i = 0; i < components(); ++i) {
422 uint8_t* p = data()[i];
423 for (int y = 0; y < lines(i); ++y) {
424 socket->read (p, line_size()[i]);
431 Image::write_to_socket (shared_ptr<Socket> socket) const
433 for (int i = 0; i < components(); ++i) {
434 uint8_t* p = data()[i];
435 for (int y = 0; y < lines(i); ++y) {
436 socket->write (p, line_size()[i]);
444 Image::bytes_per_pixel (int c) const
446 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
448 throw PixelFormatError ("lines()", _pixel_format);
451 if (c >= components()) {
455 float bpp[4] = { 0, 0, 0, 0 };
457 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
458 if (d->nb_components > 1) {
459 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
461 if (d->nb_components > 2) {
462 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
464 if (d->nb_components > 3) {
465 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
468 if ((d->flags & PIX_FMT_PLANAR) == 0) {
469 /* Not planar; sum them up */
470 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
476 /** Construct a Image of a given size and format, allocating memory
479 * @param p Pixel format.
480 * @param s Size in pixels.
482 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
493 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
494 _data[0] = _data[1] = _data[2] = _data[3] = 0;
496 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
497 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
499 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
500 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
502 for (int i = 0; i < components(); ++i) {
503 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
504 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
506 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
507 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
508 Hence on the last pixel of the last line it reads over the end of
509 the actual data by 1 byte. If the width of an image is a multiple
510 of the stride alignment there will be no padding at the end of image lines.
511 OS X crashes on this illegal read, though other operating systems don't
512 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
513 for that instruction to read safely.
515 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 1);
519 Image::Image (Image const & other)
521 , _pixel_format (other._pixel_format)
522 , _aligned (other._aligned)
526 for (int i = 0; i < components(); ++i) {
527 uint8_t* p = _data[i];
528 uint8_t* q = other._data[i];
529 for (int j = 0; j < lines(i); ++j) {
530 memcpy (p, q, _line_size[i]);
532 q += other.stride()[i];
537 Image::Image (AVFrame* frame)
538 : dcp::Image (dcp::Size (frame->width, frame->height))
539 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
544 for (int i = 0; i < components(); ++i) {
545 uint8_t* p = _data[i];
546 uint8_t* q = frame->data[i];
547 for (int j = 0; j < lines(i); ++j) {
548 memcpy (p, q, _line_size[i]);
550 /* AVFrame's linesize is what we call `stride' */
551 q += frame->linesize[i];
556 Image::Image (shared_ptr<const Image> other, bool aligned)
558 , _pixel_format (other->_pixel_format)
563 for (int i = 0; i < components(); ++i) {
564 assert(line_size()[i] == other->line_size()[i]);
565 uint8_t* p = _data[i];
566 uint8_t* q = other->data()[i];
567 for (int j = 0; j < lines(i); ++j) {
568 memcpy (p, q, line_size()[i]);
570 q += other->stride()[i];
576 Image::operator= (Image const & other)
578 if (this == &other) {
588 Image::swap (Image & other)
590 dcp::Image::swap (other);
592 std::swap (_pixel_format, other._pixel_format);
594 for (int i = 0; i < 4; ++i) {
595 std::swap (_data[i], other._data[i]);
596 std::swap (_line_size[i], other._line_size[i]);
597 std::swap (_stride[i], other._stride[i]);
600 std::swap (_aligned, other._aligned);
603 /** Destroy a Image */
606 for (int i = 0; i < components(); ++i) {
611 av_free (_line_size);
622 Image::line_size () const
628 Image::stride () const
640 Image::aligned () const
646 merge (list<PositionImage> images)
648 if (images.empty ()) {
649 return PositionImage ();
652 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
653 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
654 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
657 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
658 merged->make_transparent ();
659 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
660 merged->alpha_blend (i->image, i->position);
663 return PositionImage (merged, all.position ());