#include "batch.h" #include "uimanager.h" #include "browser.h" #include "dialogs.h" #include "imageutils.h" #include "ifapp.h" #include "jpegtransform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void createTextLabel(const QString &text, const QColor &color, const QFont &font, QImage &destImage) { QFontMetrics fm(font); QRect r(0, 0, fm.width(text), fm.height()); // TODO: Get rid of tmp pixmap and Qt - call FreeType or Magick's annotate // directly QPixmap tmpPix(r.width(), r.height()); tmpPix.fill(Qt::black); QPainter p; p.begin(&tmpPix); p.setFont(font); p.setPen(Qt::white); p.drawText(0, 0, r.width(), r.height(), Qt::AlignCenter, text); p.end(); destImage.reset(); destImage.create(r.width(), r.height(), 32); QImage srcImage = tmpPix.convertToImage(); if(srcImage.depth() < 32) srcImage.convertDepth(32); unsigned int *dest = (unsigned int *)destImage.bits(); unsigned int *src = (unsigned int *)srcImage.bits(); int i, len = r.width()*r.height(); for(i=0; i < len; ++i){ if(src[i] == Qt::black.rgb()) dest[i] = qRgba(0, 0, 0, 0); else if(src[i] == Qt::white.rgb()) dest[i] = color.rgb(); else{ // src will be grayscale, so just use red for alpha dest[i] = qRgba(color.red(), color.green(), color.blue(), qRed(src[i])); } } } bool applyTextLabel(TextPosition pos, QImage &textImage, QImage &destImage) { if(textImage.width() > destImage.width() || textImage.height() > destImage.height()){ // TODO: error dlg qWarning("Image too small for text label! Skipping."); return(false); } int sx, sy, dx, dy; int xstart, ystart; unsigned int *src, *dest; int r, g, b, alpha; if(pos == UpperLeftText){ xstart = 0; ystart = 0; } else if(pos == BottomLeftText){ xstart = 0; ystart = destImage.height()-textImage.height()-1; } else if(pos == UpperRightText){ xstart = destImage.width()-textImage.width()-1; ystart = 0; } else if(pos == BottomRightText){ xstart = destImage.width()-textImage.width()-1; ystart = destImage.height()-textImage.height()-1; } else{ // center xstart = ((destImage.width()-textImage.width())/2)-1; ystart = ((destImage.height()-textImage.height())/2)-1; } for(sy = 0, dy = ystart; sy < textImage.height(); ++sy, ++dy){ src = (unsigned int *)textImage.scanLine(sy); dest = (unsigned int *)destImage.scanLine(dy); for(sx = 0, dx = xstart; sx < textImage.width(); ++sx, ++dx){ alpha = qAlpha(src[sx]); if(!alpha) ; else if(alpha == 255) dest[dx] = src[sx]; else{ float srcPercent = ((float)alpha)/255.0; float destPercent = 1.0-srcPercent; r = (int)(qRed(src[sx])*srcPercent + qRed(dest[dx])*destPercent); g = (int)(qGreen(src[sx])*srcPercent + qGreen(dest[dx])*destPercent); b = (int)(qBlue(src[sx])*srcPercent + qBlue(dest[dx])*destPercent); dest[dx] = qRgba(r, g, b, 255); } } } return(true); } bool getRadiusAndDeviation(const QString &caption, double &radius, double &stdDeviation, QWidget *parent) { KIFGet2DoubleDialog dlg(caption, i18n("Radius (use 0 for default)"), 5.0, -5.0, 0.1, 0.0, i18n("Standard deviation:"), 5.0, -5.0, 0.1, 1.0, parent); dlg.setCaption(i18n("Effect Parameters")); if(dlg.exec() == QDialog::Accepted){ radius = dlg.value1(); stdDeviation = dlg.value2(); return(true); } return(false); } KIFBatchPixmapView::KIFBatchPixmapView(QWidget *parent, const char *name) : QScrollView(parent, name) { pix = NULL; } KIFBatchPixmapView::~KIFBatchPixmapView() { qWarning("In batch pixmap view destructor"); if(pix) delete pix; } void KIFBatchPixmapView::setImage(QImage &img) { if(!pix) pix = new QPixmap(img.width(), img.height()); convertImageToPixmap(img, *pix); resizeContents(img.width(), img.height()); repaintContents(); } void KIFBatchPixmapView::drawContents(QPainter *p, int x, int y, int w, int h) { if(!pix) return; else p->drawPixmap(x, y, *pix, x, y, w, h); } KIFSineWaveDialog::KIFSineWaveDialog(QWidget *parent, const char *name) : QDialog(parent, name, true) { setCaption(i18n("Sine Wave Parameters")); QVBoxLayout *layout = new QVBoxLayout(this, 10); QLabel *lbl = new QLabel(i18n("Please enter the amplitude and\n\ frequency of the sine wave."), this); layout->addWidget(lbl); aInput = new KDoubleNumInput(25.0, this); aInput->setLabel(i18n("Amplitude"), AlignVCenter); layout->addWidget(aInput); fInput = new KDoubleNumInput(150.0, this); fInput->setLabel(i18n("Frequency"), AlignVCenter); layout->addWidget(fInput); layout->addStretch(); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("OK")), SIGNAL(clicked()), this, SLOT(accept())); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), this, SLOT(reject())); layout->addWidget(bbox); }; KIFShadeDialog::KIFShadeDialog(QWidget *parent, const char *name) : QDialog(parent, name, true) { setCaption(i18n("Shade Parameters")); QVBoxLayout *layout = new QVBoxLayout(this, 10); QLabel *lbl = new QLabel(i18n("Please enter the direction of the shading"), this); layout->addWidget(lbl); aInput = new KDoubleNumInput(30.0, this); aInput->setLabel(i18n("Azimuth"), AlignVCenter); layout->addWidget(aInput); eInput = new KDoubleNumInput(30.0, this); eInput->setLabel(i18n("Elevation"), AlignVCenter); layout->addWidget(eInput); KSeparator *sep = new KSeparator(Qt::Horizontal, this); layout->addWidget(sep); colorCB = new QCheckBox(i18n("Color shading"), this); colorCB->setChecked(true); layout->addWidget(colorCB); layout->addStretch(); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("OK")), SIGNAL(clicked()), this, SLOT(accept())); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), this, SLOT(reject())); layout->addWidget(bbox); }; KIFTextDialog::KIFTextDialog(QWidget *parent, const char *name) : QDialog(parent, name, true) { KConfig *config = KGlobal::config(); QString oldGrp = config->group(); config->setGroup("BatchAddText"); QVBoxLayout *mainLayout = new QVBoxLayout(this); QGroupBox *alignGroup= new QGroupBox(i18n("Text Position"), this); alignBtns = new QButtonGroup(this); alignBtns->hide(); QGridLayout *alignLayout = new QGridLayout(alignGroup, 1, 1, 15); QRadioButton *ulBtn = new QRadioButton(i18n("Upper Left"), alignGroup); alignBtns->insert(ulBtn, UpperLeftText); alignLayout->addWidget(ulBtn, 0, 0); QRadioButton *urBtn = new QRadioButton(i18n("Upper Right"), alignGroup); alignBtns->insert(urBtn, UpperRightText); alignLayout->addWidget(urBtn, 0, 2); QRadioButton *cBtn = new QRadioButton(i18n("Centered"), alignGroup); alignBtns->insert(cBtn, CenterText); alignLayout->addWidget(cBtn, 1, 1); QRadioButton *llBtn = new QRadioButton(i18n("Lower Left"), alignGroup); alignBtns->insert(llBtn, BottomLeftText); alignLayout->addWidget(llBtn, 2, 0); QRadioButton *lrBtn = new QRadioButton(i18n("Lower Right"), alignGroup); alignBtns->insert(lrBtn, BottomRightText); alignLayout->addWidget(lrBtn, 2, 2); mainLayout->addWidget(alignGroup); alignBtns->setButton(0); QGroupBox *colorGroup = new QGroupBox(i18n("Text Options"), this); QHBoxLayout *colorLayout = new QHBoxLayout(colorGroup, 15); QLabel *colorLbl = new QLabel(i18n("Text color:"), colorGroup); colorLayout->addWidget(colorLbl); colorBtn = new KColorButton(colorGroup); colorBtn->setColor(config->readColorEntry("Color", &Qt::black)); colorLayout->addWidget(colorBtn); numInput = new KIntNumInput(100, colorGroup); numInput->setLabel(i18n("Opacity"), AlignLeft); numInput->setRange(10, 100); numInput->setValue(config->readNumEntry("Opacity", 100)); colorLayout->addWidget(numInput); mainLayout->addWidget(colorGroup); fontChooser = new KFontChooser(this); fontChooser->setSampleText(config->readEntry("Text", i18n("Add your text here!"))); mainLayout->addWidget(fontChooser); mainLayout->addStretch(); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("OK")), SIGNAL(clicked()), this, SLOT(accept())); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), this, SLOT(reject())); mainLayout->addWidget(bbox); setCaption(i18n("Add Text Options")); config->setGroup(oldGrp); } void KIFTextDialog::accept() { qWarning("In KIFTextDialog::accept"); if(result() == Accepted){ KConfig *config = KGlobal::config(); QString oldGrp = config->group(); config->setGroup("BatchAddText"); config->writeEntry("Color", colorBtn->color()); config->writeEntry("Opacity", numInput->value()); config->writeEntry("Text", fontChooser->sampleText()); config->sync(); } QDialog::accept(); } TextPosition KIFTextDialog::pos() { if(alignBtns->selected()) return((TextPosition)alignBtns->id(alignBtns->selected())); return(UpperLeftText); } KIFGet2DoubleDialog::KIFGet2DoubleDialog(const QString &captionStr, const QString &input1Str, double input1Upper, double input1Lower, double input1Step, double input1Val, const QString &input2Str, double input2Upper, double input2Lower, double input2Step, double input2Val, QWidget *parent, const char *name) : QDialog(parent, name, true) { QGridLayout *layout = new QGridLayout(this, 1, 1, 5, 5); QLabel *lbl = new QLabel(captionStr, this); lbl->setAlignment(Qt::AlignCenter); layout->addMultiCellWidget(lbl, 1, 1, 0, 2); layout->addRowSpacing(2, 10); lbl = new QLabel(input1Str, this); lbl->setAlignment(AlignRight | AlignVCenter); layout->addWidget(lbl, 3, 1); lbl = new QLabel(input2Str, this); lbl->setAlignment(AlignRight | AlignVCenter); layout->addWidget(lbl, 4, 1); spinBox1 = new KDoubleSpinBox(input1Lower, input1Upper, input1Step, input1Val, 2, this); layout->addWidget(spinBox1, 3, 2); spinBox2 = new KDoubleSpinBox(input2Lower, input2Upper, input2Step, input2Val, 2, this); layout->addWidget(spinBox2, 4, 2); layout->addRowSpacing(5, 10); layout->addMultiCellWidget(new KSeparator(Qt::Horizontal, this), 6, 6, 0, 2); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("OK")), SIGNAL(clicked()), this, SLOT(accept())); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), this, SLOT(reject())); layout->addMultiCellWidget(bbox, 7, 7, 0, 2); layout->setRowStretch(5, 1); layout->setColStretch(0, 1); } KIFBatchProgressWidget::KIFBatchProgressWidget(BatchEffect *effectMgr, QWidget *parent, const char *name) : QWidget(parent, name) { QVBoxLayout *layout = new QVBoxLayout(this, 5, 5); captionLbl = new QLabel(i18n("Filename:"), this); layout->addWidget(captionLbl); layout->addSpacing(16); lbl = new QLabel(i18n("Status..."), this); layout->addWidget(lbl); progress = new KProgress(100, this); layout->addWidget(progress); layout->addStretch(1); layout->addWidget(new KSeparator(Qt::Horizontal, this)); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); connect(bbox->addButton(i18n("Cancel")), SIGNAL(clicked()), effectMgr, SLOT(slotCancel())); bbox->addStretch(1); layout->addWidget(bbox); setCaption(i18n("Batch Effect Progress")); setMinimumWidth(350); resize(sizeHint()); show(); } void KIFBatchProgressWidget::setTitle(const QString &captionStr) { captionLbl->setText(captionStr); } KProgress* KIFBatchProgressWidget::progressBar() { return(progress); } QLabel* KIFBatchProgressWidget::progressLabel() { return(lbl); } KIFBatchPreviewWidget::KIFBatchPreviewWidget(BatchEffect *effectMgr, QWidget *parent, const char *name) : QWidget(parent, name) { QGridLayout *layout = new QGridLayout(this, 1, 1, 5, 5); preview = new KIFBatchPixmapView(this); layout->addMultiCellWidget(preview, 1, 1, 0, 1); captionLbl = new QLabel(i18n("Filename:"), this); layout->addMultiCellWidget(captionLbl, 2, 2, 0, 1); progress = new KProgress(100, this); layout->addWidget(progress, 3, 0); lbl = new QLabel(i18n("Status..."), this); layout->addWidget(lbl, 3, 1); layout->addMultiCellWidget(new KSeparator(Qt::Horizontal, this), 4, 4, 0, 1); KButtonBox *bbox = new KButtonBox(this); bbox->addStretch(1); acceptBtn = bbox->addButton(i18n("Accept this effect")); connect(acceptBtn, SIGNAL(clicked()), effectMgr, SLOT(slotAcceptPreview())); skipBtn = bbox->addButton(i18n("Skip this effect")); connect(skipBtn, SIGNAL(clicked()), effectMgr, SLOT(slotRejectPreview())); cancelBtn = bbox->addButton(i18n("Cancel all effects")); connect(cancelBtn, SIGNAL(clicked()), effectMgr, SLOT(slotCancel())); connect(this, SIGNAL(windowClosed()), effectMgr, SLOT(slotCancel())); layout->addMultiCellWidget(bbox, 5, 5, 0, 1); layout->setColStretch(1, 1); layout->setRowStretch(1, 1); setCaption(i18n("Batch Effect Preview")); setMinimumWidth(450); resize(sizeHint()); show(); } void KIFBatchPreviewWidget::setTitle(const QString &captionStr) { captionLbl->setText(captionStr); } KProgress* KIFBatchPreviewWidget::progressBar() { return(progress); } QLabel* KIFBatchPreviewWidget::progressLabel() { return(lbl); } void KIFBatchPreviewWidget::setPreviewImage(QImage &img) { preview->setImage(img); acceptBtn->setEnabled(true); skipBtn->setEnabled(true); cancelBtn->setEnabled(true); } void KIFBatchPreviewWidget::disable() { acceptBtn->setEnabled(false); skipBtn->setEnabled(false); cancelBtn->setEnabled(false); } void KIFBatchPreviewWidget::closeEvent(QCloseEvent *) { emit windowClosed(); } // New batch effect class BatchEffect::BatchEffect(UIManager *manager, PixieBrowser *browser, QStringList &files, int effectType) : QObject() { type = effectType; mgr = manager; view = browser; fileList = files; textImage = NULL; if(type == Grayscale || type == Invert || type == FlipH || type == FlipV || type == Rot90 || type == Rot180 || type == Rot270 || type == AddText || type == Scale || type == Border) useQt = true; else useQt = false; } BatchEffect::~BatchEffect() { if(textImage) delete textImage; } bool BatchEffect::apply() { if(!getParameters()) return(false); int previewType = KMessageBox::questionYesNoCancel(view, i18n("Do you want to preview effects before applying?"), i18n("Preview Selection")); if(previewType == KMessageBox::Cancel) return(false); if(previewType == KMessageBox::No){ KIFBatchProgressWidget progress(this, NULL); if(useQt){ connect(this, SIGNAL(setProgress(int)), progress.progressBar(), SLOT(setValue(int))); connect(this, SIGNAL(setProgressText(const QString &)), progress.progressLabel(), SLOT(setText(const QString &))); } else kifapp()->setMagickMessageWidgets(progress.progressBar(), progress.progressLabel()); QStringList::Iterator it; bool proceed = true; cancel = false; for(it = fileList.begin(); it != fileList.end() && proceed && !cancel; ++it){ progress.setTitle(i18n("Processing: ") + (*it)); qApp->processEvents(); if(useQt) proceed = applyQtEffect((*it)); else proceed = applyMagickEffect((*it)); } if(!useQt) kifapp()->setMagickMessageWidgets(NULL, NULL); } else{ KIFBatchPreviewWidget progress(this, NULL); if(useQt){ connect(this, SIGNAL(setProgress(int)), progress.progressBar(), SLOT(setValue(int))); connect(this, SIGNAL(setProgressText(const QString &)), progress.progressLabel(), SLOT(setText(const QString &))); } else kifapp()->setMagickMessageWidgets(progress.progressBar(), progress.progressLabel()); QStringList::Iterator it; bool proceed = true; cancel = false; for(it = fileList.begin(); it != fileList.end() && proceed && !cancel; ++it){ progress.setTitle(i18n("Processing: ") + (*it)); qApp->processEvents(); if(useQt) proceed = applyQtEffect((*it), &progress); else proceed = applyMagickEffect((*it), &progress); } if(!useQt) kifapp()->setMagickMessageWidgets(NULL, NULL); } return(true); } void BatchEffect::slotCancel() { cancel = true; } void BatchEffect::slotAcceptPreview() { acceptPreview = true; } void BatchEffect::slotRejectPreview() { rejectPreview = true; } bool BatchEffect::applyMagickEffect(const QString &filename, KIFBatchPreviewWidget *preview) { ExceptionInfo exception; ImageInfo *info = CloneImageInfo(NULL); Image *img; bool save = true; if(preview) preview->disable(); GetExceptionInfo(&exception); qstrcpy(info->filename, QFile::encodeName(filename)); img = ReadImage(info, &exception); if(!img){ DestroyImageInfo(info); return(KMessageBox::warningContinueCancel(NULL, i18n("Cannot open ") + filename + i18n("!"), i18n("File Open Error"), i18n("Continue"), QString::null, true) != KMessageBox::Cancel); } if(type == Normalize) NormalizeImage(img); else if(type == Equalize) EqualizeImage(img); else if(type == IncContrast) ContrastImage(img, true); else if(type == DecContrast) ContrastImage(img, false); else if(type == Solarize) SolarizeImage(img, weight); else if(type == Threshold) ThresholdImage(img, weight); else if(type == Despeckle){ Image *tmp = DespeckleImage(img, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Blur){ Image *tmp = BlurImage(img, radius, sigma, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Emboss){ Image *tmp = EmbossImage(img, radius, sigma, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Charcoal){ Image *tmp = CharcoalImage(img, radius, sigma, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Sharpen){ Image *tmp = SharpenImage(img, radius, sigma, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Edge){ Image *tmp = EdgeImage(img, weight, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Implode){ img->background_color.red = ScaleCharToQuantum(bg.red()); img->background_color.green = ScaleCharToQuantum(bg.green()); img->background_color.blue = ScaleCharToQuantum(bg.blue()); Image *tmp = ImplodeImage(img, weight, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == OilPaint){ Image *tmp = OilPaintImage(img, weight, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Spread){ Image *tmp = SpreadImage(img, (unsigned int)weight, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Swirl){ img->background_color.red = ScaleCharToQuantum(bg.red()); img->background_color.green = ScaleCharToQuantum(bg.green()); img->background_color.blue = ScaleCharToQuantum(bg.blue()); Image *tmp = SwirlImage(img, weight, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Shade){ Image *tmp = ShadeImage(img, useColor, a, e, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == Wave){ img->background_color.red = ScaleCharToQuantum(bg.red()); img->background_color.green = ScaleCharToQuantum(bg.green()); img->background_color.blue = ScaleCharToQuantum(bg.blue()); Image *tmp = WaveImage(img, a, f, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } else if(type == AddNoise){ Image *tmp = AddNoiseImage(img, noiseType, &exception); if(tmp){ if(img->next) DestroyImageList(img); else DestroyImage(img); img = tmp; } else save = false; } MagickMonitor(i18n("Finished").latin1(), 100, 100, &exception); bool retValue = true; if(save){ bool result; if(preview){ acceptPreview = false; rejectPreview = false; QImage qImg(img->columns, img->rows, 32); DispatchImage(img, 0, 0, img->columns, img->rows, "BGRA", CharPixel, qImg.bits(), &exception); preview->setPreviewImage(qImg); while(!cancel && !acceptPreview && !rejectPreview) qApp->processEvents(); if(acceptPreview){ result = WriteImage(info, img); if(!result){ retValue = KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) != KMessageBox::Cancel; } } } else{ result = WriteImage(info, img); if(!result){ retValue = KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel; } } } if(img->next) DestroyImageList(img); else DestroyImage(img); DestroyImageInfo(info); return(retValue); } bool BatchEffect::applyQtEffect(const QString &filename, KIFBatchPreviewWidget *preview) { QImage img; bool save = true; char format[32]; if(preview) preview->disable(); if(type == FlipH || type == FlipV || type == Rot90 || type == Rot180 || type == Rot270){ const char *ext = extension(QFile::encodeName(filename)); if(ext){ if(qstricmp(ext, "jpg") == 0 || qstricmp(ext, "jpeg") == 0){ // do lossless JPEG rotation QBuffer buffer; JPEGTransform t; switch(type){ case FlipH: t = JPEGFlipH; break; case FlipV: t = JPEGFlipV; break; case Rot90: t = JPEGRot90; break; case Rot180: t = JPEGRot180; break; case Rot270: t = JPEGRot270; break; default: t = JPEGFlipH; break; } if(type == FlipH || type == FlipV) emit setProgressText(i18n("Lossless JPEG Flipping...")); else emit setProgressText(i18n("Loseless JPEG Rotating...")); emit setProgress(0); qApp->processEvents(); if(transformJPEG(QFile::encodeName(filename), &buffer, t)){ qWarning("JPEG transform success!"); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); buffer.close(); if(buffer.size() != 0 && img.loadFromData(buffer.buffer(), "JPEG")){ if(preview){ acceptPreview = false; rejectPreview = false; preview->setPreviewImage(img); while(!cancel && !acceptPreview && !rejectPreview) qApp->processEvents(); if(acceptPreview){ QFile file(QFile::encodeName(filename)); if(file.open(IO_WriteOnly | IO_Truncate)){ file.writeBlock(buffer.buffer()); file.close(); return(true); } else{ qWarning("Unable to save image"); if(KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel) return(false); return(true); } } else return(true); } else{ QFile file(QFile::encodeName(filename)); if(file.open(IO_WriteOnly | IO_Truncate)){ file.writeBlock(buffer.buffer()); file.close(); return(true); } else{ qWarning("Unable to save image"); if(KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel) return(false); return(true); } return(true); } } } qWarning("Lossless JPEG transform failed, trying normal effect."); } } } // Normal effect if(!loadImage(img, filename, NULL, format)){ return(KMessageBox::warningContinueCancel(NULL, i18n("Cannot open ") + filename + i18n("!"), i18n("File Open Error"), i18n("Continue"), QString::null, true) != KMessageBox::Cancel); } if(type == AddText){ emit setProgressText(i18n("Applying text...")); // progress bar is kindof dumb here since it just goes from 0->100, // but we use it to be consistent w/ the ImageMagick effects that // display much more ;-) emit setProgress(0); qApp->processEvents(); if(img.depth() < 32) img = img.convertDepth(32); save = applyTextLabel(textPos, *textImage, img); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Scale){ if(img.width() > newW || img.height() > newH){ emit setProgressText(i18n("Smoothscaling...")); emit setProgress(0); qApp->processEvents(); if(img.width() > img.height()){ float percent = (((float)newW)/img.width()); int h = (int)(img.height()*percent); img = img.smoothScale(newW, h); } else{ float percent = (((float)newH)/img.height()); int w = (int)(img.width()*percent); img = img.smoothScale(w, newH); } emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else{ emit setProgressText(i18n("No resize needed")); qApp->processEvents(); save = false; } } else if(type == Border){ emit setProgressText(i18n("Applying border...")); emit setProgress(0); qApp->processEvents(); QImage tmpImg; if(img.depth() < 32) img = img.convertDepth(32); if(borderType == Solid){ KIFBorderEffect::solid(img, tmpImg, fg, borderWidth); } else if(borderType == Bevel){ KIFBorderEffect::bevel(img, tmpImg, fg, bg, borderWidth); } else if(borderType == Liquid){ KIFBorderEffect::liquid(img, tmpImg, fg, bg, borderWidth); } else if(borderType == RoundCorner){ KIFBorderEffect::roundCorner(img, tmpImg, bg); } img = tmpImg; emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Grayscale){ emit setProgressText(i18n("Grayscaling...")); emit setProgress(0); qApp->processEvents(); KImageEffect::toGray(img); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Invert){ emit setProgressText(i18n("Inverting...")); emit setProgress(0); qApp->processEvents(); img.invertPixels(false); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == FlipH){ emit setProgressText(i18n("Flipping...")); emit setProgress(0); qApp->processEvents(); img = img.mirror(true, false); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == FlipV){ emit setProgressText(i18n("Flipping...")); emit setProgress(0); qApp->processEvents(); img = img.mirror(false, true); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Rot90){ emit setProgressText(i18n("Rotating...")); emit setProgress(0); qApp->processEvents(); img = KImageEffect::rotate(img, KImageEffect::Rotate90); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Rot180){ emit setProgressText(i18n("Rotating...")); emit setProgress(0); qApp->processEvents(); img = KImageEffect::rotate(img, KImageEffect::Rotate180); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } else if(type == Rot270){ emit setProgressText(i18n("Rotating...")); emit setProgress(0); qApp->processEvents(); img = KImageEffect::rotate(img, KImageEffect::Rotate270); emit setProgress(100); emit setProgressText(i18n("Finished")); qApp->processEvents(); } if(save){ if(preview){ acceptPreview = false; rejectPreview = false; preview->setPreviewImage(img); while(!cancel && !acceptPreview && !rejectPreview) qApp->processEvents(); if(acceptPreview){ if(!saveImage(img, filename, format)){ qWarning("Unable to save image"); if(KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel) return(false); return(true); } } } else{ if(!saveImage(img, filename, format)){ qWarning("Unable to save image"); if(KMessageBox::warningContinueCancel(view, i18n("Cannot save ") + filename, i18n("Effect save error!"), i18n("Continue"), QString::null, true) == KMessageBox::Cancel) return(false); return(true); } } } return(true); } bool BatchEffect::getParameters() { // QImage effects if(type == AddText){ KIFTextDialog dlg(view); if(dlg.exec() == QDialog::Accepted){ textImage = new QImage(); createTextLabel(dlg.text(), dlg.color(), dlg.font(), *textImage); textPos = dlg.pos(); return(true); } return(false); } else if(type == Scale){ KIFSizeDialog dlg(600, 500, view); if(dlg.exec() == QDialog::Accepted){ newW = dlg.resultWidth(); newH = dlg.resultHeight(); return(true); } return(false); } else if(type == Border){ KIFBorderDialog dlg(view); if(dlg.exec() == QDialog::Accepted){ borderType = dlg.borderType(); borderWidth = dlg.borderWidth(); fg = dlg.fgColor(); bg = dlg.bgColor(); return(true); } return(false); } // Magick effects else if(type == AddNoise){ QStringList typeList; typeList.append(i18n("Uniform")); typeList.append(i18n("Gaussian")); typeList.append(i18n("Multiplicative Gaussian")); typeList.append(i18n("Impulse")); typeList.append(i18n("Laplacian")); typeList.append(i18n("Poisson")); bool ok; QString type = QInputDialog::getItem(i18n("Noise Type"), i18n("Please select a noise type."), typeList, 0, false, &ok, view); if(!ok) return(false); if(type == i18n("Uniform")) noiseType = UniformNoise; else if(type == i18n("Gaussian")) noiseType = GaussianNoise; else if(type == i18n("Multiplicative Gaussian")) noiseType = MultiplicativeGaussianNoise; else if(type == i18n("Impulse")) noiseType = ImpulseNoise; else if(type == i18n("Laplacian")) noiseType = LaplacianNoise; else if(type == i18n("Poisson")) noiseType = PoissonNoise; return(true); } else if(type == Wave){ KIFSineWaveDialog dlg(view); if(dlg.exec() == QDialog::Accepted){ a = dlg.amplitude(); f = dlg.frequency(); KColorDialog dlg(NULL, NULL, true); dlg.setCaption(i18n("Select a Background Color")); dlg.setColor(Qt::white); if(dlg.exec() != QDialog::Accepted) return(false); else{ bg = dlg.color(); return(true); } } return(false); } else if(type == Shade){ KIFShadeDialog dlg(view); if(dlg.exec() == QDialog::Accepted){ a = dlg.azimuth(); e = dlg.elevation(); useColor = dlg.colorShading(); return(true); } return(false); } else if(type == Emboss){ return(getRadiusAndDeviation(i18n("Please enter the emboss radius and standard deviation:"), radius, sigma, view)); } else if(type == Charcoal){ return(getRadiusAndDeviation(i18n("Please enter the charcoal radius and standard deviation:"), radius, sigma, view)); } else if(type == Sharpen){ return(getRadiusAndDeviation(i18n("Please enter the sharpen radius and standard deviation:"), radius, sigma, view)); } else if(type == Blur){ return(getRadiusAndDeviation(i18n("Please enter the blur radius and standard deviation:"), radius, sigma, view)); } else if(type == Edge){ bool ok; weight = QInputDialog::getDouble(i18n("Edge Detect Radius"), i18n("Please enter the edge detect radius (0=use default)"), 0, 0, 10, 1, &ok, view); return(ok); } else if(type == ReduceNoise){ bool ok; weight = QInputDialog::getDouble(i18n("Reduce Noise Radius"), i18n("Please enter the noise radius (0=use default)"), 0, 0, 10, 1, &ok, view); return(ok); } else if(type == OilPaint){ bool ok; weight = QInputDialog::getDouble(i18n("Oil Paint Radius"), i18n("Please enter the oil paint radius (0=use default)"), 0, 0, 10, 1, &ok, view); return(ok); } else if(type == Solarize){ bool ok; weight = QInputDialog::getInteger(i18n("Solarization Factor"), i18n("Please enter the solarization factor (0-65565)"), 100, 0, MaxRGB, 1, &ok, view); return(ok); } else if(type == Swirl){ bool ok; weight = QInputDialog::getDouble(i18n("Swirl Angle"), i18n("Please enter angle to swirl"), 60, 1, 360, 1, &ok, view); if(ok){ KColorDialog dlg(NULL, NULL, true); dlg.setCaption(i18n("Select a Background Color")); dlg.setColor(Qt::white); if(dlg.exec() != QDialog::Accepted) return(false); else{ bg = dlg.color(); return(true); } } return(false); } else if(type == Implode){ bool ok; weight = QInputDialog::getDouble(i18n("Implode Factor"), i18n("Please enter factor to implode (-1.0 - 1.0)"), 0.3, -1.0, 1.0, 1, &ok, view); if(ok){ KColorDialog dlg(NULL, NULL, true); dlg.setCaption(i18n("Select a Background Color")); dlg.setColor(Qt::white); if(dlg.exec() != QDialog::Accepted) return(false); else{ bg = dlg.color(); return(true); } } return(false); } else if(type == Threshold){ bool ok; weight = QInputDialog::getInteger(i18n("Threshold"), i18n("Please enter the threshold value"), 128, 0, 255, 1, &ok, view); return(ok); } else if(type == Spread){ bool ok; weight = QInputDialog::getInteger(i18n("Displacement Amount"), i18n("Please enter the displacement amount"), 2, 1, 30, 1, &ok, view); return(ok); } return(true); }