2014年3月14日金曜日

Qtで画像圧縮

ちょっと所用があって、Qtを使った画像圧縮ソフトを作った。

倍率は0から最大99倍まで、不必要に大きなサイズにすると処理が重くなるので注意、
変換後の画像形式はjpegのみ。

ubuntuとwindowsで動作確認

以下コード C++ソースのみ 全ファイルはここ

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QFileInfo>
#include <QDebug>
#include <QPainter>
#include <QRect>


//範囲for用の  添字イテレータ intを返す
class CountIterator
{
public:
    constexpr CountIterator(int set):index(set){;}
   //デリファレンス
    int operator *() const
    {
        const int out=index;
       //index++;
        return out;
    }
    //非一致判定
    bool operator !=(CountIterator set) const{
        if(index!=set.Index()){
            return true;
        }else{
            return false;
        }
    }
    //インクリメント
    void operator ++()
    {
        index++;
    }
    //比較用関数
    int Index() const {
        return index;
    }
private:
    int index;
};

//範囲for用のカウンタ
class SmartCountor
{
public:
    constexpr SmartCountor(int size):index(0),countSize(size){;}
    constexpr SmartCountor(int pos,int length):index(pos),countSize(pos+length){}
    constexpr CountIterator begin() const {return CountIterator(index);}
    constexpr CountIterator end() const {return CountIterator(countSize);}
private:
    int index;
    int countSize;
};


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:

    void on_ImageFileOpen_triggered();

    void on_ClearButton_clicked();

    void on_SetSaveFolderButton_clicked();

    void on_DoConvertButton_clicked();

    void on_AddImageButton_clicked();

    void on_RemoveIMageButton_clicked();

private:
    Ui::MainWindow *ui;
    QStringList CompressImageNames;
    //QString SaveDirName;
    QString imageSelectDir;
    QString saveFolderName;
    void updateListWidget();
};

#endif // MAINWINDOW_H

mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("画像圧縮");
}

MainWindow::~MainWindow()
{
    delete ui;
}

//ファイルオープン
void MainWindow::on_ImageFileOpen_triggered()
{
    //QString dir;
    //ファイル名を取得
    QStringList strlist=QFileDialog::getOpenFileNames(this,QString("画像選択"),
                                                      imageSelectDir,
                                                      tr("Images (*.png *.xpm *.jpg)"));
    if(strlist.isEmpty()==false){
        imageSelectDir=QFileInfo(strlist[0]).absolutePath();
        CompressImageNames+=strlist;
        updateListWidget();
    }
}

//ファイルリストの削除
void MainWindow::on_ClearButton_clicked()
{

    //ファイル名をクリア
    CompressImageNames.clear();
    //表示をクリア
    ui->listWidget->clear();
}

//保存フォルダ選択
void MainWindow::on_SetSaveFolderButton_clicked()
{
    saveFolderName=QFileDialog::getExistingDirectory(this,"画像ファイルを保存するフォルダを選択");
    ui->lineEdit->setText(saveFolderName);
}

//変換
void MainWindow::on_DoConvertButton_clicked()
{
    //ファイルの変換
    //確認
    if(saveFolderName.isEmpty()==true){
        ui->statusBar->showMessage("保存先のフォルダが設定されていません",5000);
        return;
    }
    if(CompressImageNames.isEmpty()==true){
        ui->statusBar->showMessage("変換する画像データが設定されていません",5000);
        return;
    }
    //変換処理
    auto ConvertImage=[&](QString saveDirName,QString ImageName,const double resize,const int quality){
        //ファイルの読み込み
        QImage comimage(ImageName);
        if(comimage.isNull()==true){
            //存在しない場合
            qDebug() << "image can not open";
            return;
        }
        const QString filename="comp_"+QFileInfo(ImageName).baseName()+".jpg";
        ui->statusBar->showMessage(QString(QFileInfo(ImageName).fileName()+"  "+filename+" に変換中"),-1);
        QImage saveimage(static_cast<int>(comimage.width()*resize),
                         (comimage.height()*resize),QImage::Format_ARGB32_Premultiplied);
        saveimage.fill(Qt::transparent);
        QPainter painter(&saveimage);
        painter.drawImage(QRect(0,0,saveimage.width(),saveimage.height()),comimage);
        QString savename=saveDirName+"/"+filename;
        saveimage.save(savename,"jpg",quality);
        return;
    };

    if(CompressImageNames.isEmpty()==false){
        const double resize=ui->SetResizeFactor->value();
        const int quality=ui->SetQualityBox->value();
        for(const int i:SmartCountor(CompressImageNames.count())){
            ConvertImage(saveFolderName,CompressImageNames[i],resize,quality);
        }
        ui->statusBar->showMessage("画像の変換が完了しました",5000);
    }

}

void MainWindow::on_AddImageButton_clicked()
{
    on_ImageFileOpen_triggered();
}

void MainWindow::on_RemoveIMageButton_clicked()
{
    const int index=ui->listWidget->currentIndex().column();
    CompressImageNames.removeAt(index);
    updateListWidget();
}

void MainWindow::updateListWidget()
{
    //表示のアップデート
    ui->listWidget->clear();
    QStringList filenames;
    filenames.reserve(CompressImageNames.count());
    for(auto &filename:CompressImageNames){
        filenames.append(QFileInfo(filename).fileName());
    }
    ui->listWidget->addItems(filenames);
}