/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include "previewhandler.h" #include #include "../rtengine/rtengine.h" using namespace rtengine; using namespace rtengine::procparams; PreviewHandler::PreviewHandler () : image(nullptr), previewScale(1.) { pih = new PreviewHandlerIdleHelper; pih->phandler = this; pih->destroyed = false; pih->pending = 0; } PreviewHandler::~PreviewHandler () { idle_register.destroy(); if (pih->pending) { pih->destroyed = true; } else { delete pih; } } //----------------previewimagelistener functions-------------------- void PreviewHandler::setImage(rtengine::IImage8* i, double scale, const rtengine::procparams::CropParams& cp) { pih->pending++; idle_register.add( [this, i, scale, cp]() -> bool { if (pih->destroyed) { if (pih->pending == 1) { delete pih; } else { --pih->pending; } return false; } if (pih->phandler->image) { IImage8* const oldImg = pih->phandler->image; oldImg->getMutex().lock(); pih->phandler->image = i; oldImg->getMutex().unlock(); } else { pih->phandler->image = i; } pih->phandler->cropParams = cp; pih->phandler->previewScale = scale; --pih->pending; return false; } ); } void PreviewHandler::delImage(IImage8* i) { pih->pending++; idle_register.add( [this, i]() -> bool { if (pih->destroyed) { if (pih->pending == 1) { delete pih; } else { --pih->pending; } return false; } if (pih->phandler->image) { IImage8* oldImg = pih->phandler->image; oldImg->getMutex().lock(); pih->phandler->image = nullptr; oldImg->getMutex().unlock(); } i->free(); pih->phandler->previewImgMutex.lock(); pih->phandler->previewImg.clear(); pih->phandler->previewImgMutex.unlock(); --pih->pending; return false; } ); } void PreviewHandler::imageReady(const rtengine::procparams::CropParams& cp) { pih->pending++; idle_register.add( [this, cp]() -> bool { if (pih->destroyed) { if (pih->pending == 1) { delete pih; } else { --pih->pending; } return false; } pih->phandler->previewImgMutex.lock(); pih->phandler->previewImg = Gdk::Pixbuf::create_from_data(pih->phandler->image->getData(), Gdk::COLORSPACE_RGB, false, 8, pih->phandler->image->getWidth(), pih->phandler->image->getHeight(), 3 * pih->phandler->image->getWidth()); pih->phandler->previewImgMutex.unlock (); pih->phandler->cropParams = cp; pih->phandler->previewImageChanged (); --pih->pending; return false; } ); } Glib::RefPtr PreviewHandler::getRoughImage (int x, int y, int w, int h, double zoom) { MyMutex::MyLock lock(previewImgMutex); Glib::RefPtr resPixbuf; if (previewImg) { double totalZoom = zoom * previewScale; if (w > previewImg->get_width()*totalZoom) { w = image->getWidth() * totalZoom; } if (h > previewImg->get_height()*totalZoom) { h = image->getHeight() * totalZoom; } x *= zoom; y *= zoom; w = rtengine::LIM(w, 0, int(previewImg->get_width() * totalZoom) - x); h = rtengine::LIM(h, 0, int(previewImg->get_height() * totalZoom) - y); resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, w, h); previewImg->scale (resPixbuf, 0, 0, w, h, -x, -y, totalZoom, totalZoom, Gdk::INTERP_NEAREST); } return resPixbuf; } Glib::RefPtr PreviewHandler::getRoughImage (int desiredW, int desiredH, double& zoom_) { MyMutex::MyLock lock(previewImgMutex); Glib::RefPtr resPixbuf; if (previewImg) { double zoom1 = (double)max(desiredW, 20) / previewImg->get_width(); // too small values lead to extremely increased processing time in scale function, Issue 2783 double zoom2 = (double)max(desiredH, 20) / previewImg->get_height(); // "" double zoom = zoom1 < zoom2 ? zoom1 : zoom2; resPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, image->getWidth() * zoom, image->getHeight() * zoom); previewImg->scale (resPixbuf, 0, 0, previewImg->get_width()*zoom, previewImg->get_height()*zoom, 0, 0, zoom, zoom, Gdk::INTERP_BILINEAR); zoom_ = zoom / previewScale; } return resPixbuf; } void PreviewHandler::previewImageChanged () { for (std::list::iterator i = listeners.begin(); i != listeners.end(); ++i) { (*i)->previewImageChanged (); } }