频道栏目
首页 > 资讯 > 其他 > 正文

制作证件照排版软件

16-10-08        来源:[db:作者]  
收藏   我要投稿

制作证件照排版软件

媳妇开了个摄影店,经常要拍证件照,证件照拍好后,需要在ps里面修饰一下,然后排成多张进行打印。
之前排版都是手工在ps里进行的。如下图所示,左侧是裁剪好的一寸证件照,右图是排好版准备打印的,排版照片
这里写图片描述
其中右侧9张照片排版是手工排版的,虽然简单,但也比较费时间,而且照片的间距是靠目测的,没有固定值。作为程序员,我感觉到可以用软件来做这个事情。

制作软件

说干就干,首先想到用熟悉的QT来做一个,在说怎么做之前,先看看最终效果
这里写图片描述
利用这个软件,只要拖入修饰裁剪好的单张照片,即可自动生成排版好的图片,间距都是固定的,非常整齐,并且可以直接点击打印按钮进行打印。
好了,开始看代码

图片浏览器

首先需要做一个图片浏览器,用于展示排版好的图片,我通过直接继承QWidget类,并重写paintEvent函数来绘制图片,头文件声明如下

// imageview.h
class ImageView : public QWidget
{
    Q_OBJECT
public:
    explicit ImageView(QWidget *parent = 0);

    //重点函数:重载绘制事件用于绘制图片
    void paintEvent( QPaintEvent * );
    //设置要显示的图片
    void setImage(const QImage &image);
    void setImage(const QString &imageFile);

    // 设置四周的空白区域,图片四周不顶满,留点空白会好看一些
    // 不过现在看来四周边距设置一个值就行了,没必要设置4个值,当时考虑太多
    void setBottomPadding(int padding);
    void setTopPadding(int padding);
    void setRightPadding(int padding);
    void setLeftPadding(int padding);
    //
    void setBackgroundColor(QColor color);
signals:

public slots:
private :
    QImage currentImage;

    int bottomPadding;
    int topPadding;
    int rightPadding;
    int leftPadding;

    QColor backgroundColor;
};

下面看一下具体实现代码

ImageView::ImageView(QWidget *parent) :
    QWidget(parent)
{
    bottomPadding = 10;
    topPadding = 10;
    rightPadding = 10;
    leftPadding = 10;
    setBackgroundColor(Qt::black);
}

void ImageView::paintEvent( QPaintEvent *paintEvent )
{
    QPainter painter(this);
    //先在widget上全部填上背景色
    painter.fillRect(0,0,width(),height(),backgroundColor);

    //如果没有设置图片,就直接退出,那么整个wdiget就会显示成背景色
    if(currentImage.isNull()) {
        return;
    }
    //实际可显示图片的区域,要除去四周留白
    int actualWidth = width() - (rightPadding + leftPadding);
    int actualHeight = height() - (topPadding + bottomPadding);

    //将图片缩放到显示区域的大小,保持比例不变
    QImage showImage =
        currentImage.scaled(QSize(actualWidth,actualHeight),Qt::KeepAspectRatio);
    //计算显示图片的左上角坐标,让图片居中显示
    int x = leftPadding + (actualWidth - showImage.width()) / 2;
    int y = topPadding  + (actualHeight - showImage.height()) / 2;
    //绘制图片
    painter.drawImage(x,y,showImage);
}

void ImageView::setImage(const QImage &image)
{
    currentImage = image;
    update();
}

这个图片浏览器是非常简单的,最主要的问题就是不能缩放图片,只能以widget大小最大化显示图片,但在我们这个场景下面也足够用了。

功能介绍

首先看一下软件功能,在截个图,这里为了区分说明功能,将配置改的有点奇怪
这里写图片描述
软件的功能有三点
- 照片张数设置
在左上方的打开按钮边上,有张数设置,分别表示横向排几张,纵向排几张
- 边距和间隔设置
在界面右上方有边距和间隔设置,分别设置照片之间的间隔和照片四周的间距
- 打印功能
好了,介绍完毕,看一下主窗口的代码,总共200行左右

主窗口的构造函数

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //打开,保存,打印按钮的事件处理
    connect(ui->openButton,SIGNAL(clicked()),this,SLOT(openFile()));
    connect(ui->saveButton,SIGNAL(clicked()),this,SLOT(saveFile()));
    connect(ui->printButton,SIGNAL(clicked()),this,SLOT(printImage()));

    //边距,间隔,或者照片张数发生变化时候,都要重新生成并显示新的图片,达到实时更新的效果
    connect(ui->marginBox,SIGNAL(valueChanged(int)),this,SLOT(updateImage()));
    connect(ui->xcountBox,SIGNAL(valueChanged(int)),this,SLOT(updateImage()));
    connect(ui->ycountBox,SIGNAL(valueChanged(int)),this,SLOT(updateImage()));
    connect(ui->paddingBox,SIGNAL(valueChanged(int)),this,SLOT(updateImage()));

    //从注册表中读取照片边距和间隔设置
    //如果没有设置,则默认值是30
    QSettings settings;
    int padding = settings.value("padding",30).toInt();
    int margin = settings.value("margin",30).toInt();
    ui->marginBox->setValue(margin);
    ui->paddingBox->setValue(padding);
    //开启拖放功能
    setAcceptDrops(true);
}

