Skip to content
52 changes: 46 additions & 6 deletions src/modules/qt/filter_qtblend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,25 @@ static int filter_get_image(mlt_frame frame,

int image_size = mlt_image_format_size(*format, *width, *height, NULL);

char *interps = mlt_properties_get(frame_properties, "consumer.rescale");
bool hqPainting = interps && strcmp(interps, "nearest") && strcmp(interps, "neighbor");

// resize to rect
bool scaled = false;
QImage scaledSource;
if (distort) {
transform.scale(rect.w / b_width, rect.h / b_height);
if (rect.w != b_width || rect.h != b_height) {
if (rect.w < b_width || rect.h < b_height) {
scaled = true;
scaledSource = sourceImage.scaled(qRound(rect.w),
qRound(rect.h),
Qt::IgnoreAspectRatio,
hqPainting ? Qt::SmoothTransformation
: Qt::FastTransformation);
} else {
transform.scale(rect.w / b_width, rect.h / b_height);
}
}
} else {
double scale;
double resize_dar = rect.w * consumer_ar / rect.h;
Expand All @@ -227,9 +243,28 @@ static int filter_get_image(mlt_frame frame,
} else {
scale = rect.h / b_height * b_ar;
}
// Center image in rect
transform.translate((rect.w - (b_width * scale)) / 2.0, (rect.h - (b_height * scale)) / 2.0);
transform.scale(scale, scale);
if (scale < 1.) {
// Use higher quality QImage scaling
scaled = true;
const QSize finalSize(qRound(sourceImage.width() * scale),
qRound(sourceImage.height() * scale));
// Center image in rect
Comment thread
j-b-m marked this conversation as resolved.
transform.translate((rect.w - finalSize.width()) / 2.0,
(rect.h - finalSize.height()) / 2.0);
// Scale
scaledSource = sourceImage.scaled(finalSize,
Qt::IgnoreAspectRatio,
hqPainting ? Qt::SmoothTransformation
: Qt::FastTransformation);
} else {
// Center image in rect
transform.translate((rect.w - (b_width * scale)) / 2.0,
(rect.h - (b_height * scale)) / 2.0);
if (scale > 1.) {
// Use QPainter scaling
transform.scale(scale, scale);
}
}
}

uint8_t *dest_image = NULL;
Expand All @@ -242,13 +277,18 @@ static int filter_get_image(mlt_frame frame,
QPainter painter(&destImage);
painter.setCompositionMode(
(QPainter::CompositionMode) mlt_properties_get_int(properties, "compositing"));
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setTransform(transform);
painter.setOpacity(opacity);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, hqPainting);
// Composite top frame
painter.drawImage(0, 0, sourceImage);
if (scaled) {
painter.drawImage(0, 0, scaledSource);
} else {
painter.drawImage(0, 0, sourceImage);
}
// finish Qt drawing
painter.end();

convert_qimage_to_mlt(&destImage, dest_image, *width, *height);
*image = dest_image;
mlt_frame_set_image(frame, *image, *width * *height * 4, mlt_pool_release);
Expand Down
69 changes: 49 additions & 20 deletions src/modules/qt/transition_qtblend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,6 @@ static int get_image(mlt_frame a_frame,
// This is not a field-aware transform.
mlt_properties_set_int(b_properties, "consumer.progressive", 1);

// Suppress padding and aspect normalization.
char *interps = mlt_properties_get(properties, "consumer.rescale");
if (interps)
interps = strdup(interps);

// Check profile dar vs image dar image
if (!forceAlpha && rect.w == -1 && b_dar != mlt_profile_dar(profile)) {
// Activate transparency if the clips don't have the same aspect ratio
Expand Down Expand Up @@ -233,7 +228,6 @@ static int get_image(mlt_frame a_frame,
*height = b_height;
}
*image = b_image;
free(interps);
return 0;
}
}
Expand All @@ -248,9 +242,31 @@ static int get_image(mlt_frame a_frame,
}
if (*format != mlt_image_rgba64)
*format = mlt_image_rgba;

bool scaled = false;
QImage scaledSource;

// We don't do subpixel smoothing for nearest neighbour interpolation
// so people can use that to upscale pixel art and keep the hard edges.
char *interps = mlt_properties_get(properties, "consumer.rescale");
bool hqPainting = interps && strcmp(interps, "nearest") && strcmp(interps, "neighbor");

// convert top mlt image to qimage
QImage topImg;
convert_mlt_to_qimage(b_image, &topImg, b_width, b_height, *format);

if (distort) {
if (b_width != 0 && b_height != 0) {
transform.scale(rect.w / b_width, rect.h / b_height);
if (rect.w < b_width || rect.h < b_height) {
scaled = true;
scaledSource = topImg.scaled(qRound(rect.w),
qRound(rect.h),
Qt::IgnoreAspectRatio,
hqPainting ? Qt::SmoothTransformation
: Qt::FastTransformation);
} else {
transform.scale(rect.w / b_width, rect.h / b_height);
}
}
} else if (rect.w > 0 && rect.h > 0) {
double resize_dar = rect.w * consumer_ar / rect.h;
Expand All @@ -266,15 +282,33 @@ static int get_image(mlt_frame a_frame,
scale *= transformScale;
}
}
transform.translate((rect.w - (b_width * scale)) / 2.0, (rect.h - (b_height * scale)) / 2.0);
transform.scale(scale, scale);
if (scale < 1.) {
// Use higher quality QImage scaling
scaled = true;
const QSize finalSize(qRound(topImg.width() * scale), qRound(topImg.height() * scale));
// Center image in rect
Comment thread
j-b-m marked this conversation as resolved.
transform.translate((rect.w - finalSize.width()) / 2.0,
(rect.h - finalSize.height()) / 2.0);
// Scale
scaledSource = topImg.scaled(finalSize,
Qt::IgnoreAspectRatio,
hqPainting ? Qt::SmoothTransformation
: Qt::FastTransformation);
} else {
// Center image in rect
transform.translate((rect.w - (b_width * scale)) / 2.0,
(rect.h - (b_height * scale)) / 2.0);
if (scale > 1.) {
// Use QPainter scaling
transform.scale(scale, scale);
}
}
}

// Get bottom frame
uint8_t *a_image = NULL;
error = mlt_frame_get_image(a_frame, &a_image, format, width, height, 0);
if (error) {
free(interps);
return error;
}
// Prepare output image
Expand All @@ -284,18 +318,10 @@ static int get_image(mlt_frame a_frame,
// Copy bottom frame in output
memcpy(*image, a_image, image_size);

// We don't do subpixel smoothing for nearest neighbour interpolation
// so people can use that to upscale pixel art and keep the hard edges.
bool hqPainting = interps && strcmp(interps, "nearest") != 0;

// convert bottom mlt image to qimage
QImage bottomImg;
convert_mlt_to_qimage(*image, &bottomImg, *width, *height, *format);

// convert top mlt image to qimage
QImage topImg;
convert_mlt_to_qimage(b_image, &topImg, b_width, b_height, *format);

// setup Qt drawing
QPainter painter(&bottomImg);
painter.setCompositionMode(mode);
Expand All @@ -304,15 +330,18 @@ static int get_image(mlt_frame a_frame,
painter.setOpacity(opacity);

// Composite top frame
painter.drawImage(0, 0, topImg);
if (scaled) {
painter.drawImage(0, 0, scaledSource);
} else {
painter.drawImage(0, 0, topImg);
}

// finish Qt drawing
painter.end();
convert_qimage_to_mlt(&bottomImg, *image, *width, *height);
mlt_frame_set_image(a_frame, *image, image_size, mlt_pool_release);
// Remove potentially large image on the B frame.
mlt_frame_set_image(b_frame, NULL, 0, NULL);
free(interps);
return error;
}

Expand Down
Loading