2 Copyright (C) 2012 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>
29 #include <libpostproc/postprocess.h>
32 #include "exceptions.h"
39 using boost::shared_ptr;
43 Image::line_factor (int n) const
49 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
51 throw PixelFormatError ("lines()", _pixel_format);
54 return pow (2.0f, d->log2_chroma_h);
57 /** @param n Component index.
58 * @return Number of lines in the image for the given component.
61 Image::lines (int n) const
63 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
66 /** @return Number of components */
68 Image::components () const
70 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
72 throw PixelFormatError ("components()", _pixel_format);
75 if ((d->flags & PIX_FMT_PLANAR) == 0) {
79 return d->nb_components;
82 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
84 Image::crop_scale_window (Crop crop, libdcp::Size inter_size, libdcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
87 /* Empirical testing suggests that sws_scale() will crash if
88 the input image is not aligned.
92 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned));
95 libdcp::Size cropped_size = crop.apply (size ());
97 struct SwsContext* scale_context = sws_getContext (
98 cropped_size.width, cropped_size.height, pixel_format(),
99 inter_size.width, inter_size.height, out_format,
100 scaler->ffmpeg_id (), 0, 0, 0
103 uint8_t* scale_in_data[components()];
104 for (int c = 0; c < components(); ++c) {
105 scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c));
108 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
110 uint8_t* scale_out_data[components()];
111 for (int c = 0; c < components(); ++c) {
112 scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y;
117 scale_in_data, stride(),
118 0, cropped_size.height,
119 scale_out_data, out->stride()
122 sws_freeContext (scale_context);
128 Image::scale (libdcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
131 /* Empirical testing suggests that sws_scale() will crash if
132 the input image is not aligned.
136 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
138 struct SwsContext* scale_context = sws_getContext (
139 size().width, size().height, pixel_format(),
140 out_size.width, out_size.height, out_format,
141 scaler->ffmpeg_id (), 0, 0, 0
148 scaled->data(), scaled->stride()
151 sws_freeContext (scale_context);
156 /** Run a FFmpeg post-process on this image and return the processed version.
157 * @param pp Flags for the required set of post processes.
158 * @return Post-processed image.
161 Image::post_process (string pp, bool aligned) const
163 shared_ptr<Image> out (new Image (pixel_format(), size (), aligned));
166 switch (pixel_format()) {
167 case PIX_FMT_YUV420P:
168 pp_format = PP_FORMAT_420;
170 case PIX_FMT_YUV422P10LE:
171 case PIX_FMT_YUV422P:
172 case PIX_FMT_UYVY422:
173 pp_format = PP_FORMAT_422;
175 case PIX_FMT_YUV444P:
176 case PIX_FMT_YUV444P9BE:
177 case PIX_FMT_YUV444P9LE:
178 case PIX_FMT_YUV444P10BE:
179 case PIX_FMT_YUV444P10LE:
180 pp_format = PP_FORMAT_444;
182 throw PixelFormatError ("post_process", pixel_format());
185 pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
186 pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
189 (const uint8_t **) data(), stride(),
190 out->data(), out->stride(),
191 size().width, size().height,
192 0, 0, mode, context, 0
196 pp_free_context (context);
202 Image::crop (Crop crop, bool aligned) const
204 libdcp::Size cropped_size = crop.apply (size ());
205 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
207 for (int c = 0; c < components(); ++c) {
208 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
209 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
210 up, and we need to make sure that we copy over the width (up to the stride)
211 rather than short of the width; hence the ceil() here.
213 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
215 /* Start of the source line, cropped from the top but not the left */
216 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
217 uint8_t* out_p = out->data()[c];
219 for (int y = 0; y < out->lines(c); ++y) {
220 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
222 out_p += out->stride()[c];
229 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
231 Image::yuv_16_black (uint16_t v, bool alpha)
233 memset (data()[0], 0, lines(0) * stride()[0]);
234 for (int i = 1; i < 3; ++i) {
235 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
236 for (int y = 0; y < lines(i); ++y) {
237 /* We divide by 2 here because we are writing 2 bytes at a time */
238 for (int x = 0; x < line_size()[i] / 2; ++x) {
241 p += stride()[i] / 2;
246 memset (data()[3], 0, lines(3) * stride()[3]);
251 Image::swap_16 (uint16_t v)
253 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
259 /* U/V black value for 8-bit colour */
260 static uint8_t const eight_bit_uv = (1 << 7) - 1;
261 /* U/V black value for 9-bit colour */
262 static uint16_t const nine_bit_uv = (1 << 8) - 1;
263 /* U/V black value for 10-bit colour */
264 static uint16_t const ten_bit_uv = (1 << 9) - 1;
265 /* U/V black value for 16-bit colour */
266 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
268 switch (_pixel_format) {
269 case PIX_FMT_YUV420P:
270 case PIX_FMT_YUV422P:
271 case PIX_FMT_YUV444P:
272 case PIX_FMT_YUV411P:
273 memset (data()[0], 0, lines(0) * stride()[0]);
274 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
275 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
278 case PIX_FMT_YUVJ420P:
279 case PIX_FMT_YUVJ422P:
280 case PIX_FMT_YUVJ444P:
281 memset (data()[0], 0, lines(0) * stride()[0]);
282 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
283 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
286 case PIX_FMT_YUV422P9LE:
287 case PIX_FMT_YUV444P9LE:
288 yuv_16_black (nine_bit_uv, false);
291 case PIX_FMT_YUV422P9BE:
292 case PIX_FMT_YUV444P9BE:
293 yuv_16_black (swap_16 (nine_bit_uv), false);
296 case PIX_FMT_YUV422P10LE:
297 case PIX_FMT_YUV444P10LE:
298 yuv_16_black (ten_bit_uv, false);
301 case PIX_FMT_YUV422P16LE:
302 case PIX_FMT_YUV444P16LE:
303 yuv_16_black (sixteen_bit_uv, false);
306 case PIX_FMT_YUV444P10BE:
307 case PIX_FMT_YUV422P10BE:
308 yuv_16_black (swap_16 (ten_bit_uv), false);
311 case AV_PIX_FMT_YUVA420P9BE:
312 case AV_PIX_FMT_YUVA422P9BE:
313 case AV_PIX_FMT_YUVA444P9BE:
314 yuv_16_black (swap_16 (nine_bit_uv), true);
317 case AV_PIX_FMT_YUVA420P9LE:
318 case AV_PIX_FMT_YUVA422P9LE:
319 case AV_PIX_FMT_YUVA444P9LE:
320 yuv_16_black (nine_bit_uv, true);
323 case AV_PIX_FMT_YUVA420P10BE:
324 case AV_PIX_FMT_YUVA422P10BE:
325 case AV_PIX_FMT_YUVA444P10BE:
326 yuv_16_black (swap_16 (ten_bit_uv), true);
329 case AV_PIX_FMT_YUVA420P10LE:
330 case AV_PIX_FMT_YUVA422P10LE:
331 case AV_PIX_FMT_YUVA444P10LE:
332 yuv_16_black (ten_bit_uv, true);
335 case AV_PIX_FMT_YUVA420P16BE:
336 case AV_PIX_FMT_YUVA422P16BE:
337 case AV_PIX_FMT_YUVA444P16BE:
338 yuv_16_black (swap_16 (sixteen_bit_uv), true);
341 case AV_PIX_FMT_YUVA420P16LE:
342 case AV_PIX_FMT_YUVA422P16LE:
343 case AV_PIX_FMT_YUVA444P16LE:
344 yuv_16_black (sixteen_bit_uv, true);
352 memset (data()[0], 0, lines(0) * stride()[0]);
355 case PIX_FMT_UYVY422:
357 int const Y = lines(0);
358 int const X = line_size()[0];
359 uint8_t* p = data()[0];
360 for (int y = 0; y < Y; ++y) {
361 for (int x = 0; x < X / 4; ++x) {
362 *p++ = eight_bit_uv; // Cb
364 *p++ = eight_bit_uv; // Cr
372 throw PixelFormatError ("make_black()", _pixel_format);
377 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
379 /* Only implemented for RGBA onto RGB24 so far */
380 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
382 int start_tx = position.x;
386 start_ox = -start_tx;
390 int start_ty = position.y;
394 start_oy = -start_ty;
398 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
399 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
400 uint8_t* op = other->data()[0] + oy * other->stride()[0];
401 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
402 float const alpha = float (op[3]) / 255;
403 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
404 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
405 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
413 Image::copy (shared_ptr<const Image> other, Position<int> position)
415 /* Only implemented for RGB24 onto RGB24 so far */
416 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
417 assert (position.x >= 0 && position.y >= 0);
419 int const N = min (position.x + other->size().width, size().width) - position.x;
420 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
421 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
422 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
423 memcpy (tp, op, N * 3);
428 Image::read_from_socket (shared_ptr<Socket> socket)
430 for (int i = 0; i < components(); ++i) {
431 uint8_t* p = data()[i];
432 for (int y = 0; y < lines(i); ++y) {
433 socket->read (p, line_size()[i]);
440 Image::write_to_socket (shared_ptr<Socket> socket) const
442 for (int i = 0; i < components(); ++i) {
443 uint8_t* p = data()[i];
444 for (int y = 0; y < lines(i); ++y) {
445 socket->write (p, line_size()[i]);
453 Image::bytes_per_pixel (int c) const
455 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
457 throw PixelFormatError ("lines()", _pixel_format);
460 if (c >= components()) {
464 float bpp[4] = { 0, 0, 0, 0 };
466 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
467 if (d->nb_components > 1) {
468 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
470 if (d->nb_components > 2) {
471 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
473 if (d->nb_components > 3) {
474 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
477 if ((d->flags & PIX_FMT_PLANAR) == 0) {
478 /* Not planar; sum them up */
479 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
485 /** Construct a Image of a given size and format, allocating memory
488 * @param p Pixel format.
489 * @param s Size in pixels.
491 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
502 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
503 _data[0] = _data[1] = _data[2] = _data[3] = 0;
505 _line_size = (int *) av_malloc (4 * sizeof (int));
506 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
508 _stride = (int *) av_malloc (4 * sizeof (int));
509 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
511 for (int i = 0; i < components(); ++i) {
512 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
513 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
515 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
516 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
517 Hence on the last pixel of the last line it reads over the end of
518 the actual data by 1 byte. If the width of an image is a multiple
519 of the stride alignment there will be no padding at the end of image lines.
520 OS X crashes on this illegal read, though other operating systems don't
521 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
522 for that instruction to read safely.
524 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
528 Image::Image (Image const & other)
529 : libdcp::Image (other)
530 , _pixel_format (other._pixel_format)
531 , _aligned (other._aligned)
535 for (int i = 0; i < components(); ++i) {
536 uint8_t* p = _data[i];
537 uint8_t* q = other._data[i];
538 for (int j = 0; j < lines(i); ++j) {
539 memcpy (p, q, _line_size[i]);
541 q += other.stride()[i];
546 Image::Image (AVFrame* frame)
547 : libdcp::Image (libdcp::Size (frame->width, frame->height))
548 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
553 for (int i = 0; i < components(); ++i) {
554 uint8_t* p = _data[i];
555 uint8_t* q = frame->data[i];
556 for (int j = 0; j < lines(i); ++j) {
557 memcpy (p, q, _line_size[i]);
559 /* AVFrame's linesize is what we call `stride' */
560 q += frame->linesize[i];
565 Image::Image (shared_ptr<const Image> other, bool aligned)
566 : libdcp::Image (other)
567 , _pixel_format (other->_pixel_format)
572 for (int i = 0; i < components(); ++i) {
573 assert(line_size()[i] == other->line_size()[i]);
574 uint8_t* p = _data[i];
575 uint8_t* q = other->data()[i];
576 for (int j = 0; j < lines(i); ++j) {
577 memcpy (p, q, line_size()[i]);
579 q += other->stride()[i];
585 Image::operator= (Image const & other)
587 if (this == &other) {
597 Image::swap (Image & other)
599 libdcp::Image::swap (other);
601 std::swap (_pixel_format, other._pixel_format);
603 for (int i = 0; i < 4; ++i) {
604 std::swap (_data[i], other._data[i]);
605 std::swap (_line_size[i], other._line_size[i]);
606 std::swap (_stride[i], other._stride[i]);
609 std::swap (_aligned, other._aligned);
612 /** Destroy a Image */
615 for (int i = 0; i < components(); ++i) {
620 av_free (_line_size);
631 Image::line_size () const
637 Image::stride () const
649 Image::aligned () const