Stop resizing images when transferred as such

This commit is contained in:
Anton Thomasson 2022-05-16 21:52:00 +02:00
parent ff2eae04cf
commit 08b66ed711
14 changed files with 116 additions and 63 deletions

View file

@ -34,9 +34,12 @@ For images, your printer needs to support one of the following formats:
* PDF
* Postscript
For printing JPEG images, transferring the unaltered image has priority and the printer does the scaling.
JPEGs are however (losslessly) re-encoded to the baseline encoding profile to work with all printers (since SeaPrint 1.1).
Other image formats are lossless and SeaPrint does scale-and-rotate to fit, so JPEG has lowest prio there.
When printing images the result may depend on how they are transferred.
If a document-oriented format like PDF/Postscript/PWG/URF is used SeaPrint does scale-and-rotate to fit, otherwise (when transferred as PNG or JPEG) that is left up to the printer. Only when printing images *as images* can the scaling setting be used.
For printing JPEG images, transferring them as JPEG has highest priority.
JPEGs are then (losslessly) re-encoded to the baseline encoding profile to work with all printers (since SeaPrint 1.1).
For other image formats JPEG has lowest priority as transfer format since it is lossy.
Printers with any of these IPP certifications and derivative standards should likely be supported:

View file

@ -148,10 +148,10 @@ Page {
tag: IppMsg.Keyword
name: "print-scaling"
prettyName: qsTr("Scaling")
valid: _valid && selectedFileType == Mimer.JPEG
valid: _valid && Mimer.isImage(selectedFileType)
DependentOn {
target: transferFormatSetting
values: [Mimer.JPEG]
values: [Mimer.JPEG, Mimer.PNG]
}
}
ChoiceSetting {

View file

@ -20,7 +20,7 @@ IppPrinter::IppPrinter() : _worker(this)
connect(this, &IppPrinter::doIdentify, &_worker, &PrinterWorker::identify);
connect(this, &IppPrinter::doJustUpload, &_worker, &PrinterWorker::justUpload);
connect(this, &IppPrinter::doFixupPlaintext, &_worker, &PrinterWorker::fixupPlaintext);
connect(this, &IppPrinter::doFixupJpeg, &_worker, &PrinterWorker::fixupJpeg);
connect(this, &IppPrinter::doFixupImage, &_worker, &PrinterWorker::fixupImage);
connect(this, &IppPrinter::doConvertPdf, &_worker, &PrinterWorker::convertPdf);
connect(this, &IppPrinter::doConvertImage, &_worker, &PrinterWorker::convertImage);
@ -566,7 +566,7 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
getAttrOrDefault(jobAttrs, "media-bottom-margin", "media-col").toInt());
// Only keep margin setting for JPEG - but only attemt to remove it if media-col exists
if(!(mimeType == Mimer::JPEG && targetFormat == Mimer::JPEG) && jobAttrs.contains("media-col"))
if(!mimer->isImage(targetFormat) && jobAttrs.contains("media-col"))
{
QJsonObject MediaCol = jobAttrs["media-col"].toObject();
QJsonObject MediaColValue = MediaCol["value"].toObject();
@ -688,9 +688,9 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
{ // Can't process Postscript
emit doJustUpload(filename, contents);
}
else if((mimeType == targetFormat) && (targetFormat == Mimer::JPEG))
{ // Just make the jpeg baseline-encoded, don't resize locally
emit doFixupJpeg(filename, contents);
else if(mimer->isImage(targetFormat))
{ // Just make sure the image is in the desired format (and jpeg baseline-encoded), don't resize locally
emit doFixupImage(filename, contents, targetFormat);
}
else
{
@ -723,7 +723,7 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
}
else if (Mimer::isImage(mimeType))
{
emit doConvertImage(filename, contents, Params, targetFormat, margins);
emit doConvertImage(filename, contents, Params, margins);
}
else if(Mimer::isOffice(mimeType))
{

View file

@ -62,11 +62,11 @@ signals:
void doJustUpload(QString filename, Bytestream header);
void doFixupPlaintext(QString filename, Bytestream header);
void doFixupJpeg(QString filename, Bytestream header);
void doFixupImage(QString filename, Bytestream header, QString targetFormat);
void doConvertPdf(QString filename, Bytestream header, PrintParameters Params);
void doConvertImage(QString filename, Bytestream header, PrintParameters Params, QString targetFormat, QMargins margins);
void doConvertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins);
void doConvertOfficeDocument(QString filename, Bytestream header, PrintParameters Params);

View file

@ -23,6 +23,7 @@ const QString Mimer::ODP = "application/vnd.oasis.opendocument.presentation";
const QString Mimer::Plaintext = "text/plain";
const QStringList Mimer::RasterFormats = {PWG, URF};
const QStringList Mimer::OfficeFormats = {DOC, DOCX, RTF, RTF_APP, ODT, PPT, PPTX, ODP};
Mimer::Mimer()

View file

@ -61,11 +61,16 @@ public:
static const QString Plaintext;
static const QStringList RasterFormats;
static const QStringList OfficeFormats;
Q_INVOKABLE static bool isImage(QString mimeType)
{
return mimeType.startsWith("image/");
return mimeType.startsWith("image/") && ! isRaster(mimeType);
}
Q_INVOKABLE static bool isRaster(QString mimeType)
{
return RasterFormats.contains(mimeType);
}
Q_INVOKABLE static bool isOffice(QString mimeType)
{

View file

@ -85,17 +85,54 @@ catch(const ConvertFailedException& e)
}
}
void PrinterWorker::fixupJpeg(QString filename, Bytestream header)
void PrinterWorker::fixupImage(QString filename, Bytestream header, QString targetFormat)
{
try {
QString imageFormat = "";
QStringList supportedImageFormats = {Mimer::JPEG, Mimer::PNG};
if(supportedImageFormats.contains(targetFormat))
{
imageFormat = targetFormat.split("/")[1];
}
else
{
throw ConvertFailedException(tr("Unknown target format"));
}
QString mimeType = Mimer::instance()->get_type(filename);
Bytestream OutBts;
CurlRequester cr(_printer->httpUrl());
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::printRequestFinished);
std::ifstream ifs = std::ifstream(filename.toStdString(), std::ios::in | std::ios::binary);
Bytestream InBts(ifs);
Bytestream OutBts;
if(mimeType == Mimer::JPEG && targetFormat == Mimer::JPEG)
{
std::ifstream ifs = std::ifstream(filename.toStdString(), std::ios::in | std::ios::binary);
Bytestream InBts(ifs);
baselinify(InBts, OutBts);
baselinify(InBts, OutBts);
}
else if(targetFormat == mimeType)
{
std::ifstream ifs = std::ifstream(filename.toStdString(), std::ios::in | std::ios::binary);
OutBts = Bytestream(ifs);
}
else
{
QImage inImage;
QBuffer buf;
if(!inImage.load(filename))
{
qDebug() << "failed to load";
throw ConvertFailedException(tr("Failed to load image"));
}
buf.open(QIODevice::ReadWrite);
inImage.save(&buf, imageFormat.toStdString().c_str());
buf.seek(0);
OutBts = Bytestream(buf.size());
buf.read((char*)(OutBts.raw()), buf.size());
}
emit busyMessage(tr("Printing"));
@ -192,17 +229,10 @@ catch(const ConvertFailedException& e)
}
}
void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParameters Params, QString targetFormat, QMargins margins)
void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins)
{
try {
QString imageFormat = "";
QStringList supportedImageFormats = {Mimer::JPEG, Mimer::PNG};
if(supportedImageFormats.contains(targetFormat))
{
imageFormat = targetFormat.split("/")[1];
}
if(Params.format == PrintParameters::URF && (Params.hwResW != Params.hwResH))
{ // URF only supports symmetric resolutions
@ -235,7 +265,7 @@ try {
inImage = inImage.scaled(Params.getPaperSizeWInPixels()-totalXMarginPx, Params.getPaperSizeHInPixels()-totalYMarginPx,
Qt::KeepAspectRatio, Qt::SmoothTransformation);
if(imageFormat == "" && (Params.format == PrintParameters::PDF || Params.format == PrintParameters::Postscript))
if(Params.format == PrintParameters::PDF || Params.format == PrintParameters::Postscript)
{
QTemporaryFile tmpPdfFile;
tmpPdfFile.open();
@ -267,45 +297,35 @@ try {
buf.open(QIODevice::ReadWrite);
Bytestream outBts;
if(imageFormat != "")
{ // We are converting to a supported image format
outImage.save(&buf, imageFormat.toStdString().c_str());
buf.seek(0);
outBts = Bytestream(buf.size());
buf.read((char*)(outBts.raw()), buf.size());
if(inImage.allGray())
{
Params.colors = 1; // No need to waste space/bandwidth...
}
else
{ // We are converting to a raster format
if(inImage.allGray())
{
Params.colors = 1; // No need to waste space/bandwidth...
}
outImage.save(&buf, Params.colors==1 ? "pgm" : "ppm");
buf.seek(0);
// Skip header - TODO consider reimplementing
buf.readLine(255);
buf.readLine(255);
buf.readLine(255);
outImage.save(&buf, Params.colors==1 ? "pgm" : "ppm");
buf.seek(0);
// Skip header - TODO consider reimplementing
buf.readLine(255);
buf.readLine(255);
buf.readLine(255);
Bytestream inBts(Params.getPaperSizeWInPixels() * Params.getPaperSizeHInPixels() * Params.colors);
Bytestream inBts(Params.getPaperSizeWInPixels() * Params.getPaperSizeHInPixels() * Params.colors);
if((((size_t)buf.size())-buf.pos()) != inBts.size())
{
qDebug() << buf.size() << buf.pos() << inBts.size();
throw ConvertFailedException();
}
buf.read((char*)(inBts.raw()), inBts.size());
outBts << (Params.format == PrintParameters::URF ? make_urf_file_hdr(1) : make_pwg_file_hdr());
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
bmp_to_pwg(inBts, outBts, 1, Params, verbose);
if((((size_t)buf.size())-buf.pos()) != inBts.size())
{
qDebug() << buf.size() << buf.pos() << inBts.size();
throw ConvertFailedException();
}
buf.read((char*)(inBts.raw()), inBts.size());
outBts << (Params.format == PrintParameters::URF ? make_urf_file_hdr(1) : make_pwg_file_hdr());
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
bmp_to_pwg(inBts, outBts, 1, Params, verbose);
CurlRequester cr(_printer->httpUrl());
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::printRequestFinished);

View file

@ -40,13 +40,13 @@ public slots:
void justUpload(QString filename, Bytestream header);
void fixupJpeg(QString filename, Bytestream header);
void fixupImage(QString filename, Bytestream header, QString targetFormat);
void fixupPlaintext(QString filename, Bytestream header);
void convertPdf(QString filename, Bytestream header, PrintParameters Params);
void convertImage(QString filename, Bytestream header, PrintParameters Params, QString targetFormat, QMargins margins);
void convertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins);
void convertOfficeDocument(QString filename, Bytestream header, PrintParameters Params);

View file

@ -520,6 +520,10 @@ auf diesem Drucker</translation>
<source>Upload error</source>
<translation>Übertragungsfehler</translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>

View file

@ -519,6 +519,10 @@
<source>Upload error</source>
<translation>Error de carga</translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>

View file

@ -520,6 +520,10 @@ sur cette imprimante</translation>
<source>Upload error</source>
<translation>Erreur de chargement</translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>

View file

@ -519,6 +519,10 @@
<source>Upload error</source>
<translation>Uploadfout</translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>

View file

@ -519,6 +519,10 @@
<source>Upload error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>

View file

@ -519,6 +519,10 @@
<source>Upload error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>