}
shared_ptr<Image>
-Image::scale (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
+Image::scale (libdcp::Size out_size, Scaler const * scaler, AVPixelFormat result_format, bool result_aligned) const
{
assert (scaler);
/* Empirical testing suggests that sws_scale() will crash if
*/
assert (aligned ());
- shared_ptr<Image> scaled (new Image (pixel_format(), out_size, result_aligned));
+ shared_ptr<Image> scaled (new Image (result_format, out_size, result_aligned));
struct SwsContext* scale_context = sws_getContext (
size().width, size().height, pixel_format(),
- out_size.width, out_size.height, pixel_format(),
+ out_size.width, out_size.height, result_format,
scaler->ffmpeg_id (), 0, 0, 0
);
return scaled;
}
-/** Scale this image to a given size and convert it to RGB.
- * @param out_size Output image size in pixels.
- * @param scaler Scaler to use.
- */
-shared_ptr<Image>
-Image::scale_and_convert_to_rgb (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
-{
- assert (scaler);
- /* Empirical testing suggests that sws_scale() will crash if
- the input image is not aligned.
- */
- assert (aligned ());
-
- shared_ptr<Image> rgb (new Image (PIX_FMT_RGB24, out_size, result_aligned));
-
- struct SwsContext* scale_context = sws_getContext (
- size().width, size().height, pixel_format(),
- out_size.width, out_size.height, PIX_FMT_RGB24,
- scaler->ffmpeg_id (), 0, 0, 0
- );
-
- /* Scale and convert to RGB from whatever its currently in (which may be RGB) */
- sws_scale (
- scale_context,
- data(), stride(),
- 0, size().height,
- rgb->data(), rgb->stride()
- );
-
- sws_freeContext (scale_context);
-
- return rgb;
-}
-
/** Run a FFmpeg post-process on this image and return the processed version.
* @param pp Flags for the required set of post processes.
* @return Post-processed image.
Image::make_black ()
{
/* U/V black value for 8-bit colour */
- static uint8_t const eight_bit_uv = (1 << 7) - 1;
+ static uint8_t const eight_bit_uv = (1 << 7) - 1;
/* U/V black value for 9-bit colour */
- static uint16_t const nine_bit_uv = (1 << 8) - 1;
+ static uint16_t const nine_bit_uv = (1 << 8) - 1;
/* U/V black value for 10-bit colour */
- static uint16_t const ten_bit_uv = (1 << 9) - 1;
+ static uint16_t const ten_bit_uv = (1 << 9) - 1;
/* U/V black value for 16-bit colour */
- static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
+ static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
switch (_pixel_format) {
case PIX_FMT_YUV420P:
for (int y = 0; y < Y; ++y) {
for (int x = 0; x < X / 4; ++x) {
*p++ = eight_bit_uv; // Cb
- *p++ = 0; // Y0
+ *p++ = 0; // Y0
*p++ = eight_bit_uv; // Cr
- *p++ = 0; // Y1
+ *p++ = 0; // Y1
}
}
break;
* @param s Size in pixels.
*/
Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
- : _pixel_format (p)
- , _size (s)
+ : libdcp::Image (s)
+ , _pixel_format (p)
, _aligned (aligned)
{
allocate ();
_stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
for (int i = 0; i < components(); ++i) {
- _line_size[i] = _size.width * bytes_per_pixel(i);
+ _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
_stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
- _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i));
+
+ /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
+ uses a 16-byte fetch to read three bytes (R/G/B) of image data.
+ Hence on the last pixel of the last line it reads over the end of
+ the actual data by 1 byte. If the width of an image is a multiple
+ of the stride alignment there will be no padding at the end of image lines.
+ OS X crashes on this illegal read, though other operating systems don't
+ seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
+ for that instruction to read safely.
+ */
+ _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
}
}
Image::Image (Image const & other)
- : _pixel_format (other._pixel_format)
- , _size (other._size)
+ : libdcp::Image (other)
+ , _pixel_format (other._pixel_format)
, _aligned (other._aligned)
{
allocate ();
}
Image::Image (AVFrame* frame)
- : _pixel_format (static_cast<AVPixelFormat> (frame->format))
- , _size (frame->width, frame->height)
+ : libdcp::Image (libdcp::Size (frame->width, frame->height))
+ , _pixel_format (static_cast<AVPixelFormat> (frame->format))
, _aligned (true)
{
allocate ();
}
Image::Image (shared_ptr<const Image> other, bool aligned)
- : _pixel_format (other->_pixel_format)
- , _size (other->size())
+ : libdcp::Image (other)
+ , _pixel_format (other->_pixel_format)
, _aligned (aligned)
{
allocate ();
void
Image::swap (Image & other)
{
+ libdcp::Image::swap (other);
+
std::swap (_pixel_format, other._pixel_format);
- std::swap (_size, other._size);
for (int i = 0; i < 4; ++i) {
std::swap (_data[i], other._data[i]);