File indexing completed on 2024-04-21 04:51:33
0001 /* 0002 SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 This file is part of Kdenlive. See www.kdenlive.org. 0004 0005 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "kthumb.h" 0009 #include "core.h" 0010 #include "kdenlivesettings.h" 0011 #include "profiles/profilemodel.hpp" 0012 0013 #include <mlt++/Mlt.h> 0014 0015 #include <QPixmap> 0016 // static 0017 QPixmap KThumb::getImage(const QUrl &url, int width, int height) 0018 { 0019 if (!url.isValid()) { 0020 return QPixmap(); 0021 } 0022 return getImage(url, 0, width, height); 0023 } 0024 0025 // static 0026 QPixmap KThumb::getImage(const QUrl &url, int frame, int width, int height) 0027 { 0028 QScopedPointer<Mlt::Profile> profile(new Mlt::Profile(pCore->getCurrentProfilePath().toUtf8().constData())); 0029 if (height == -1) { 0030 height = int(width * double(profile->height()) / profile->width()); 0031 } 0032 QPixmap pix(width, height); 0033 if (!url.isValid()) { 0034 return pix; 0035 } 0036 Mlt::Producer *producer = new Mlt::Producer(*(profile.data()), url.toLocalFile().toUtf8().constData()); 0037 if (KdenliveSettings::gpu_accel()) { 0038 QString service = producer->get("mlt_service"); 0039 QString res = producer->get("resource"); 0040 delete producer; 0041 producer = new Mlt::Producer(*(profile.data()), service.toUtf8().constData(), res.toUtf8().constData()); 0042 Mlt::Filter scaler(*(profile.data()), "swscale"); 0043 Mlt::Filter converter(*(profile.data()), "avcolor_space"); 0044 producer->attach(scaler); 0045 producer->attach(converter); 0046 } 0047 pix = QPixmap::fromImage(getFrame(producer, frame, width, height)); 0048 delete producer; 0049 return pix; 0050 } 0051 0052 // static 0053 QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int width, int height, int displayWidth) 0054 { 0055 if (producer == nullptr || !producer->is_valid()) { 0056 QImage p(displayWidth == 0 ? width : displayWidth, height, QImage::Format_ARGB32_Premultiplied); 0057 p.fill(QColor(Qt::red).rgb()); 0058 return p; 0059 } 0060 if (producer->is_blank()) { 0061 QImage p(displayWidth == 0 ? width : displayWidth, height, QImage::Format_ARGB32_Premultiplied); 0062 p.fill(QColor(Qt::black).rgb()); 0063 return p; 0064 } 0065 0066 producer->seek(framepos); 0067 Mlt::Frame *frame = producer->get_frame(); 0068 const QImage p = getFrame(frame, width, height, displayWidth); 0069 delete frame; 0070 return p; 0071 } 0072 0073 // static 0074 QImage KThumb::getFrame(Mlt::Producer &producer, int framepos, int width, int height, int displayWidth) 0075 { 0076 if (!producer.is_valid()) { 0077 QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied); 0078 p.fill(QColor(Qt::red).rgb()); 0079 return p; 0080 } 0081 producer.seek(framepos); 0082 Mlt::Frame *frame = producer.get_frame(); 0083 const QImage p = getFrame(frame, width, height, displayWidth); 0084 delete frame; 0085 return p; 0086 } 0087 0088 // static 0089 QImage KThumb::getFrame(Mlt::Frame *frame, int width, int height, int scaledWidth) 0090 { 0091 if (frame == nullptr || !frame->is_valid()) { 0092 qDebug() << "* * * *INVALID FRAME"; 0093 return QImage(); 0094 } 0095 int ow = width; 0096 int oh = height; 0097 mlt_image_format format = mlt_image_rgba; 0098 const uchar *imagedata = frame->get_image(format, ow, oh); 0099 if (imagedata) { 0100 QImage temp(ow, oh, QImage::Format_ARGB32); 0101 memcpy(temp.scanLine(0), imagedata, unsigned(ow * oh * 4)); 0102 if (scaledWidth == 0 || scaledWidth == width) { 0103 return temp.rgbSwapped(); 0104 } 0105 return temp.rgbSwapped().scaled(scaledWidth, height == 0 ? oh : height); 0106 } 0107 return QImage(); 0108 } 0109 0110 // static 0111 int KThumb::imageVariance(const QImage &image) 0112 { 0113 int delta = 0; 0114 int avg = 0; 0115 int bytes = int(image.sizeInBytes()); 0116 int STEPS = bytes / 2; 0117 QVarLengthArray<uchar> pivot(STEPS); 0118 const uchar *bits = image.bits(); 0119 // First pass: get pivots and taking average 0120 for (int i = 0; i < STEPS; ++i) { 0121 pivot[i] = bits[2 * i]; 0122 avg += pivot.at(i); 0123 } 0124 if (STEPS != 0) { 0125 avg = avg / STEPS; 0126 } 0127 // Second Step: calculate delta (average?) 0128 for (int i = 0; i < STEPS; ++i) { 0129 int curdelta = abs(int(avg - pivot.at(i))); 0130 delta += curdelta; 0131 } 0132 if (STEPS != 0) { 0133 return delta / STEPS; 0134 } 0135 return 0; 0136 }