对应构造函数的边距和间隔设置,需要在窗口关闭时保存这两个设置

void MainWindow::closeEvent(QCloseEvent *event)
{
    QSettings settings;
    settings.setValue("margin",ui->marginBox->value());
    settings.setValue("padding",ui->paddingBox->value());
}

拖放文件处理

拖放是简化软件操作的重要手段,在QT中通过重载dragEnterEvent和dropEvent两个函数实现

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/uri-list"))
            event->acceptProposedAction();
}

void MainWindow::dropEvent(QDropEvent *event)
{
    QList urls = event->mimeData()->urls();
    if(urls.isEmpty())
        return;
    QString fileName = urls.at(0).toLocalFile();
    QImage image(fileName);
    if(image.isNull()) {
        return;
    }
    openImage(image);
}

固定张数处理

对于最常见的1寸和2寸照片,照片张数是固定的,1寸是9张,2寸是4张
这里直接写死了,最好是做个可配置化,偷懒没有做

#define ONE_INCH 1 //1寸
#define TWO_INCH 2 //2寸
static int inch(const QSize size)
{
    if(size == QSize(250,350)) {
        return ONE_INCH;
    }
    if(size == QSize(350,500)){
        return TWO_INCH;
    }
    return -1;
}

void MainWindow::openImage(QImage image)
{
    if(image.isNull()) {
        return;
    }
    int i = inch(image.size());
    switch(i) {
        case ONE_INCH:
            ui->xcountBox->setValue(3);
            ui->ycountBox->setValue(3);
            break;
        case TWO_INCH:
            ui->xcountBox->setValue(2);
            ui->ycountBox->setValue(2);
            break;

    }
    currentImage = image;
    updateImage();
}

生成拼版图片

当有配置改变或者新图片打开时会调用updateImage函数
在这个函数中会根据当前配置生成新图片,并放到图片浏览器中显示

void MainWindow::updateImage()
{
    if(currentImage.isNull()) {
        return;
    }
    int new_xcount = ui->xcountBox->value();
    int new_ycount = ui->ycountBox->value();

    int new_margin = ui->marginBox->value();
    int new_padding = ui->paddingBox->value();

    xcount = new_xcount == 0 ? 1 : new_xcount;
    ycount = new_ycount == 0 ? 1 : new_ycount;
    margin = new_margin;
    padding = new_padding;
    generateImage = createImage();
    ui->imageView->setImage(generateImage);

}

QImage MainWindow::createImage()
{
    int width = xcount * currentImage.width() + margin * (xcount - 1) + padding * 2;
    int height = ycount * currentImage.height() + margin * (ycount - 1) + padding *2;

    QImage dstImage(width,height,currentImage.format());
    QPainter painter(&dstImage);

    dstImage.setDotsPerMeterX(10000);
    dstImage.setDotsPerMeterY(10000);
    painter.fillRect(0,0,dstImage.width(),dstImage.height(),Qt::white);
    for(int w = 0; w < xcount; w++){
        for(int h = 0; h < ycount; h ++) {
            int x = padding + (margin + currentImage.width()) * w ;
            int y = padding + (margin + currentImage.height()) * h;
            painter.drawImage(x,y,currentImage);
        }
    }
    return dstImage;
}

打印功能

当点击打印按钮时会显示打印对话框,点击确定后,可以直接打印图片
这里写图片描述

void MainWindow::printImage()
{
    if(generateImage.isNull()) {
        return;
    }
    QPrinter printer;
    QPrintDialog printDialog(&printer,this);
    if(printDialog.exec() != QDialog::Accepted) {
        return;
    }
    //设置分辨率为254
    printer.setResolution(254);
    //设置纸张为A4
    printer.setPageSize(QPrinter::A4);
    QPainter painter(&printer);
    painter.drawImage(0,0,generateImage);
}

当打开图片或者更改设置后会调用updateImage函数,在这个函数里面处理一下张数,边距,间隔设置,
然后生成新的拼版图片并调用图片浏览器显示出来。

相关TAG标签
上一篇:程序员面试金典:清除行列
下一篇:坦克大战小游戏(Java)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站