void LensAutoFixTool::preparePreview() { // Settings information must be get before to disable settings view. LensFunContainer settings = d->cameraSelector->settings(); d->settingsView->assignFilterSettings(settings); ImageIface* const iface = d->previewWidget->imageIface(); DImg preview = iface->preview(); if (d->showGrid->isChecked()) { QBitmap pattern(9, 9); pattern.clear(); QPainter p1(&pattern); p1.setPen(QPen(Qt::black, 1)); p1.drawLine(5, 0, 5, 9); p1.drawLine(0, 5, 9, 5); p1.end(); QPixmap pix(preview.size()); pix.fill(Qt::transparent); QPainter p2(&pix); p2.setPen(QPen(Qt::gray, 1)); p2.fillRect(0, 0, pix.width(), pix.height(), QBrush(pattern)); p2.end(); DImg grid(pix.toImage()); DColorComposer* const composer = DColorComposer::getComposer(DColorComposer::PorterDuffNone); DColorComposer::MultiplicationFlags flags = DColorComposer::NoMultiplication; // Do alpha blending of template on dest image preview.bitBlendImage(composer, &grid, 0, 0, preview.width(), preview.height(), 0, 0, flags); } setFilter(new LensFunFilter(&preview, this, settings)); }
DImg SharedLoadSaveThread::cacheLookup(const QString& filePath, AccessMode /*accessMode*/) { LoadingCache* cache = LoadingCache::cache(); LoadingCache::CacheLock lock(cache); DImg* cachedImg = cache->retrieveImage(filePath); // Qt4: uncomment this code. // See comments in SharedLoadingTask::execute for explanation. /* if (cachedImg) { if (accessMode == AccessModeReadWrite) return cachedImg->copy(); else return *cachedImg; } else return DImg(); */ if (cachedImg) { return cachedImg->copy(); } else { return DImg(); } }
void ImageQualityTask::run() { if (!d->cancel) { // Get item preview to perform quality analysis. No need to load whole image, this will be slower. // TODO : check if 1024 pixels size is enough to get suitable Quality results. DImg dimg = PreviewLoadThread::loadFastSynchronously(d->path, 1024); if (!dimg.isNull() && !d->cancel) { // TODO : run here Quality analysis backend and store Pick Label result to DB. // Backend Input : d->quality as Quality analysis settings, // dimg as reduced size image data to parse, // d->path as file path to patch DB properties. // Result : Backend must scan Quality of image depending of settings and compute a Quality estimation accordingly. // Finaly, using file path, DB Pick Label properties must be assigned through ImageInfo interface. // Warning : All code here will run in a separated thread and must be re-entrant/thread-safe. Only pure computation // must be processed. GUI calls are prohibited. ImageInfo and DImg can be used safety in thread. PickLabel pick; d->imgqsort = new ImgQSort(dimg, d->quality, &pick); d->imgqsort->startAnalyse(); ImageInfo info = ImageInfo::fromLocalFile(d->path); info.setPickLabel(pick); delete d->imgqsort; //delete image data after setting label d->imgqsort = 0; } // Dispatch progress to Progress Manager QImage qimg = dimg.smoothScale(22, 22, Qt::KeepAspectRatio).copyQImage(); emit signalFinished(qimg); emit signalDone(); } }
void ShearTool::setPreviewImage() { ImageIface* const iface = d->previewWidget->imageIface(); int w = iface->previewSize().width(); int h = iface->previewSize().height(); DImg imTemp = filter()->getTargetImage().smoothScale(w, h, Qt::KeepAspectRatio); DImg imDest( w, h, filter()->getTargetImage().sixteenBit(), filter()->getTargetImage().hasAlpha() ); imDest.fill( DColor(d->previewWidget->palette().color(QPalette::Background).rgb(), filter()->getTargetImage().sixteenBit()) ); imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2); iface->setPreview(imDest.smoothScale(iface->previewSize())); d->previewWidget->updatePreview(); ShearFilter* const tool = dynamic_cast<ShearFilter*>(filter()); if (tool) { QSize newSize = tool->getNewSize(); QString temp; d->newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") ); d->newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") ); } }
void ContentAwareResizeTool::prepareEffect() { if (d->prevW != d->wInput->value() || d->prevH != d->hInput->value() || d->prevWP != d->wpInput->value() || d->prevHP != d->hpInput->value()) { slotValuesChanged(); } disableSettings(); ImageIface* iface = d->previewWidget->imageIface(); int w = iface->previewWidth(); int h = iface->previewHeight(); DImg imTemp = iface->getOriginalImg()->smoothScale(w, h, Qt::KeepAspectRatio); int new_w = (int)(w*d->wpInput->value()/100.0); int new_h = (int)(h*d->hpInput->value()/100.0); if (d->mixedRescaleInput->value()<100.0) // mixed rescale { double stdRescaleP = (100.0 - d->mixedRescaleInput->value()) / 100.0; int diff_w = (int)(stdRescaleP * (w - new_w)); int diff_h = (int)(stdRescaleP * (h - new_h)); imTemp.resize(imTemp.width() - diff_w, imTemp.height() - diff_h); } QImage mask; if (d->weightMaskBox->isChecked()) { mask = d->previewWidget->getMask(); } contentAwareResizeCore(&imTemp, new_w, new_h, mask); }
int LoadSaveThread::exifOrientation(const DImg& image, const QString& filePath) { QVariant attribute = image.attribute("fromRawEmbeddedPreview"); return exifOrientation(filePath, DMetadata(image.getMetadata()), image.detectedFormat() == DImg::RAW, (attribute.isValid() && attribute.toBool())); }
bool MetadataHub::write(DImg& image, WriteComponent writeMode, bool ignoreLazySync, const MetadataSettingsContainer& settings) { applyChangeNotifications(); // if no DMetadata object is needed at all, don't construct one if (!willWriteMetadata(writeMode, settings)) { return false; } // See DImgLoader::readMetadata() and saveMetadata() DMetadata metadata; metadata.setData(image.getMetadata()); QString filePath = image.originalFilePath(); if (filePath.isEmpty()) { filePath = image.lastSavedFilePath(); } if (!ignoreLazySync && settings.useLazySync && !filePath.isEmpty()) { ImageInfo info = ImageInfo::fromLocalFile(filePath); MetadataHubMngr::instance()->addPending(info); return true; } if (!filePath.isEmpty()) { writeToBaloo(filePath); } return write(metadata, writeMode, settings); }
void UndoManager::getSnapshot(int index, DImg* const img) const { DImg data = d->undoCache->getData(index); // Pass ownership of buffer. If data is null, img will be null img->putImageData(data.width(), data.height(), data.sixteenBit(), data.hasAlpha(), data.bits(), true); }
void RainDropTool::putPreviewData() { ImageIface* iface = d->previewWidget->imageIface(); DImg imDest = filter()->getTargetImage().smoothScale(iface->previewWidth(), iface->previewHeight()); iface->putPreviewImage(imDest.bits()); d->previewWidget->updatePreview(); }
void UndoManager::restoreSnapshot(int index, const UndoMetadataContainer& c) { DImg img = d->undoCache->getData(index); if (!img.isNull()) { d->core->setUndoImg(c, img); } }
void InsertTextWidget::makePixmap() { int orgW = d->iface->originalSize().width(); int orgH = d->iface->originalSize().height(); float ratioW = (float)d->w / (float)orgW; float ratioH = (float)d->h / (float)orgH; int x, y; if (d->textRect.isValid()) { // convert from widget to image coordinates x = d->textRect.x() - d->rect.x(); y = d->textRect.y() - d->rect.y(); } else { x = -1; y = -1; } // get preview image data DImg image = d->iface->preview(); image.setIccProfile( d->iface->original()->getIccProfile() ); // paint pixmap for drawing this widget // First, fill with background color d->pixmap->fill(d->bgColor); QPainter p(d->pixmap); // Convert image to pixmap and draw it QPixmap imagePixmap = d->iface->convertToPixmap(image); p.drawPixmap(d->rect.x(), d->rect.y(), imagePixmap, 0, 0, imagePixmap.width(), imagePixmap.height()); // prepare painter for use by compose image p.setClipRect(d->rect); p.translate(d->rect.x(), d->rect.y()); int borderWidth = qMax(1, qRound(ratioW)); // compose image and draw result directly on pixmap, with correct offset QRect textRect = composeImage(&image, &p, x, y, d->textFont, d->textFont.pointSizeF(), d->textRotation, d->textColor, d->textOpacity, d->alignMode, d->textString, d->textTransparent, d->backgroundColor, d->textBorder ? BORDER_NORMAL : BORDER_SUPPORT, borderWidth, borderWidth, (ratioW > ratioH) ? ratioW : ratioH); p.end(); // store new text rectangle // convert from image to widget coordinates d->textRect.setX(textRect.x() + d->rect.x()); d->textRect.setY(textRect.y() + d->rect.y()); d->textRect.setSize(textRect.size()); }
void WhiteBalanceTool::setPreviewImage() { DImg preview = filter()->getTargetImage(); d->previewWidget->setPreviewImage(preview); // Update histogram. d->gboxSettings->histogramBox()->histogram()->updateData(preview.copy(), DImg(), false); }
void ResizeTool::putFinalData() { ImageIface iface(0, 0); DImg targetImage = filter()->getTargetImage(); iface.putOriginalImage(i18n("Resize"), filter()->filterAction(), targetImage.bits(), targetImage.width(), targetImage.height()); }
void BCGFilter::applyBCG(DImg& image) { if (image.isNull()) { return; } applyBCG(image.bits(), image.width(), image.height(), image.sixteenBit()); }
void IccTransform::transform(DImg& image, const TransformDescription& description, DImgLoaderObserver* const observer) { const int bytesDepth = image.bytesDepth(); const int pixels = image.width() * image.height(); // convert ten scanlines in a batch const int pixelsPerStep = image.width() * 10; uchar* data = image.bits(); // see dimgloader.cpp, granularity(). int granularity = 1; if (observer) { granularity = (int)((pixels / (20 * 0.9)) / observer->granularity()); } int checkPoint = pixels; // it is safe to use the same input and output buffer if the format is the same if (description.inputFormat == description.outputFormat) { for (int p = pixels; p > 0; p -= pixelsPerStep) { int pixelsThisStep = qMin(p, pixelsPerStep); int size = pixelsThisStep * bytesDepth; LcmsLock lock; dkCmsDoTransform(d->handle, data, data, pixelsThisStep); data += size; if (observer && p <= checkPoint) { checkPoint -= granularity; observer->progressInfo(&image, 0.1 + 0.9 * (1.0 - float(p) / float(pixels))); } } } else { QVarLengthArray<uchar> buffer(pixelsPerStep * bytesDepth); for (int p = pixels; p > 0; p -= pixelsPerStep) { int pixelsThisStep = qMin(p, pixelsPerStep); int size = pixelsThisStep * bytesDepth; LcmsLock lock; memcpy(buffer.data(), data, size); dkCmsDoTransform(d->handle, buffer.data(), data, pixelsThisStep); data += size; if (observer && p <= checkPoint) { checkPoint -= granularity; observer->progressInfo(&image, 0.1 + 0.9 * (1.0 - float(p) / float(pixels))); } } } }
bool IccTransform::apply(DImg& image, DImgLoaderObserver* const observer) { if (!willHaveEffect()) { if (!d->outputProfile.isNull() && !d->doNotEmbed) { image.setIccProfile(d->outputProfile); } return true; } if (!checkProfiles()) { return false; } TransformDescription description; if (d->proofProfile.isNull()) { description = getDescription(image); if (!open(description)) { return false; } } else { description = getProofingDescription(image); if (!openProofing(description)) { return false; } } if (observer) { observer->progressInfo(&image, 0.1F); } transform(image, description, observer); if (!d->doNotEmbed) { image.setIccProfile(d->outputProfile); } // if this was a RAW color image, it is no more image.removeAttribute(QLatin1String("uncalibratedColor")); return true; }
void BWSepiaFilter::applyToneFilter(DImg& img, TonalityContainer& settings) { // Value to multiply RGB 8 bits component of mask used by TonalityFilter. int mul = img.sixteenBit() ? 255 : 1; settings.redMask = settings.redMask * mul; settings.greenMask = settings.greenMask * mul; settings.blueMask = settings.blueMask * mul; TonalityFilter tone(&img, 0L, settings); tone.startFilterDirectly(); img.putImageData(tone.getTargetImage().bits()); }
void RawImport::setPreviewImage() { // Preserve metadata from loaded image, and take post-processed image data d->postProcessedImage = d->previewWidget->demosaicedImage().copyMetaData(); DImg data = filter()->getTargetImage(); d->postProcessedImage.putImageData(data.width(), data.height(), data.sixteenBit(), data.hasAlpha(), data.stripImageData(), false); d->previewWidget->setPostProcessedImage(d->postProcessedImage); d->settingsBox->setPostProcessedImage(d->postProcessedImage); EditorToolIface::editorToolIface()->setToolStopProgress(); setBusy(false); }
void DImageFilterActionTest::testActions() { QStringList files = QDir(imagePath()).entryList(QDir::Files); files.removeOne(originalImage()); DImg original(imagePath() + originalImage()); QVERIFY(!original.isNull()); foreach (const QString& fileName, files) { DImg ref(imagePath() + fileName); QVERIFY(!ref.isNull()); DImageHistory history = ref.getImageHistory(); FilterActionFilter filter; filter.setFilterActions(history.allActions()); QVERIFY(filter.isReproducible() || filter.isComplexAction()); filter.setupFilter(original.copy()); filter.startFilterDirectly(); qDebug() << filter.filterActions().size(); DImg img = filter.getTargetImage(); QVERIFY(ref.size() == img.size()); bool isEqual = true; DImg diff(ref.width(), ref.height(), ref.sixteenBit()); diff.fill(DColor(Qt::black)); for (uint x=0; x<ref.width(); x++) { for (uint y=0; y<ref.height(); y++) { DColor cref = ref.getPixelColor(x,y); DColor cres = img.getPixelColor(x,y); if (cref.red() != cres.red() || cref.green() != cres.green() || cref.blue() != cres.blue()) { //qDebug() << x << y; diff.setPixelColor(x,y, DColor(Qt::white)); isEqual = false; } } } if (!isEqual) { showDiff(original, ref, img, diff); } QVERIFY(isEqual); }
bool LoadSaveThread::exifRotate(DImg& image, const QString& filePath) { // Keep in sync with the variant in thumbnailcreator.cpp if (wasExifRotated(image)) { return false; } // Rotate thumbnail based on metadata orientation information bool rotatedOrFlipped = image.rotateAndFlip(exifOrientation(image, filePath)); image.setAttribute("exifRotated", true); return rotatedOrFlipped; }
void ResizeTool::putPreviewData() { ImageIface* iface = d->previewWidget->imageIface(); int w = iface->previewWidth(); int h = iface->previewHeight(); DImg imTemp = filter()->getTargetImage().smoothScale(w, h, Qt::KeepAspectRatio); DImg imDest(w, h, filter()->getTargetImage().sixteenBit(), filter()->getTargetImage().hasAlpha()); QColor background = toolView()->backgroundRole(); imDest.fill(DColor(background, filter()->getTargetImage().sixteenBit())); imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2); iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(), iface->previewHeight())).bits()); d->previewWidget->updatePreview(); }
QImage DImg::copyQImage(int x, int y, int w, int h) const { if (isNull()) { return QImage(); } DImg img = copy(x, y, w, h); if (img.sixteenBit()) { img.convertDepth(32); } return img.copyQImage(); }
DImg BWSepiaFilter::getThumbnailForEffect(DImg& img) { postProgress(10); DImg thumb = img.copy(); postProgress(25); if (d->settings.previewType < BWSepiaContainer::BWGeneric) { // In Filter view, we will render a preview of the B&W filter with the generic B&W film. blackAndWhiteConversion(thumb, d->settings.previewType); postProgress(50); blackAndWhiteConversion(thumb, BWSepiaContainer::BWGeneric); postProgress(75); } else { // In Film and Tone view, we will render the preview without to use the B&W Filter. postProgress(50); blackAndWhiteConversion(thumb, d->settings.previewType); postProgress(75); } postProgress(90); return (thumb); }
bool LoadSaveThread::wasExifRotated(DImg& image) { // Keep in sync with the variant in thumbnailcreator.cpp QVariant attribute(image.attribute("exifRotated")); return attribute.isValid() && attribute.toBool(); }
void DImgPreviewItem::slotGotImagePreview(const LoadingDescription& description, const DImg& image) { Q_D(DImgPreviewItem); if (description.filePath != d->path || description.isThumbnail()) { return; } setImage(image); if (image.isNull()) { d->state = ImageLoadingFailed; emit stateChanged(d->state); emit loadingFailed(); } else { d->state = ImageLoaded; emit stateChanged(d->state); emit loaded(); } preloadNext(); }
uchar* ImageIface::Private::previewImageData() { if (previewImage.isNull()) { DImg* im = 0; if (previewType == FullImage) { im = core->getImg(); if (!im || im->isNull()) { return 0; } } else // ImageSelection { im = new DImg(core->getImgSelection()); if (!im) { return 0; } if (im->isNull()) { delete im; return 0; } im->setIccProfile(core->getEmbeddedICC()); } QSize sz(im->width(), im->height()); sz.scale(constrainWidth, constrainHeight, Qt::KeepAspectRatio); previewImage = im->smoothScale(sz.width(), sz.height()); previewWidth = previewImage.width(); previewHeight = previewImage.height(); // only create another copy if needed, in setPreviewImage targetPreviewImage = previewImage; if (previewType == ImageSelection) { delete im; } } DImg previewData = previewImage.copyImageData(); return previewData.stripImageData(); }
void ImageIface::setSelection(const QString& caller, const FilterAction& action, const DImg& img) { if (img.hasAlpha() != originalHasAlpha() || img.sixteenBit() != originalSixteenBit() || img.size() != selectionRect().size() ) { kDebug() << "Properties of image to overwrite selection differs than original image"; return; } if (img.isNull()) { kDebug() << "No image data to handle"; return; } d->core->putImgSelection(caller, action, img); }
void ImageIface::setOriginal(const QString& caller, const FilterAction& action, const DImg& img) { if (img.isNull()) { kDebug() << "No image data to handle"; return; } d->core->putImg(caller, action, img); }
void Canvas::slotCopy() { QRect sel = d->core->getSelectedArea(); if (sel.size().isNull()) // No current selection. { return; } QApplication::setOverrideCursor(Qt::WaitCursor); DImg selDImg = d->core->getImgSelection(); QImage selImg = selDImg.copyQImage(); QMimeData* const mimeData = new QMimeData(); mimeData->setImageData(selImg); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); QApplication::restoreOverrideCursor(); }
void DImgBuiltinFilter::apply(DImg& image) const { switch (m_type) { case NoOperation: break; case Rotate90: image.rotate(DImg::ROT90); break; case Rotate180: image.rotate(DImg::ROT180); break; case Rotate270: image.rotate(DImg::ROT270); break; case FlipHorizontally: image.flip(DImg::HORIZONTAL); break; case FlipVertically: image.flip(DImg::VERTICAL); break; case Crop: image.crop(m_arg.toRect()); break; case Resize: { QSize s = m_arg.toSize(); image.resize(s.width(), s.height()); break; } case ConvertTo8Bit: image.convertToEightBit(); break; case ConvertTo16Bit: image.convertToSixteenBit(); break; } }