[qt topic] – 二維繪圖研習,做一個簡單批量水印工具
作者:jason lee
日期:2010-05-02
平台:qt sdk v2010.02.1 + windows xp
聲明:文章作者僅在intel軟體網絡和csdn部落格發表本文,如有轉載,請注明出處
[1]二維繪圖概覽
qt中的二維繪圖是基于qpainter、qpaintengine和qpaintdevice機制的:以qpaintengine作為中間接口,使用qpainter在不同繪圖裝置上進行繪圖操作,而qpaintdevice就是可使用qpainter進行繪圖的二維空間。
使用qpainter可以在繪圖裝置上進行繪制以下類的執行個體:qimage、qbitmap、qicon、qpixmap、qpicture等各種圖像和qpoint、qline、qpolygon等各種圖形以及其它許多,難以列舉。
目前qpaintdevice的子類有qwidget、qglwidget、qimage、qpixmap、qglpixelbuffer、qglframebufferobject、qpicture、qprinter。也就是說,可以使用qpainter對這些類的執行個體進行繪圖操作。
[2]批量水印工具簡單設想
第一,既然是批量處理,那麼第一個要求是能夠打開多個檔案。在這裡,我将之處理為打開一個檔案夾下面所有可支援的圖檔,但并未繼續遞歸深入地讀取子檔案夾。
第二,要有水印功能,就要求工具能夠對打開的圖檔進行繪圖操作。這一點比較簡單,就是以上提到的使用qpainter在繪圖裝置上(比如qimage)進行繪圖操作。針對這項功能,我隻是簡單地提供一個行文本框以輸入要水印的文字。
第三,因為隻是一個簡單的、練手的小工具,是以我真的十分簡單地實作了它的界面、功能。
第四,可以稍微讨論的擴充有:不隻是可以用文本進行水印,也可以用圖檔,原理基本一緻;可以繼續遞歸地打開子檔案夾中的圖像;可以對qlistwidget中的項進行右鍵處理,比如從清單中移除;其它……
[3]簡單水印工具的實作
首先是布局代碼。我簡單地将界面分為3列:第一列用來打開目标檔案夾,進而對裡面的圖檔進行處理;第二列是圖檔清單,可以切換着觀察圖檔;第三列就是圖檔浏覽區域。以下是部分代碼:
qlabel *marklabel;
qlineedit *marktext;
qhboxlayout *marklayout;
qlabel *folderlabel;
qlineedit *folderedit;
qpushbutton *openfolderbtn;
qhboxlayout *folderlayout;
qpushbutton *applybtn;
qvboxlayout *leftlayout;
qlistwidget *fileslist;
qlabel *imagelabel;
qscrollarea *scrollarea;
qhboxlayout *mainlayout;
接着是打開目标檔案夾,
connect(openfolderbtn, signal(clicked()), this, slot(slotopenfolder()));
dirpath = qfiledialog::getexistingdirectory(this, tr("please select a directory"), "",
qfiledialog::showdirsonly | qfiledialog::dontresolvesymlinks);
folderedit->settext(dirpath);
qdir dir(dirpath);
然後讀取該目錄下所有可支援的圖檔:
qstringlist filters;
foreach (qbytearray format, qimagereader::supportedimageformats())
filters += "*." + format;
foreach (qstring file, dir.entrylist(filters, qdir::files)){
files.append(file);
fileslist->additem(file);
}
并且浏覽第一張圖檔:
if(!files.isempty()){
qimage image(dirpath + '/' + files.at(0));
imagelabel->setpixmap(qpixmap::fromimage(image));
imagelabel->adjustsize();
到這裡,我們實作了打開目标檔案夾并将目錄下所有圖像檔案添加進來的功能。
為了實作點選不同的圖檔item能達到切換圖檔進行觀看的功能,首先連接配接信号和槽:
connect(fileslist, signal(currentrowchanged(int)), this, slot(slotchangeimage(int)));
通過qlistwidget目前item的切換信号連接配接到切換圖像的槽,具體代碼如下:
void topic::slotchangeimage(int i){
if(-1 == i) return;
qimage image(dirpath + '/' + files.at(i));
這就達到了切換浏覽圖檔的目的了。
最後就是對所有圖檔進行水印處理了。
首先,要確定有用來水印的文字,marktext就是此用途:
if(marktext->text() == ""){
qmessagebox::warning(this, tr("warning"), tr("no text for marking"));
return;
在有水印文本的條件下,使用qpainter對象來對qimage這個qpaintdevice的子類的執行個體進行繪圖,本質就是簡單地使用一下drawtext成員函數:
for(int i=0; i<files.size(); ++i){
qpainter painter(&image);
painter.setrenderhint(qpainter::antialiasing, true);
painter.setpen(qpen(qt::blue, 20, qt::solidline, qt::roundcap, qt::roundjoin));
painter.drawtext(10, 10, marktext->text());
image.save(dirpath + '/' + files.at(i));
imagelabel->setpixmap(qpixmap::fromimage(qimage(dirpath + '/' + files.at(0))));
在上面代碼中,每次處理完一張圖檔都立即儲存,而如果需要的話可以稍微改動下僅僅實作預覽功能,待使用者确認後再進行應用以及儲存。
水印後的效果圖如下:
由于本次的代碼挺簡單的,就不特地做上傳了。
各位晚安!