2 Copyright (C) 2012-2015 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.
25 #include "exceptions.h"
29 #include "md5_digester.h"
30 #include "dcpomatic_socket.h"
32 #include <libswscale/swscale.h>
33 #include <libavutil/pixfmt.h>
34 #include <libavutil/pixdesc.h>
45 using boost::shared_ptr;
49 Image::line_factor (int n) const
55 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
57 throw PixelFormatError ("lines()", _pixel_format);
60 return pow (2.0f, d->log2_chroma_h);
63 /** @param n Component index.
64 * @return Number of lines in the image for the given component.
67 Image::lines (int n) const
69 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
72 /** @return Number of components */
74 Image::components () const
76 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
78 throw PixelFormatError ("components()", _pixel_format);
81 if ((d->flags & PIX_FMT_PLANAR) == 0) {
85 return d->nb_components;
88 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
90 Image::crop_scale_window (
91 Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned
94 /* Empirical testing suggests that sws_scale() will crash if
95 the input image is not aligned.
97 DCPOMATIC_ASSERT (aligned ());
99 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
100 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
102 /* Here's an image of out_size */
103 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned));
106 /* Size of the image after any crop */
107 dcp::Size const cropped_size = crop.apply (size ());
109 /* Scale context for a scale from cropped_size to inter_size */
110 struct SwsContext* scale_context = sws_getContext (
111 cropped_size.width, cropped_size.height, pixel_format(),
112 inter_size.width, inter_size.height, out_format,
116 if (!scale_context) {
117 throw StringError (N_("Could not allocate SwsContext"));
120 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
121 int const lut[dcp::YUV_TO_RGB_COUNT] = {
126 sws_setColorspaceDetails (
128 sws_getCoefficients (lut[yuv_to_rgb]), 0,
129 sws_getCoefficients (lut[yuv_to_rgb]), 0,
133 /* Prepare input data pointers with crop */
134 uint8_t* scale_in_data[components()];
135 for (int c = 0; c < components(); ++c) {
136 scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c));
139 /* Corner of the image within out_size */
140 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
142 uint8_t* scale_out_data[out->components()];
143 for (int c = 0; c < out->components(); ++c) {
144 scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y;
149 scale_in_data, stride(),
150 0, cropped_size.height,
151 scale_out_data, out->stride()
154 sws_freeContext (scale_context);
160 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned) const
162 /* Empirical testing suggests that sws_scale() will crash if
163 the input image is not aligned.
165 DCPOMATIC_ASSERT (aligned ());
167 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
169 struct SwsContext* scale_context = sws_getContext (
170 size().width, size().height, pixel_format(),
171 out_size.width, out_size.height, out_format,
175 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
176 int const lut[dcp::YUV_TO_RGB_COUNT] = {
181 sws_setColorspaceDetails (
183 sws_getCoefficients (lut[yuv_to_rgb]), 0,
184 sws_getCoefficients (lut[yuv_to_rgb]), 0,
192 scaled->data(), scaled->stride()
195 sws_freeContext (scale_context);
201 Image::crop (Crop crop, bool aligned) const
203 dcp::Size cropped_size = crop.apply (size ());
204 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
206 for (int c = 0; c < components(); ++c) {
207 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
208 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
209 up, and we need to make sure that we copy over the width (up to the stride)
210 rather than short of the width; hence the ceil() here.
212 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
214 /* Start of the source line, cropped from the top but not the left */
215 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
216 uint8_t* out_p = out->data()[c];
218 for (int y = 0; y < out->lines(c); ++y) {
219 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
221 out_p += out->stride()[c];
228 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
230 Image::yuv_16_black (uint16_t v, bool alpha)
232 memset (data()[0], 0, lines(0) * stride()[0]);
233 for (int i = 1; i < 3; ++i) {
234 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
235 for (int y = 0; y < lines(i); ++y) {
236 /* We divide by 2 here because we are writing 2 bytes at a time */
237 for (int x = 0; x < line_size()[i] / 2; ++x) {
240 p += stride()[i] / 2;
245 memset (data()[3], 0, lines(3) * stride()[3]);
250 Image::swap_16 (uint16_t v)
252 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
258 /* U/V black value for 8-bit colour */
259 static uint8_t const eight_bit_uv = (1 << 7) - 1;
260 /* U/V black value for 9-bit colour */
261 static uint16_t const nine_bit_uv = (1 << 8) - 1;
262 /* U/V black value for 10-bit colour */
263 static uint16_t const ten_bit_uv = (1 << 9) - 1;
264 /* U/V black value for 16-bit colour */
265 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
267 switch (_pixel_format) {
268 case PIX_FMT_YUV420P:
269 case PIX_FMT_YUV422P:
270 case PIX_FMT_YUV444P:
271 case PIX_FMT_YUV411P:
272 memset (data()[0], 0, lines(0) * stride()[0]);
273 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
274 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
277 case PIX_FMT_YUVJ420P:
278 case PIX_FMT_YUVJ422P:
279 case PIX_FMT_YUVJ444P:
280 memset (data()[0], 0, lines(0) * stride()[0]);
281 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
282 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
285 case PIX_FMT_YUV422P9LE:
286 case PIX_FMT_YUV444P9LE:
287 yuv_16_black (nine_bit_uv, false);
290 case PIX_FMT_YUV422P9BE:
291 case PIX_FMT_YUV444P9BE:
292 yuv_16_black (swap_16 (nine_bit_uv), false);
295 case PIX_FMT_YUV422P10LE:
296 case PIX_FMT_YUV444P10LE:
297 yuv_16_black (ten_bit_uv, false);
300 case PIX_FMT_YUV422P16LE:
301 case PIX_FMT_YUV444P16LE:
302 yuv_16_black (sixteen_bit_uv, false);
305 case PIX_FMT_YUV444P10BE:
306 case PIX_FMT_YUV422P10BE:
307 yuv_16_black (swap_16 (ten_bit_uv), false);
310 case AV_PIX_FMT_YUVA420P9BE:
311 case AV_PIX_FMT_YUVA422P9BE:
312 case AV_PIX_FMT_YUVA444P9BE:
313 yuv_16_black (swap_16 (nine_bit_uv), true);
316 case AV_PIX_FMT_YUVA420P9LE:
317 case AV_PIX_FMT_YUVA422P9LE:
318 case AV_PIX_FMT_YUVA444P9LE:
319 yuv_16_black (nine_bit_uv, true);
322 case AV_PIX_FMT_YUVA420P10BE:
323 case AV_PIX_FMT_YUVA422P10BE:
324 case AV_PIX_FMT_YUVA444P10BE:
325 yuv_16_black (swap_16 (ten_bit_uv), true);
328 case AV_PIX_FMT_YUVA420P10LE:
329 case AV_PIX_FMT_YUVA422P10LE:
330 case AV_PIX_FMT_YUVA444P10LE:
331 yuv_16_black (ten_bit_uv, true);
334 case AV_PIX_FMT_YUVA420P16BE:
335 case AV_PIX_FMT_YUVA422P16BE:
336 case AV_PIX_FMT_YUVA444P16BE:
337 yuv_16_black (swap_16 (sixteen_bit_uv), true);
340 case AV_PIX_FMT_YUVA420P16LE:
341 case AV_PIX_FMT_YUVA422P16LE:
342 case AV_PIX_FMT_YUVA444P16LE:
343 yuv_16_black (sixteen_bit_uv, true);
351 case PIX_FMT_RGB555LE:
352 case PIX_FMT_RGB48LE:
353 case PIX_FMT_RGB48BE:
354 memset (data()[0], 0, lines(0) * stride()[0]);
357 case PIX_FMT_UYVY422:
359 int const Y = lines(0);
360 int const X = line_size()[0];
361 uint8_t* p = data()[0];
362 for (int y = 0; y < Y; ++y) {
363 for (int x = 0; x < X / 4; ++x) {
364 *p++ = eight_bit_uv; // Cb
366 *p++ = eight_bit_uv; // Cr
374 throw PixelFormatError ("make_black()", _pixel_format);
379 Image::make_transparent ()
381 if (_pixel_format != PIX_FMT_RGBA) {
382 throw PixelFormatError ("make_transparent()", _pixel_format);
385 memset (data()[0], 0, lines(0) * stride()[0]);
389 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
391 DCPOMATIC_ASSERT (other->pixel_format() == PIX_FMT_RGBA);
392 int const other_bpp = 4;
394 int start_tx = position.x;
398 start_ox = -start_tx;
402 int start_ty = position.y;
406 start_oy = -start_ty;
410 switch (_pixel_format) {
413 int const this_bpp = 3;
414 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
415 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
416 uint8_t* op = other->data()[0] + oy * other->stride()[0];
417 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
418 float const alpha = float (op[3]) / 255;
419 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
420 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
421 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
432 int const this_bpp = 4;
433 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
434 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
435 uint8_t* op = other->data()[0] + oy * other->stride()[0];
436 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
437 float const alpha = float (op[3]) / 255;
438 tp[0] = op[0] * alpha + tp[0] * (1 - alpha);
439 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
440 tp[2] = op[2] * alpha + tp[2] * (1 - alpha);
441 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
449 case PIX_FMT_RGB48LE:
451 int const this_bpp = 6;
452 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
453 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
454 uint8_t* op = other->data()[0] + oy * other->stride()[0];
455 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
456 float const alpha = float (op[3]) / 255;
457 /* Blend high bytes */
458 tp[1] = op[0] * alpha + tp[1] * (1 - alpha);
459 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
460 tp[5] = op[2] * alpha + tp[5] * (1 - alpha);
469 DCPOMATIC_ASSERT (false);
474 Image::copy (shared_ptr<const Image> other, Position<int> position)
476 /* Only implemented for RGB24 onto RGB24 so far */
477 DCPOMATIC_ASSERT (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
478 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
480 int const N = min (position.x + other->size().width, size().width) - position.x;
481 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
482 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
483 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
484 memcpy (tp, op, N * 3);
489 Image::read_from_socket (shared_ptr<Socket> socket)
491 for (int i = 0; i < components(); ++i) {
492 uint8_t* p = data()[i];
493 for (int y = 0; y < lines(i); ++y) {
494 socket->read (p, line_size()[i]);
501 Image::write_to_socket (shared_ptr<Socket> socket) const
503 for (int i = 0; i < components(); ++i) {
504 uint8_t* p = data()[i];
505 for (int y = 0; y < lines(i); ++y) {
506 socket->write (p, line_size()[i]);
514 Image::bytes_per_pixel (int c) const
516 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
518 throw PixelFormatError ("lines()", _pixel_format);
521 if (c >= components()) {
525 float bpp[4] = { 0, 0, 0, 0 };
527 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
528 if (d->nb_components > 1) {
529 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
531 if (d->nb_components > 2) {
532 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
534 if (d->nb_components > 3) {
535 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
538 if ((d->flags & PIX_FMT_PLANAR) == 0) {
539 /* Not planar; sum them up */
540 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
546 /** Construct a Image of a given size and format, allocating memory
549 * @param p Pixel format.
550 * @param s Size in pixels.
552 Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
563 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
564 _data[0] = _data[1] = _data[2] = _data[3] = 0;
566 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
567 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
569 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
570 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
572 for (int i = 0; i < components(); ++i) {
573 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
574 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
576 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
577 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
578 Hence on the last pixel of the last line it reads over the end of
579 the actual data by 1 byte. If the width of an image is a multiple
580 of the stride alignment there will be no padding at the end of image lines.
581 OS X crashes on this illegal read, though other operating systems don't
582 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
583 for that instruction to read safely.
585 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
586 over-reads by more then _avx. I can't follow the code to work out how much,
587 so I'll just over-allocate by 32 bytes and have done with it. Empirical
588 testing suggests that it works.
590 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 32);
594 Image::Image (Image const & other)
595 : _size (other._size)
596 , _pixel_format (other._pixel_format)
597 , _aligned (other._aligned)
601 for (int i = 0; i < components(); ++i) {
602 uint8_t* p = _data[i];
603 uint8_t* q = other._data[i];
604 for (int j = 0; j < lines(i); ++j) {
605 memcpy (p, q, _line_size[i]);
607 q += other.stride()[i];
612 Image::Image (AVFrame* frame)
613 : _size (frame->width, frame->height)
614 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
619 for (int i = 0; i < components(); ++i) {
620 uint8_t* p = _data[i];
621 uint8_t* q = frame->data[i];
622 for (int j = 0; j < lines(i); ++j) {
623 memcpy (p, q, _line_size[i]);
625 /* AVFrame's linesize is what we call `stride' */
626 q += frame->linesize[i];
631 Image::Image (shared_ptr<const Image> other, bool aligned)
632 : _size (other->_size)
633 , _pixel_format (other->_pixel_format)
638 for (int i = 0; i < components(); ++i) {
639 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
640 uint8_t* p = _data[i];
641 uint8_t* q = other->data()[i];
642 for (int j = 0; j < lines(i); ++j) {
643 memcpy (p, q, line_size()[i]);
645 q += other->stride()[i];
651 Image::operator= (Image const & other)
653 if (this == &other) {
663 Image::swap (Image & other)
665 std::swap (_size, other._size);
666 std::swap (_pixel_format, other._pixel_format);
668 for (int i = 0; i < 4; ++i) {
669 std::swap (_data[i], other._data[i]);
670 std::swap (_line_size[i], other._line_size[i]);
671 std::swap (_stride[i], other._stride[i]);
674 std::swap (_aligned, other._aligned);
677 /** Destroy a Image */
680 for (int i = 0; i < components(); ++i) {
685 av_free (_line_size);
696 Image::line_size () const
702 Image::stride () const
714 Image::aligned () const
720 merge (list<PositionImage> images)
722 if (images.empty ()) {
723 return PositionImage ();
726 if (images.size() == 1) {
727 return images.front ();
730 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
731 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
732 all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
735 shared_ptr<Image> merged (new Image (images.front().image->pixel_format (), dcp::Size (all.width, all.height), true));
736 merged->make_transparent ();
737 for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
738 merged->alpha_blend (i->image, i->position - all.position());
741 return PositionImage (merged, all.position ());
745 operator== (Image const & a, Image const & b)
747 if (a.components() != b.components() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
751 for (int c = 0; c < a.components(); ++c) {
752 if (a.lines(c) != b.lines(c) || a.line_size()[c] != b.line_size()[c] || a.stride()[c] != b.stride()[c]) {
756 uint8_t* p = a.data()[c];
757 uint8_t* q = b.data()[c];
758 for (int y = 0; y < a.lines(c); ++y) {
759 if (memcmp (p, q, a.line_size()[c]) != 0) {
772 Image::fade (float f)
774 switch (_pixel_format) {
775 case PIX_FMT_YUV420P:
776 case PIX_FMT_YUV422P:
777 case PIX_FMT_YUV444P:
778 case PIX_FMT_YUV411P:
779 case PIX_FMT_YUVJ420P:
780 case PIX_FMT_YUVJ422P:
781 case PIX_FMT_YUVJ444P:
787 case PIX_FMT_RGB555LE:
789 for (int c = 0; c < 3; ++c) {
790 uint8_t* p = data()[c];
791 for (int y = 0; y < lines(c); ++y) {
793 for (int x = 0; x < line_size()[c]; ++x) {
794 *q = int (float (*q) * f);
802 case PIX_FMT_YUV422P9LE:
803 case PIX_FMT_YUV444P9LE:
804 case PIX_FMT_YUV422P10LE:
805 case PIX_FMT_YUV444P10LE:
806 case PIX_FMT_YUV422P16LE:
807 case PIX_FMT_YUV444P16LE:
808 case AV_PIX_FMT_YUVA420P9LE:
809 case AV_PIX_FMT_YUVA422P9LE:
810 case AV_PIX_FMT_YUVA444P9LE:
811 case AV_PIX_FMT_YUVA420P10LE:
812 case AV_PIX_FMT_YUVA422P10LE:
813 case AV_PIX_FMT_YUVA444P10LE:
814 case AV_PIX_FMT_RGB48LE:
815 /* 16-bit little-endian */
816 for (int c = 0; c < 3; ++c) {
817 int const stride_pixels = stride()[c] / 2;
818 int const line_size_pixels = line_size()[c] / 2;
819 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
820 for (int y = 0; y < lines(c); ++y) {
822 for (int x = 0; x < line_size_pixels; ++x) {
823 *q = int (float (*q) * f);
831 case PIX_FMT_YUV422P9BE:
832 case PIX_FMT_YUV444P9BE:
833 case PIX_FMT_YUV444P10BE:
834 case PIX_FMT_YUV422P10BE:
835 case AV_PIX_FMT_YUVA420P9BE:
836 case AV_PIX_FMT_YUVA422P9BE:
837 case AV_PIX_FMT_YUVA444P9BE:
838 case AV_PIX_FMT_YUVA420P10BE:
839 case AV_PIX_FMT_YUVA422P10BE:
840 case AV_PIX_FMT_YUVA444P10BE:
841 case AV_PIX_FMT_YUVA420P16BE:
842 case AV_PIX_FMT_YUVA422P16BE:
843 case AV_PIX_FMT_YUVA444P16BE:
844 case AV_PIX_FMT_RGB48BE:
845 /* 16-bit big-endian */
846 for (int c = 0; c < 3; ++c) {
847 int const stride_pixels = stride()[c] / 2;
848 int const line_size_pixels = line_size()[c] / 2;
849 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
850 for (int y = 0; y < lines(c); ++y) {
852 for (int x = 0; x < line_size_pixels; ++x) {
853 *q = swap_16 (int (float (swap_16 (*q)) * f));
861 case PIX_FMT_UYVY422:
863 int const Y = lines(0);
864 int const X = line_size()[0];
865 uint8_t* p = data()[0];
866 for (int y = 0; y < Y; ++y) {
867 for (int x = 0; x < X; ++x) {
868 *p = int (float (*p) * f);
876 throw PixelFormatError ("fade()", _pixel_format);