File indexing completed on 2025-01-05 03:53:13
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2002-30-09 0007 * Description : a tool to print images 0008 * 0009 * SPDX-FileCopyrightText: 2002-2003 by Todd Shoemaker <todd at theshoemakers dot net> 0010 * SPDX-FileCopyrightText: 2007-2012 by Angelo Naselli <anaselli at linux dot it> 0011 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "advprintcropframe.h" 0018 0019 // C++ includes 0020 0021 #include <cmath> 0022 #include <cstdio> 0023 0024 // Qt includes 0025 0026 #include <QPixmap> 0027 #include <QImage> 0028 #include <QPainter> 0029 #include <QMouseEvent> 0030 #include <QtGlobal> 0031 0032 // Local includes 0033 0034 #include "digikam_debug.h" 0035 #include "advprintphoto.h" 0036 #include "advprintwizard.h" 0037 0038 namespace DigikamGenericPrintCreatorPlugin 0039 { 0040 0041 class Q_DECL_HIDDEN AdvPrintCropFrame::Private 0042 { 0043 public: 0044 0045 explicit Private() 0046 : photo (nullptr), 0047 mouseDown(false), 0048 image (nullptr), 0049 imageX (0), 0050 imageY (0), 0051 color (Qt::red), 0052 drawRec (true) 0053 { 0054 } 0055 0056 AdvPrintPhoto* photo; 0057 bool mouseDown; 0058 QImage image; 0059 int imageX; 0060 int imageY; 0061 0062 QColor color; 0063 0064 QRect cropRegion; 0065 bool drawRec; 0066 0067 QTransform matrix; 0068 }; 0069 0070 AdvPrintCropFrame::AdvPrintCropFrame(QWidget* const parent) 0071 : QWidget(parent), 0072 d (new Private) 0073 { 0074 } 0075 0076 AdvPrintCropFrame::~AdvPrintCropFrame() 0077 { 0078 delete d; 0079 } 0080 0081 void AdvPrintCropFrame::init(AdvPrintPhoto* const photo, 0082 int woutlay, 0083 int houtlay, 0084 bool autoRotate, 0085 bool paint) 0086 { 0087 d->photo = photo; 0088 d->matrix = d->photo->updateCropRegion(woutlay, houtlay, autoRotate); 0089 0090 if (paint) 0091 { 0092 updateImage(); 0093 update(); 0094 } 0095 } 0096 0097 QRect AdvPrintCropFrame::screenToPhotoRect(const QRect& r) const 0098 { 0099 // 'r' is given in screen coordinates, and we want to convert that to photo coordinates. 0100 0101 double xRatio = 0.0; 0102 double yRatio = 0.0; 0103 0104 // Flip the photo dimensions if rotated 0105 0106 int photoW; 0107 int photoH; 0108 0109 if ((d->photo->m_rotation == 0) || (d->photo->m_rotation == 180)) 0110 { 0111 photoW = d->photo->width(); 0112 photoH = d->photo->height(); 0113 } 0114 else 0115 { 0116 photoW = d->photo->height(); 0117 photoH = d->photo->width(); 0118 } 0119 0120 if (d->image.width() > 0) 0121 { 0122 xRatio = (double) photoW / (double) d->image.width(); 0123 } 0124 0125 if (d->image.height() > 0) 0126 { 0127 yRatio = (double) photoH / (double) d->image.height(); 0128 } 0129 0130 int x1 = AdvPrintWizard::normalizedInt((r.left() - d->imageX) * xRatio); 0131 int y1 = AdvPrintWizard::normalizedInt((r.top() - d->imageY) * yRatio); 0132 0133 int w = AdvPrintWizard::normalizedInt(r.width() * xRatio); 0134 int h = AdvPrintWizard::normalizedInt(r.height() * yRatio); 0135 0136 QRect result; 0137 result.setRect(x1, y1, w, h); 0138 0139 return result; 0140 } 0141 0142 QRect AdvPrintCropFrame::photoToScreenRect(const QRect& r) const 0143 { 0144 // 'r' is given in photo coordinates, and we want to convert that to screen coordinates 0145 0146 double xRatio = 0.0; 0147 double yRatio = 0.0; 0148 0149 // Flip the photo dimensions if rotated 0150 0151 int photoW; 0152 int photoH; 0153 0154 if ((d->photo->m_rotation == 0) || (d->photo->m_rotation == 180)) 0155 { 0156 photoW = d->photo->width(); 0157 photoH = d->photo->height(); 0158 } 0159 else 0160 { 0161 photoW = d->photo->height(); 0162 photoH = d->photo->width(); 0163 } 0164 0165 if (d->photo->width() > 0) 0166 { 0167 xRatio = (double) d->image.width() / (double) photoW; 0168 } 0169 0170 if (d->photo->height() > 0) 0171 { 0172 yRatio = (double)d->image.height() / (double)photoH; 0173 } 0174 0175 int x1 = AdvPrintWizard::normalizedInt(r.left() * xRatio + d->imageX); 0176 int y1 = AdvPrintWizard::normalizedInt(r.top() * yRatio + d->imageY); 0177 0178 int w = AdvPrintWizard::normalizedInt(r.width() * xRatio); 0179 int h = AdvPrintWizard::normalizedInt(r.height() * yRatio); 0180 0181 QRect result; 0182 result.setRect(x1, y1, w, h); 0183 0184 return result; 0185 } 0186 0187 void AdvPrintCropFrame::updateImage() 0188 { 0189 if (d->photo) 0190 { 0191 d->image = d->photo->loadPhoto().copyQImage(); 0192 d->image = d->image.transformed(d->matrix); 0193 d->image = d->image.scaled(width(), height(), Qt::KeepAspectRatio); 0194 d->imageX = (width() / 2) - (d->image.width() / 2); 0195 d->imageY = (height() / 2) - (d->image.height() / 2); 0196 d->cropRegion = photoToScreenRect(d->photo->m_cropRegion); 0197 } 0198 } 0199 0200 void AdvPrintCropFrame::resizeEvent(QResizeEvent*) 0201 { 0202 updateImage(); 0203 update(); 0204 } 0205 0206 void AdvPrintCropFrame::paintEvent(QPaintEvent*) 0207 { 0208 updateImage(); 0209 0210 QPixmap bmp(this->width(), this->height()); 0211 QPainter p; 0212 p.begin(&bmp); 0213 0214 p.eraseRect(0, 0, this->width(), this->height()); 0215 0216 // Draw the background image 0217 0218 p.drawImage(d->imageX, d->imageY, d->image); 0219 0220 if (d->drawRec) 0221 { 0222 // Draw the rectangle 0223 0224 p.setPen(QPen(d->color, 2)); 0225 p.drawRect(d->cropRegion); 0226 0227 // Draw the crosshairs 0228 0229 int midX = d->cropRegion.left() + d->cropRegion.width() / 2; 0230 int midY = d->cropRegion.top() + d->cropRegion.height() / 2; 0231 p.drawLine(midX - 10, midY, midX + 10, midY); 0232 p.drawLine(midX, midY - 10, midX, midY + 10); 0233 } 0234 0235 p.end(); 0236 0237 QPainter newp(this); 0238 newp.drawPixmap(0, 0, bmp); 0239 } 0240 0241 void AdvPrintCropFrame::mousePressEvent(QMouseEvent* e) 0242 { 0243 if (e && (e->button() == Qt::LeftButton)) 0244 { 0245 d->mouseDown = true; 0246 QWidget::mouseMoveEvent(e); 0247 } 0248 } 0249 0250 void AdvPrintCropFrame::mouseReleaseEvent(QMouseEvent* e) 0251 { 0252 if (e && (e->button() == Qt::LeftButton)) 0253 { 0254 d->mouseDown = false; 0255 } 0256 } 0257 0258 void AdvPrintCropFrame::mouseMoveEvent(QMouseEvent* e) 0259 { 0260 if (d->mouseDown) 0261 { 0262 // Don't let the rectangle float off the image. 0263 0264 int newW = d->cropRegion.width(); 0265 int newH = d->cropRegion.height(); 0266 0267 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0268 0269 int newX = e->position().toPoint().x() - (newW / 2); 0270 int newY = e->position().toPoint().y() - (newH / 2); 0271 0272 #else 0273 0274 int newX = e->x() - (newW / 2); 0275 int newY = e->y() - (newH / 2); 0276 0277 #endif 0278 0279 newX = qMax(d->imageX, newX); 0280 newX = qMin(d->imageX + d->image.width() - newW, newX); 0281 0282 newY = qMax(d->imageY, newY); 0283 newY = qMin(d->imageY + d->image.height() - newH, newY); 0284 0285 d->cropRegion.setRect(newX, newY, newW, newH); 0286 d->photo->m_cropRegion = screenToPhotoRect(d->cropRegion); 0287 update(); 0288 } 0289 } 0290 0291 void AdvPrintCropFrame::keyReleaseEvent(QKeyEvent* e) 0292 { 0293 int newX = d->cropRegion.x(); 0294 int newY = d->cropRegion.y(); 0295 0296 switch (e->key()) 0297 { 0298 case Qt::Key_Up: 0299 { 0300 newY--; 0301 break; 0302 } 0303 0304 case Qt::Key_Down: 0305 { 0306 newY++; 0307 break; 0308 } 0309 0310 case Qt::Key_Left: 0311 { 0312 newX--; 0313 break; 0314 } 0315 0316 case Qt::Key_Right: 0317 { 0318 newX++; 0319 break; 0320 } 0321 } 0322 0323 // Keep inside the image 0324 0325 int w = d->cropRegion.width(); 0326 int h = d->cropRegion.height(); 0327 0328 newX = qMax(d->imageX, newX); 0329 newX = qMin(d->imageX + d->image.width() - w, newX); 0330 0331 newY = qMax(d->imageY, newY); 0332 newY = qMin(d->imageY + d->image.height() - h, newY); 0333 0334 d->cropRegion.setRect(newX, newY, w, h); 0335 d->photo->m_cropRegion = screenToPhotoRect(d->cropRegion); 0336 update(); 0337 } 0338 0339 void AdvPrintCropFrame::setColor(const QColor& c) 0340 { 0341 d->color = c; 0342 update(); 0343 } 0344 0345 QColor AdvPrintCropFrame::color() const 0346 { 0347 return d->color; 0348 } 0349 0350 void AdvPrintCropFrame::drawCropRectangle(bool draw) 0351 { 0352 d->drawRec = draw; 0353 } 0354 0355 } // Namespace Digikam 0356 0357 #include "moc_advprintcropframe.cpp"