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"
38 using boost::shared_ptr;
42 Image::line_factor (int n) const
48 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
50 throw PixelFormatError ("lines()", _pixel_format);
53 return pow (2.0f, d->log2_chroma_h);
56 /** @param n Component index.
57 * @return Number of lines in the image for the given component.
60 Image::lines (int n) const
62 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
65 /** @return Number of components */
67 Image::components () const
69 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
71 throw PixelFormatError ("components()", _pixel_format);
74 if ((d->flags & PIX_FMT_PLANAR) == 0) {
78 return d->nb_components;
82 Image::scale (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
85 /* Empirical testing suggests that sws_scale() will crash if
86 the input image is not aligned.
90 shared_ptr<Image> scaled (new Image (pixel_format(), out_size, result_aligned));
92 struct SwsContext* scale_context = sws_getContext (
93 size().width, size().height, pixel_format(),
94 out_size.width, out_size.height, pixel_format(),
95 scaler->ffmpeg_id (), 0, 0, 0
102 scaled->data(), scaled->stride()
105 sws_freeContext (scale_context);
110 /** Scale this image to a given size and convert it to RGB.
111 * @param out_size Output image size in pixels.
112 * @param scaler Scaler to use.
115 Image::scale_and_convert_to_rgb (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
118 /* Empirical testing suggests that sws_scale() will crash if
119 the input image is not aligned.
123 shared_ptr<Image> rgb (new Image (PIX_FMT_RGB24, out_size, result_aligned));
125 struct SwsContext* scale_context = sws_getContext (
126 size().width, size().height, pixel_format(),
127 out_size.width, out_size.height, PIX_FMT_RGB24,
128 scaler->ffmpeg_id (), 0, 0, 0
131 /* Scale and convert to RGB from whatever its currently in (which may be RGB) */
136 rgb->data(), rgb->stride()
139 sws_freeContext (scale_context);
144 /** Run a FFmpeg post-process on this image and return the processed version.
145 * @param pp Flags for the required set of post processes.
146 * @return Post-processed image.
149 Image::post_process (string pp, bool aligned) const
151 shared_ptr<Image> out (new Image (pixel_format(), size (), aligned));
154 switch (pixel_format()) {
155 case PIX_FMT_YUV420P:
156 pp_format = PP_FORMAT_420;
158 case PIX_FMT_YUV422P10LE:
159 case PIX_FMT_YUV422P:
160 case PIX_FMT_UYVY422:
161 pp_format = PP_FORMAT_422;
163 case PIX_FMT_YUV444P:
164 case PIX_FMT_YUV444P9BE:
165 case PIX_FMT_YUV444P9LE:
166 case PIX_FMT_YUV444P10BE:
167 case PIX_FMT_YUV444P10LE:
168 pp_format = PP_FORMAT_444;
170 throw PixelFormatError ("post_process", pixel_format());
173 pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
174 pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
177 (const uint8_t **) data(), stride(),
178 out->data(), out->stride(),
179 size().width, size().height,
180 0, 0, mode, context, 0
184 pp_free_context (context);
190 Image::crop (Crop crop, bool aligned) const
192 libdcp::Size cropped_size = size ();
193 cropped_size.width -= crop.left + crop.right;
194 cropped_size.height -= crop.top + crop.bottom;
196 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
198 for (int c = 0; c < components(); ++c) {
199 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
200 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
201 up, and we need to make sure that we copy over the width (up to the stride)
202 rather than short of the width; hence the ceil() here.
204 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
206 /* Start of the source line, cropped from the top but not the left */
207 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
208 uint8_t* out_p = out->data()[c];
210 for (int y = 0; y < out->lines(c); ++y) {
211 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
213 out_p += out->stride()[c];
220 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
222 Image::yuv_16_black (uint16_t v)
224 memset (data()[0], 0, lines(0) * stride()[0]);
225 for (int i = 1; i < 3; ++i) {
226 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
227 for (int y = 0; y < size().height; ++y) {
228 for (int x = 0; x < line_size()[i] / 2; ++x) {
231 p += stride()[i] / 2;
237 Image::swap_16 (uint16_t v)
239 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
245 /* U/V black value for 8-bit colour */
246 static uint8_t const eight_bit_uv = (1 << 7) - 1;
247 /* U/V black value for 9-bit colour */
248 static uint16_t const nine_bit_uv = (1 << 8) - 1;
249 /* U/V black value for 10-bit colour */
250 static uint16_t const ten_bit_uv = (1 << 9) - 1;
251 /* U/V black value for 16-bit colour */
252 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
254 switch (_pixel_format) {
255 case PIX_FMT_YUV420P:
256 case PIX_FMT_YUV422P:
257 case PIX_FMT_YUV444P:
258 memset (data()[0], 0, lines(0) * stride()[0]);
259 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
260 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
263 case PIX_FMT_YUVJ420P:
264 case PIX_FMT_YUVJ422P:
265 case PIX_FMT_YUVJ444P:
266 memset (data()[0], 0, lines(0) * stride()[0]);
267 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
268 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
271 case PIX_FMT_YUV422P9LE:
272 case PIX_FMT_YUV444P9LE:
273 yuv_16_black (nine_bit_uv);
276 case PIX_FMT_YUV422P9BE:
277 case PIX_FMT_YUV444P9BE:
278 yuv_16_black (swap_16 (nine_bit_uv));
281 case PIX_FMT_YUV422P10LE:
282 case PIX_FMT_YUV444P10LE:
283 yuv_16_black (ten_bit_uv);
286 case PIX_FMT_YUV422P16LE:
287 case PIX_FMT_YUV444P16LE:
288 yuv_16_black (sixteen_bit_uv);
291 case PIX_FMT_YUV444P10BE:
292 case PIX_FMT_YUV422P10BE:
293 yuv_16_black (swap_16 (ten_bit_uv));
297 memset (data()[0], 0, lines(0) * stride()[0]);
300 case PIX_FMT_UYVY422:
302 int const Y = lines(0);
303 int const X = line_size()[0];
304 uint8_t* p = data()[0];
305 for (int y = 0; y < Y; ++y) {
306 for (int x = 0; x < X / 4; ++x) {
307 *p++ = eight_bit_uv; // Cb
309 *p++ = eight_bit_uv; // Cr
317 throw PixelFormatError ("make_black()", _pixel_format);
322 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
324 /* Only implemented for RGBA onto RGB24 so far */
325 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
327 int start_tx = position.x;
331 start_ox = -start_tx;
335 int start_ty = position.y;
339 start_oy = -start_ty;
343 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
344 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
345 uint8_t* op = other->data()[0] + oy * other->stride()[0];
346 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
347 float const alpha = float (op[3]) / 255;
348 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
349 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
350 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
358 Image::copy (shared_ptr<const Image> other, Position<int> position)
360 /* Only implemented for RGB24 onto RGB24 so far */
361 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
362 assert (position.x >= 0 && position.y >= 0);
364 int const N = min (position.x + other->size().width, size().width) - position.x;
365 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
366 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
367 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
368 memcpy (tp, op, N * 3);
373 Image::read_from_socket (shared_ptr<Socket> socket)
375 for (int i = 0; i < components(); ++i) {
376 uint8_t* p = data()[i];
377 for (int y = 0; y < lines(i); ++y) {
378 socket->read (p, line_size()[i]);
385 Image::write_to_socket (shared_ptr<Socket> socket) const
387 for (int i = 0; i < components(); ++i) {
388 uint8_t* p = data()[i];
389 for (int y = 0; y < lines(i); ++y) {
390 socket->write (p, line_size()[i]);
398 Image::bytes_per_pixel (int c) const
400 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
402 throw PixelFormatError ("lines()", _pixel_format);
405 if (c >= components()) {
409 float bpp[4] = { 0, 0, 0, 0 };
411 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
412 if (d->nb_components > 1) {
413 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
415 if (d->nb_components > 2) {
416 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
418 if (d->nb_components > 3) {
419 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
422 if ((d->flags & PIX_FMT_PLANAR) == 0) {
423 /* Not planar; sum them up */
424 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
430 /** Construct a Image of a given size and format, allocating memory
433 * @param p Pixel format.
434 * @param s Size in pixels.
436 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
447 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
448 _data[0] = _data[1] = _data[2] = _data[3] = 0;
450 _line_size = (int *) av_malloc (4 * sizeof (int));
451 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
453 _stride = (int *) av_malloc (4 * sizeof (int));
454 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
456 for (int i = 0; i < components(); ++i) {
457 _line_size[i] = _size.width * bytes_per_pixel(i);
458 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
459 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i));
463 Image::Image (Image const & other)
464 : libdcp::Image (other)
465 , _pixel_format (other._pixel_format)
466 , _aligned (other._aligned)
470 for (int i = 0; i < components(); ++i) {
471 uint8_t* p = _data[i];
472 uint8_t* q = other._data[i];
473 for (int j = 0; j < lines(i); ++j) {
474 memcpy (p, q, _line_size[i]);
476 q += other.stride()[i];
481 Image::Image (AVFrame* frame)
482 : libdcp::Image (libdcp::Size (frame->width, frame->height))
483 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
488 for (int i = 0; i < components(); ++i) {
489 uint8_t* p = _data[i];
490 uint8_t* q = frame->data[i];
491 for (int j = 0; j < lines(i); ++j) {
492 memcpy (p, q, _line_size[i]);
494 /* AVFrame's linesize is what we call `stride' */
495 q += frame->linesize[i];
500 Image::Image (shared_ptr<const Image> other, bool aligned)
501 : libdcp::Image (other)
502 , _pixel_format (other->_pixel_format)
507 for (int i = 0; i < components(); ++i) {
508 assert(line_size()[i] == other->line_size()[i]);
509 uint8_t* p = _data[i];
510 uint8_t* q = other->data()[i];
511 for (int j = 0; j < lines(i); ++j) {
512 memcpy (p, q, line_size()[i]);
514 q += other->stride()[i];
520 Image::operator= (Image const & other)
522 if (this == &other) {
532 Image::swap (Image & other)
534 libdcp::Image::swap (other);
536 std::swap (_pixel_format, other._pixel_format);
538 for (int i = 0; i < 4; ++i) {
539 std::swap (_data[i], other._data[i]);
540 std::swap (_line_size[i], other._line_size[i]);
541 std::swap (_stride[i], other._stride[i]);
544 std::swap (_aligned, other._aligned);
547 /** Destroy a Image */
550 for (int i = 0; i < components(); ++i) {
555 av_free (_line_size);
566 Image::line_size () const
572 Image::stride () const
584 Image::aligned () const