File indexing completed on 2024-04-21 03:42:16
0001 /* 0002 SPDX-FileCopyrightText: 2013 Akarsh Simha <akarsh.simha@kdemail.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /* Project Includes */ 0008 #include "imageexporter.h" 0009 #include "kstars.h" 0010 #include "skyqpainter.h" 0011 #include "skymap.h" 0012 0013 #include <KJob> 0014 #include <KIO/StoredTransferJob> 0015 0016 /* Qt Includes */ 0017 #include <QTemporaryFile> 0018 #include <QStatusBar> 0019 #include <QSvgGenerator> 0020 #include <QApplication> 0021 0022 ImageExporter::ImageExporter(QObject *parent) : QObject(parent), m_includeLegend(false), m_Size(nullptr) 0023 { 0024 m_Legend = new Legend; 0025 0026 // set font for legend labels 0027 m_Legend->setFont(QFont("Courier New", 8)); 0028 0029 // set up the default alpha 0030 setLegendAlpha(160); 0031 } 0032 0033 void ImageExporter::exportSvg(const QString &fileName) 0034 { 0035 SkyMap *map = SkyMap::Instance(); 0036 0037 // export as SVG 0038 QSvgGenerator svgGenerator; 0039 svgGenerator.setFileName(fileName); 0040 svgGenerator.setTitle(i18n("KStars Exported Sky Image")); 0041 svgGenerator.setDescription(i18n("KStars Exported Sky Image")); 0042 svgGenerator.setSize(QSize(map->width(), map->height())); 0043 svgGenerator.setResolution(qMax(map->logicalDpiX(), map->logicalDpiY())); 0044 svgGenerator.setViewBox(QRect(0, 0, map->width(), map->height())); 0045 0046 SkyQPainter painter(KStars::Instance(), &svgGenerator); 0047 painter.begin(); 0048 0049 map->exportSkyImage(&painter); 0050 0051 if (m_includeLegend) 0052 { 0053 addLegend(&painter); 0054 } 0055 0056 painter.end(); 0057 } 0058 0059 bool ImageExporter::exportRasterGraphics(const QString &fileName) 0060 { 0061 //Determine desired image format from filename extension 0062 QString ext = fileName.mid(fileName.lastIndexOf(".") + 1); 0063 0064 // export as raster graphics 0065 const char *format = "PNG"; 0066 0067 if (ext.toLower() == "png") 0068 { 0069 format = "PNG"; 0070 } 0071 else if (ext.toLower() == "jpg" || ext.toLower() == "jpeg") 0072 { 0073 format = "JPG"; 0074 } 0075 else if (ext.toLower() == "gif") 0076 { 0077 format = "GIF"; 0078 } 0079 else if (ext.toLower() == "pnm") 0080 { 0081 format = "PNM"; 0082 } 0083 else if (ext.toLower() == "bmp") 0084 { 0085 format = "BMP"; 0086 } 0087 else 0088 { 0089 qWarning() << "Could not parse image format of" << fileName << "assuming PNG"; 0090 } 0091 0092 SkyMap *map = SkyMap::Instance(); 0093 0094 int width, height; 0095 if (m_Size) 0096 { 0097 width = m_Size->width(); 0098 height = m_Size->height(); 0099 } 0100 else 0101 { 0102 width = map->width(); 0103 height = map->height(); 0104 } 0105 0106 QPixmap skyimage(map->width(), map->height()); 0107 QPixmap outimage(width, height); 0108 outimage.fill(); 0109 0110 map->exportSkyImage(&skyimage); 0111 qApp->processEvents(); 0112 0113 //skyImage is the size of the sky map. The requested image size is w x h. 0114 //If w x h is smaller than the skymap, then we simply crop the image. 0115 //If w x h is larger than the skymap, pad the skymap image with a white border. 0116 if (width == map->width() && height == map->height()) 0117 { 0118 outimage = skyimage.copy(); 0119 } 0120 0121 else 0122 { 0123 int dx(0), dy(0), sx(0), sy(0); 0124 int sw(map->width()), sh(map->height()); 0125 0126 if (width > map->width()) 0127 { 0128 dx = (width - map->width()) / 2; 0129 } 0130 0131 else 0132 { 0133 sx = (map->width() - width) / 2; 0134 sw = width; 0135 } 0136 0137 if (height > map->height()) 0138 { 0139 dy = (height - map->height()) / 2; 0140 } 0141 0142 else 0143 { 0144 sy = (map->height() - height) / 2; 0145 sh = height; 0146 } 0147 0148 QPainter p; 0149 p.begin(&outimage); 0150 p.fillRect(outimage.rect(), QBrush(Qt::white)); 0151 p.drawImage(dx, dy, skyimage.toImage(), sx, sy, sw, sh); 0152 p.end(); 0153 } 0154 0155 if (m_includeLegend) 0156 { 0157 addLegend(&outimage); 0158 } 0159 0160 if (!outimage.save(fileName, format)) 0161 { 0162 m_lastErrorMessage = i18n("Error: Unable to save image: %1", fileName); 0163 qDebug() << Q_FUNC_INFO << m_lastErrorMessage; 0164 return false; 0165 } 0166 0167 else 0168 { 0169 KStars::Instance()->statusBar()->showMessage(i18n("Saved image to %1", fileName)); 0170 return true; 0171 } 0172 } 0173 void ImageExporter::addLegend(SkyQPainter *painter) 0174 { 0175 m_Legend->paintLegend(painter); 0176 } 0177 0178 void ImageExporter::addLegend(QPaintDevice *pd) 0179 { 0180 SkyQPainter painter(KStars::Instance(), pd); 0181 painter.begin(); 0182 0183 addLegend(&painter); 0184 0185 painter.end(); 0186 } 0187 0188 bool ImageExporter::exportImage(QString url) 0189 { 0190 QUrl fileURL = QUrl::fromUserInput(url); 0191 0192 m_lastErrorMessage = QString(); 0193 if (fileURL.isValid()) 0194 { 0195 QTemporaryFile tmpfile; 0196 QString fname; 0197 bool isLocalFile = fileURL.isLocalFile(); 0198 0199 if (isLocalFile) 0200 { 0201 fname = fileURL.toLocalFile(); 0202 } 0203 0204 else 0205 { 0206 tmpfile.open(); 0207 fname = tmpfile.fileName(); 0208 } 0209 0210 //Determine desired image format from filename extension 0211 QString ext = fname.mid(fname.lastIndexOf(".") + 1); 0212 if (ext.toLower() == "svg") 0213 { 0214 exportSvg(fname); 0215 } 0216 0217 else 0218 { 0219 return exportRasterGraphics(fname); 0220 } 0221 0222 if (!isLocalFile) 0223 { 0224 //attempt to upload image to remote location 0225 KIO::StoredTransferJob *put_job = KIO::storedHttpPost(&tmpfile, fileURL, -1); 0226 //if(!KIO::NetAccess::upload(tmpfile.fileName(), fileURL, m_KStars)) 0227 if (put_job->exec() == false) 0228 { 0229 m_lastErrorMessage = i18n("Could not upload image to remote location: %1", fileURL.url()); 0230 qWarning() << m_lastErrorMessage; 0231 return false; 0232 } 0233 } 0234 return true; 0235 } 0236 m_lastErrorMessage = i18n("Could not export image: URL %1 invalid", fileURL.url()); 0237 qWarning() << m_lastErrorMessage; 0238 return false; 0239 } 0240 0241 void ImageExporter::setLegendProperties(Legend::LEGEND_TYPE type, Legend::LEGEND_ORIENTATION orientation, 0242 Legend::LEGEND_POSITION position, int alpha, bool include) 0243 { 0244 // set background color (alpha) 0245 setLegendAlpha(alpha); 0246 // set legend orientation 0247 m_Legend->setOrientation(orientation); 0248 0249 // set legend type 0250 m_Legend->setType(type); 0251 0252 // set legend position 0253 m_Legend->setPosition(position); 0254 0255 m_includeLegend = include; 0256 } 0257 0258 ImageExporter::~ImageExporter() 0259 { 0260 delete m_Legend; 0261 } 0262 0263 void ImageExporter::setRasterOutputSize(const QSize *size) 0264 { 0265 if (size) 0266 m_Size = new QSize(*size); // make a copy, so it's safe if the original gets deleted 0267 else 0268 m_Size = nullptr; 0269 } 0270 0271 void ImageExporter::setLegendAlpha(int alpha) 0272 { 0273 Q_ASSERT(alpha >= 0 && alpha <= 255); 0274 Q_ASSERT(m_Legend); 0275 QColor bgColor = m_Legend->getBgColor(); 0276 bgColor.setAlpha(alpha); 0277 m_Legend->setBgColor(bgColor); 0278 }