Commit a80d6721 authored by Peter Zhigalov's avatar Peter Zhigalov

Портировал на Qt библиотеки сохранения изображений от Jon Olick

parent 7afbcfd1
......@@ -21,11 +21,15 @@ lessThan(QT_VERSION, 4.5.0) {
}
SOURCES += \
src_qt/libs/jo_jpeg.cpp \
src_qt/libs/jo_gif.cpp \
src_qt/libs/jo_tga.cpp \
src_qt/paintwidget.cpp \
src_qt/main.cpp \
src_qt/mainwindow.cpp
HEADERS += \
src_qt/libs/jo_images.h \
src_qt/paintwidget.h \
src_qt/mainwindow.h
......
This diff is collapsed.
// http://www.jonolick.com/code.html
#ifndef JO_IMAGES_H
#define JO_IMAGES_H
#include <QDataStream>
#include <QImage>
typedef struct {
QDataStream *stream;
unsigned char palette[0x300];
short width, height, repeat;
int numColors, palSize;
int frame;
} q_jo_gif_t;
// width/height | the same for every frame
// repeat | 0 = loop forever, 1 = loop once, etc...
// palSize | must be power of 2 - 1. so, 255 not 256.
q_jo_gif_t jo_gif_start(QDataStream &stream, short width, short height, short repeat = 0, int numColors = 255);
// gif | the state (returned from jo_gif_start)
// rgba | the pixels
// delayCsec | amount of time in between frames (in centiseconds)
// localPalette | true if you want a unique palette generated for this frame (does not effect future frames)
void jo_gif_frame(q_jo_gif_t &gif, const QImage &image, short delayCsec, bool localPalette = false);
// gif | the state (returned from jo_gif_start)
void jo_gif_end(q_jo_gif_t &gif);
// Returns false on failure
void jo_write_jpg(QDataStream &stream, const QImage &image, int quality = 0);
void jo_write_tga(QDataStream &stream, const QImage &image, bool transparency);
#endif // JO_IMAGES_H
This diff is collapsed.
// Based on TGA Writer from http://www.jonolick.com/code.html
#include <QDataStream>
#include <QImage>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
void jo_write_tga(QDataStream &stream, const QImage &image, bool transparency) {
// Convert QImage to rgb(a)
int width = image.width();
int height = image.height();
int numChannels = transparency ? 4 : 3;
unsigned char *rgba = (unsigned char *)malloc(width * height * numChannels);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
unsigned offset = numChannels * (y * width + x);
QRgb pixel = image.pixel(x, y);
rgba[offset] = qRed(pixel);
rgba[offset+1] = qGreen(pixel);
rgba[offset+2] = qBlue(pixel);
if(transparency) rgba[offset+3] = qAlpha(pixel);
}
}
// Header
stream.writeRawData("\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12);
stream.writeRawData((const char*)(&width), 2);
stream.writeRawData((const char*)(&height), 2);
int bpc = numChannels * 8; // 8 bits per channel
stream.writeRawData((const char*)(&bpc), 2);
// Swap RGBA to BGRA if using 3 or more channels
int remap[4] = {numChannels >= 3 ? 2 : 0, 1, numChannels >= 3 ? 0 : 2, 3};
char *s = (char *)rgba;
for(int y = height-1; y >= 0; --y) {
int i = (y * width) * numChannels;
for(int x = i; x < i+width*numChannels; x += numChannels) {
for(int j = 0; j < numChannels; ++j) {
stream << (quint8)(s[x+remap[j]]);
}
}
}
// Free rgb(a)
free(rgba);
}
......@@ -5,6 +5,7 @@
#include <QSvgGenerator>
#include <QPrinter>
#include <algorithm>
#include "libs/jo_images.h"
// Конструктор
MainWindow::MainWindow(QWidget *parent) :
......@@ -193,7 +194,9 @@ void MainWindow::on_actionSave_Image_File_triggered()
supported.push_back(QString(*it).toLower());
supported_temp.clear();
supported.push_back("svg");
//#if !defined HAVE_QT5
// supported.push_back("ps");
//#endif
supported.push_back("pdf");
bool qt_jpg = true;
......@@ -278,13 +281,19 @@ void MainWindow::on_actionSave_Image_File_triggered()
ui->widget->draw(& generator, ui->actionTransparent_Image->isChecked(), true);
saved = true;
}
else if(ext == "ps" || ext == "pdf")
//#if !defined HAVE_QT5
// else if(ext == "ps" || ext == "pdf")
//#else
else if(ext == "pdf")
//#endif
{
QPrinter printer(QPrinter::ScreenResolution);
if(ext == "pdf")
printer.setOutputFormat(QPrinter::PdfFormat);
//#if !defined HAVE_QT5
// else if(ext == "ps")
// printer.setOutputFormat(QPrinter::PostScriptFormat);
//#endif
printer.setOutputFileName(filename);
printer.setPaperSize(QSizeF(ui->widget->width(), ui->widget->height()), QPrinter::DevicePixel);
printer.setPageMargins(0, 0, 0, 0, QPrinter::DevicePixel);
......@@ -293,15 +302,47 @@ void MainWindow::on_actionSave_Image_File_triggered()
}
else if(ext == "jpg" && !qt_jpg)
{
QFile file(filename);
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
if(stream.status() == QDataStream::Ok)
{
QImage image(ui->widget->width(), ui->widget->height(), QImage::Format_ARGB32_Premultiplied);
ui->widget->draw(& image, false);
jo_write_jpg(stream, image);
stream.device()->close();
saved = true;
}
}
else if(ext == "gif" && !qt_gif)
{
QFile file(filename);
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
if(stream.status() == QDataStream::Ok)
{
QImage image(ui->widget->width(), ui->widget->height(), QImage::Format_ARGB32_Premultiplied);
ui->widget->draw(& image, false);
q_jo_gif_t gif = jo_gif_start(stream, image.width(), image.height());
jo_gif_frame(gif, image, 0);
jo_gif_end(gif);
stream.device()->close();
saved = true;
}
}
else if(ext == "tga" && !qt_tga)
{
QFile file(filename);
file.open(QIODevice::WriteOnly);
QDataStream stream(&file);
if(stream.status() == QDataStream::Ok)
{
QImage image(ui->widget->width(), ui->widget->height(), QImage::Format_ARGB32_Premultiplied);
ui->widget->draw(& image, ui->actionTransparent_Image->isChecked());
jo_write_tga(stream, image, ui->actionTransparent_Image->isChecked());
stream.device()->close();
saved = true;
}
}
else
{
......@@ -422,6 +463,35 @@ void MainWindow::on_actionAbout_FEM_Draw_triggered()
msgBox.exec();
}
// Событие при нажатии кнопки About Libraries
void MainWindow::on_actionAbout_Third_Party_Libraries_triggered()
{
QMessageBox msgBox;
msgBox.setAttribute(Qt::WA_QuitOnClose);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setWindowTitle("About Third Party Libraries");
msgBox.setText("<b>Third Party Libraries:</b><br>"
"<table border=\"0\">"
"<tr><td style=\"padding-right:8%\">Library:</td><td>Jon Olick JPEG Writer</td></tr>"
"<tr><td style=\"padding-right:8%\">License:</td><td>public domain</td></tr>"
"<tr><td style=\"padding-right:8%\">Website:</td><td><a href=\"http://www.jonolick.com/code.html\">http://www.jonolick.com/code.html</td></tr>"
"</table><br>"
"<table border=\"0\">"
"<tr><td style=\"padding-right:8%\">Library:</td><td>Jon Olick GIF Writer</td></tr>"
"<tr><td style=\"padding-right:8%\">License:</td><td>public domain</td></tr>"
"<tr><td style=\"padding-right:8%\">Website:</td><td><a href=\"http://www.jonolick.com/code.html\">http://www.jonolick.com/code.html</td></tr>"
"</table><br>"
"<table border=\"0\">"
"<tr><td style=\"padding-right:8%\">Library:</td><td>Jon Olick TGA Writer</td></tr>"
"<tr><td style=\"padding-right:8%\">License:</td><td>public domain</td></tr>"
"<tr><td style=\"padding-right:8%\">Website:</td><td><a href=\"http://www.jonolick.com/code.html\">http://www.jonolick.com/code.html</td></tr>"
"</table>");
msgBox.setIconPixmap(QPixmap::fromImage(QImage(":/resources/icon_64.png")));
msgBox.setWindowIcon(QIcon(":/resources/icon.ico"));
msgBox.exec();
}
// Событие при переключении закраски цветом
void MainWindow::on_checkBox_Color_clicked()
{
......
......@@ -57,6 +57,8 @@ private slots:
void on_actionMemory_Limit_triggered();
// Событие при нажатии кнопки About
void on_actionAbout_FEM_Draw_triggered();
// Событие при нажатии кнопки About Libraries
void on_actionAbout_Third_Party_Libraries_triggered();
// Событие при переключении закраски цветом
void on_checkBox_Color_clicked();
// Изменение переменной, которую выводим
......
......@@ -200,6 +200,7 @@
<string>About</string>
</property>
<addaction name="actionAbout_FEM_Draw"/>
<addaction name="actionAbout_Third_Party_Libraries"/>
<addaction name="actionAbout_Qt"/>
</widget>
<widget class="QMenu" name="menuConfiguration">
......@@ -273,6 +274,11 @@
<string>About FEM Draw</string>
</property>
</action>
<action name="actionAbout_Third_Party_Libraries">
<property name="text">
<string>About Third Party Libraries</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="text">
<string>About Qt</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment