QImage конвертация картинки

389
26 ноября 2016, 18:56

Есть картинка в bmp формате открываю её с помощью диалога выбора файла, нужно её конвертировать в jpg формат средствами qt, как это сделать? далее по нажатию кнопки "вывести на форму" картинка формата jpg выводится в виджет.

Answer 1

JPG - это файловый контейнер, плюс кодек. Прежде чем вывести jpeg-картинку на экран, данные проходят конвертацию в один из удобных для рисования форматов. То же самое с BMP.

Открыть любой из поддерживаемого формата файлов изображений можно так:

QImage img("my_image.bmp");

Сохранить ранее открытый файл в другой формат так:

img.save("my_image.jpg");

Нарисовать QImage на виджете проще всего, используя QLabel:

QLabel *label = new QLabel(this);
label->setPixmap(QPixmap::fromImage(img));

... или без QImage:

QLabel *label = new QLabel(this);
label->setPixmap(QPixmap("my_image.bmp"));

Если хочется рисовать на фоне произвольного виджета, потребуется переопределить событие QWidget::paintEvent():

void MyWidget::paintEvent(QPaintEvent *event) {
    QPixmap pix("my_image.bmp");
    if(pix.isNull() == false) {
        QRect dst_rc = rect();
        if(dst_rc.width() > dst_rc.height())
            pix = pix.scaledToHeight(dst_rc.height());
        else if(dst_rc.height() > dst_rc.width())
            pix = pix.scaledToWidth(dst_rc.width());
        dst_rc = pix.rect();
        dst_rc.moveCenter(rect().center());
        QPainter painter(this);
        painter.drawPixmap(dst_rc, pix);
    }
    event->accept();
}

Дополнение

Загрузку файла изображения непосредственно в paintEvent() лучше не осуществлять, поскольку операция эта может оказаться ощутимо затратной, да и производиться будет каждый раз при перерисовке виджета. Лучше вынести это в отдельный метод класса виджета, принимающего в качестве атрибута имя файла.

Ещё, как вариант, можно задействовать кэш:

void MyWidget::paintEvent(QPaintEvent *event) {
    const QString fname("my_image.bmp");
    QPixmap pix;
    if(QPixmapCache::find(fname, &pix) == false) {
        pix.load(fname);
        if(pix.isNull() == false) {
            QRect dst_rc = rect();
            if(dst_rc.width() > dst_rc.height())
                pix = pix.scaledToHeight(dst_rc.height());
            else if(dst_rc.height() > dst_rc.width())
                pix = pix.scaledToWidth(dst_rc.width());
            QPixmapCache::insert(fname, pix);
        }
    }
    if(pix.isNull() == false) {
        QRect dst_rc = pix.rect();
        dst_rc.moveCenter(rect().center());
        QPainter painter(this);
        painter.drawPixmap(dst_rc, pix);
    }
    event->accept();
}

В варианте кода с кэшем изображение будет загружено и преобразовано под размер виджета лишь один раз. Далее, пока жив кэш, будет лишь рисоваться, что конечно сэкономит ресурсы.

На всякий случай отмечу, что объекты в глобальном статическом QPixmapCache живут не более 30 секунд. Если это не устраивает, то можно использовать QCache или что-то своё производное.

READ ALSO
Ошибка в деструкторе сокета boost

Ошибка в деструкторе сокета boost

Используется следующая модель абстракции:

305
Перегрузка оператор С++

Перегрузка оператор С++

Такой вопросЯ перегружаю операторы для работы с вектором, который состоит из трек точек

247
Ошибки SIGABRT и с sysmalloc

Ошибки SIGABRT и с sysmalloc

Пишу программу по двоичным деревьям

267