r23525 by jghali - #16069: PDF import distorts images

scribus-commit scribus-commit at lists.scribus.net
Sun Mar 22 15:08:24 UTC 2020


Author: jghali
Date: Sun Mar 22 15:08:24 2020
New Revision: 23525

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=23525
Log:
#16069: PDF import distorts images

Modified:
    trunk/Scribus/scribus/pdf_analyzer.cpp
    trunk/Scribus/scribus/pdf_analyzer.h
    trunk/Scribus/scribus/pdflib_core.cpp
    trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp
    trunk/Scribus/scribus/plugins/import/pdf/slaoutput.h
    trunk/Scribus/scribus/scribusdoc.cpp

Modified: trunk/Scribus/scribus/pdf_analyzer.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/pdf_analyzer.cpp
==============================================================================
--- trunk/Scribus/scribus/pdf_analyzer.cpp	(original)
+++ trunk/Scribus/scribus/pdf_analyzer.cpp	Sun Mar 22 15:08:24 2020
@@ -66,6 +66,7 @@
 
 
 PDFAnalyzer::PDFAnalyzer(QString & filename)
+ : m_filename(filename)
 {
 	static bool nameMapInited = false;
 	if (!nameMapInited)
@@ -82,7 +83,7 @@
 	}
 	catch (PdfError & e)
 	{
-		qDebug() << "Can't open the file";
+		qDebug() << "Can't open PDF file" << filename;
 		e.PrintErrorMsg();
 		return;
 	}
@@ -152,7 +153,7 @@
 	}
 	catch (PdfError & e)
 	{
-		qDebug() << "Error in identifying the color type";
+		qDebug() << "Error in identifying the color type. File:" << m_filename;
 		e.PrintErrorMsg();
 		return CS_Unknown;
 	}
@@ -211,7 +212,7 @@
 	}
 	catch (PdfError & e)
 	{
-		qDebug() << "Error in analyzing stream's resources.";
+		qDebug() << "Error in analyzing stream's resources. File:" << m_filename;
 		e.PrintErrorMsg();
 		return false;
 	}
@@ -384,7 +385,7 @@
 								}
 								else
 								{
-									qDebug() << "Supplied colorspace is undefined!";
+									qDebug() << "Supplied colorspace is undefined! File:" << m_filename;
 									return false;
 								}
 							}
@@ -392,7 +393,7 @@
 					}
 					else
 					{
-						qDebug() << "Wrong syntax in specifying color space!";
+						qDebug() << "Wrong syntax in specifying color space! File:" << m_filename;
 						return false;
 					}
 					}
@@ -453,7 +454,7 @@
 								}
 								else
 								{
-									qDebug() << "Supplied colorspace is undefined!";
+									qDebug() << "Supplied colorspace is undefined! File:" << m_filename;
 									return false;
 								}
 							}
@@ -461,7 +462,7 @@
 					}
 					else
 					{
-						qDebug() << "Wrong syntax in specifying color space!";
+						qDebug() << "Wrong syntax in specifying color space! File:" << m_filename;
 						return false;
 					}
 					}
@@ -530,14 +531,14 @@
 							}
 							else
 							{
-								qDebug() << "Supplied external object is undefined!";
+								qDebug() << "Supplied external object is undefined! File:" << m_filename;
 								return false;
 							}
 							processedNamedXObj.append(args[0].GetName());
 						}
 						else
 						{
-							qDebug() << "Wrong syntax for Do operator or there's no XObject defined!";
+							qDebug() << "Wrong syntax for Do operator or there's no XObject defined! File:" << m_filename;
 							return false;
 						}
 
@@ -617,14 +618,14 @@
 							}
 							else
 							{
-								qDebug() << "Named graphic state used with gs operator is undefined in current ExtGState";
+								qDebug() << "Named graphic state used with gs operator is undefined in current ExtGState. File:" << m_filename;
 								return false;
 							}
 							processedNamedGS.append(args[0].GetName());
 						}
 						else
 						{
-							qDebug() << "Wrong syntax in applying extended graphic state (gs operator) or there's no ExtGState defined!";
+							qDebug() << "Wrong syntax in applying extended graphic state (gs operator) or there's no ExtGState defined! File:" << m_filename;
 							return false;
 						}
 					}
@@ -652,13 +653,13 @@
 							}
 							else
 							{
-								qDebug() << "The specified font cannot be found in current Resources!";
+								qDebug() << "The specified font cannot be found in current Resources! File:" << m_filename;
 								return false;
 							}
 						}
 						else
 						{
-							qDebug() << "Wrong syntax in use of Tf operator or there's no Font defined in current Resources dictionary!";
+							qDebug() << "Wrong syntax in use of Tf operator or there's no Font defined in current Resources dictionary! File:" << m_filename;
 							return false;
 						}
 					}
@@ -674,7 +675,7 @@
 	}
 	catch (PdfError & e)
 	{
-		qDebug() << "Error in parsing content stream";
+		qDebug() << "Error in parsing content stream File:" << m_filename;
 		e.PrintErrorMsg();
 		return false;
 	}

Modified: trunk/Scribus/scribus/pdf_analyzer.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/pdf_analyzer.h
==============================================================================
--- trunk/Scribus/scribus/pdf_analyzer.h	(original)
+++ trunk/Scribus/scribus/pdf_analyzer.h	Sun Mar 22 15:08:24 2020
@@ -164,6 +164,9 @@
 	// pointer to the PoDoFo Pdf's object
 	PoDoFo::PdfMemDocument* m_doc;
 
+	// Path to the analyzed file
+	QString m_filename;
+
 	// Call to this method to inspect a PdfCanvas (either a PdfPage or PdfXObject of subtype Form). This method will be called by inspectPDF
 	// to start inspecting a PDF's page; it could well be called recursively to continue analyzing further in case form XObjects are painted
 	// onto the page.

Modified: trunk/Scribus/scribus/pdflib_core.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/pdflib_core.cpp
==============================================================================
--- trunk/Scribus/scribus/pdflib_core.cpp	(original)
+++ trunk/Scribus/scribus/pdflib_core.cpp	Sun Mar 22 15:08:24 2020
@@ -10349,7 +10349,7 @@
 				              "Please disable experimental PDF and PS embedding and try again.").arg(pdfFile) );
 				return false;
 			}
-			qDebug() << "Failed to embed the PDF file";
+			qDebug() << "Failed to embed the PDF file: " << pdfFile;
 		}
 		// no embedded PDF:
 		if (!imageLoaded)

Modified: trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp	(original)
+++ trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp	Sun Mar 22 15:08:24 2020
@@ -1513,7 +1513,7 @@
 	tmpSel->clear();
 }
 
-void SlaOutputDev::setSoftMask(GfxState * /*state*/, POPPLER_CONST_070 double * /*bbox*/, GBool alpha, Function *transferFunc, GfxColor * /*backdropColor*/)
+void SlaOutputDev::setSoftMask(GfxState * /*state*/, POPPLER_CONST_070 double * bbox, GBool alpha, Function *transferFunc, GfxColor * /*backdropColor*/)
 {
 	if (m_groupStack.count() <= 0)
 		return;
@@ -1529,6 +1529,8 @@
 	else
 		m_groupStack.top().inverted = true;
 	m_groupStack.top().maskName = m_currentMask;
+	// Remember the mask's bounding box as it might not align with the image to which the mask is later assigned.
+	m_groupStack.top().maskBBox = QRectF(QPointF(bbox[0], m_doc->currentPage()->height() - bbox[1]), QPointF(bbox[2], m_doc->currentPage()->height() - bbox[3]));
 	m_groupStack.top().alpha = alpha;
 	if (m_groupStack.top().Items.count() != 0)
 		applyMask(m_groupStack.top().Items.last());
@@ -2459,94 +2461,10 @@
 			t++;
 		}
 	}
-	const double *ctm = state->getCTM();
-	double xCoor = m_doc->currentPage()->xOffset();
-	double yCoor = m_doc->currentPage()->yOffset();
-	QRectF crect = QRectF(0, 0, width, height);
-	m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
-	QLineF cline = QLineF(0, 0, width, 0);
-	QLineF tline = m_ctm.map(cline);
-	QRectF trect = m_ctm.mapRect(crect);
-	double sx = m_ctm.m11();
-	double sy = m_ctm.m22();
-	QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0);
-	if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate))
-	{
-		mm.reset();
-		mm.rotate(-tline.angle());
-		res = res.transformed(mm);
-	}
-	else
-	{
-		if ((sx < 0) || (sy < 0))
-		{
-			mm.reset();
-			if (sx < 0)
-				mm.scale(-1, 1);
-			if (sy < 0)
-				mm.scale(1, -1);
-			res = res.transformed(mm);
-		}
-	}
-	if (res.isNull())
-	{
-		delete imgStr;
-		delete image;
-		return;
-	}
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None);
-	PageItem* ite = m_doc->Items->at(z);
-	ite->ClipEdited = true;
-	ite->FrameType = 3;
-	m_doc->setRedrawBounding(ite);
-	ite->Clip = flattenPath(ite->PoLine, ite->Segments);
-	ite->setTextFlowMode(PageItem::TextFlowDisabled);
-	ite->setFillShade(100);
-	ite->setLineShade(100);
-	ite->setFillEvenOdd(false);
-	m_doc->adjustItemSize(ite);
-	QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png");
-	tempFile->setAutoRemove(false);
-	if (tempFile->open())
-	{
-		QString fileName = getLongPathName(tempFile->fileName());
-		if (!fileName.isEmpty())
-		{
-			tempFile->close();
-			ite->isInlineImage = true;
-			ite->isTempFile = true;
-			res.save(fileName, "PNG");
-			m_doc->loadPict(fileName, ite);
-			ite->setImageScalingMode(false, false);
-			m_Elements->append(ite);
-			if (m_groupStack.count() != 0)
-			{
-				m_groupStack.top().Items.append(ite);
-				applyMask(ite);
-			}
-			if ((checkClip()) && (inPattern == 0))
-			{
-				FPointArray out = m_currentClipPath.copy();
-				out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
-				out.translate(-ite->xPos(), -ite->yPos());
-				ite->PoLine = out.copy();
-				FPoint wh = getMaxClipF(&ite->PoLine);
-				ite->setWidthHeight(wh.x(), wh.y());
-				ite->setTextFlowMode(PageItem::TextFlowDisabled);
-				ite->ScaleType   = true;
-				m_doc->adjustItemSize(ite);
-				ite->OldB2 = ite->width();
-				ite->OldH2 = ite->height();
-				ite->updateClip();
-			}
-		}
-		else
-			m_doc->Items->removeAll(ite);
-	}
-	else
-		m_doc->Items->removeAll(ite);
+
+	createImageFrame(res, state, 3);
+
 	imgStr->close();
-	delete tempFile;
 	delete imgStr;
 	delete image;
 }
@@ -2554,7 +2472,7 @@
 void SlaOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight,
 				   GfxImageColorMap *maskColorMap, GBool maskInterpolate)
 {
-//	qDebug() << "Masked Image Components" << colorMap->getNumPixelComps();
+//	qDebug() << "SlaOutputDev::drawSoftMaskedImage Masked Image Components" << colorMap->getNumPixelComps();
 	ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
 	imgStr->reset();
 	unsigned int *dest = nullptr;
@@ -2604,35 +2522,191 @@
 			t++;
 		}
 	}
+	
+	createImageFrame(res, state, 3);
+	
+	delete imgStr;
+	delete[] buffer;
+	delete image;
+	delete mskStr;
+	delete[] mbuffer;
+}
+
+void SlaOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,  int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GBool maskInterpolate)
+{
+//	qDebug() << "SlaOutputDev::drawMaskedImage";
+	ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+	imgStr->reset();
+	unsigned int *dest = nullptr;
+	unsigned char * buffer = new unsigned char[width * height * 4];
+	QImage * image = nullptr;
+	for (int y = 0; y < height; y++)
+	{
+		dest = (unsigned int *)(buffer + y * 4 * width);
+		Guchar * pix = imgStr->getLine();
+		colorMap->getRGBLine(pix, dest, width);
+	}
+	image = new QImage(buffer, width, height, QImage::Format_RGB32);
+	if (image == nullptr || image->isNull())
+	{
+		delete imgStr;
+		delete[] buffer;
+		delete image;
+		return;
+	}
+	ImageStream *mskStr = new ImageStream(maskStr, maskWidth, 1, 1);
+	mskStr->reset();
+	Guchar *mdest = nullptr;
+	int invert_bit = maskInvert ? 1 : 0;
+	unsigned char * mbuffer = new unsigned char[maskWidth * maskHeight];
+	memset(mbuffer, 0, maskWidth * maskHeight);
+	for (int y = 0; y < maskHeight; y++)
+	{
+		mdest = (Guchar *)(mbuffer + y * maskWidth);
+		Guchar * pix = mskStr->getLine();
+		for (int x = 0; x < maskWidth; x++)
+		{
+			if (pix[x] ^ invert_bit)
+				*mdest++ = 0;
+			else
+				*mdest++ = 255;
+		}
+	}
+	if ((maskWidth != width) || (maskHeight != height))
+		*image = image->scaled(maskWidth, maskHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+	QImage res = image->convertToFormat(QImage::Format_ARGB32);
+	unsigned char cc, cm, cy, ck;
+	int s = 0;
+	for (int yi=0; yi < res.height(); ++yi)
+	{
+		QRgb *t = (QRgb*)(res.scanLine( yi ));
+		for (int xi=0; xi < res.width(); ++xi)
+		{
+			cc = qRed(*t);
+			cm = qGreen(*t);
+			cy = qBlue(*t);
+			ck = mbuffer[s];
+			(*t) = qRgba(cc, cm, cy, ck);
+			s++;
+			t++;
+		}
+	}
+	
+	createImageFrame(res, state, colorMap->getNumPixelComps());
+	
+	delete imgStr;
+	delete[] buffer;
+	delete image;
+	delete mskStr;
+	delete[] mbuffer;
+}
+
+void SlaOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, POPPLER_CONST_082 int* maskColors, GBool inlineImg)
+{
+	ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
+//	qDebug() << "SlaOutputDev::drawImage Image Components" << colorMap->getNumPixelComps() << "Mask" << maskColors;
+	imgStr->reset();
+	QImage* image = nullptr;
+	if (maskColors)
+	{
+		image = new QImage(width, height, QImage::Format_ARGB32);
+		for (int y = 0; y < height; y++)
+		{
+			QRgb *s = (QRgb*)(image->scanLine(y));
+			Guchar *pix = imgStr->getLine();
+			for (int x = 0; x < width; x++)
+			{
+				GfxRGB rgb;
+				colorMap->getRGB(pix, &rgb);
+				int Rc = qRound(colToDbl(rgb.r) * 255);
+				int Gc = qRound(colToDbl(rgb.g) * 255);
+				int Bc = qRound(colToDbl(rgb.b) * 255);
+				*s = qRgba(Rc, Gc, Bc, 255);
+				for (int i = 0; i < colorMap->getNumPixelComps(); ++i)
+				{
+					if (pix[i] < maskColors[2*i] * 255 || pix[i] > maskColors[2*i+1] * 255)
+					{
+						*s = *s | 0xff000000;
+						break;
+					}
+				}
+				s++;
+				pix += colorMap->getNumPixelComps();
+			}
+		}
+	}
+	else
+	{
+		image = new QImage(width, height, QImage::Format_ARGB32);
+		for (int y = 0; y < height; y++)
+		{
+			QRgb *s = (QRgb*)(image->scanLine(y));
+			Guchar *pix = imgStr->getLine();
+			for (int x = 0; x < width; x++)
+			{
+				if (colorMap->getNumPixelComps() == 4)
+				{
+					GfxCMYK cmyk;
+					colorMap->getCMYK(pix, &cmyk);
+					int Cc = qRound(colToDbl(cmyk.c) * 255);
+					int Mc = qRound(colToDbl(cmyk.m) * 255);
+					int Yc = qRound(colToDbl(cmyk.y) * 255);
+					int Kc = qRound(colToDbl(cmyk.k) * 255);
+					*s = qRgba(Yc, Mc, Cc, Kc);
+				}
+				else
+				{
+					GfxRGB rgb;
+					colorMap->getRGB(pix, &rgb);
+					int Rc = qRound(colToDbl(rgb.r) * 255);
+					int Gc = qRound(colToDbl(rgb.g) * 255);
+					int Bc = qRound(colToDbl(rgb.b) * 255);
+					*s = qRgba(Rc, Gc, Bc, 255);
+				}
+				s++;
+				pix += colorMap->getNumPixelComps();
+			}
+		}
+	}
+
+	if (image != nullptr && !image->isNull()) {
+		createImageFrame(*image, state, colorMap->getNumPixelComps());
+	}
+
+	delete imgStr;
+	delete image;
+}
+
+void SlaOutputDev::createImageFrame(QImage& image, GfxState *state, int numColorComponents)
+{
 	const double *ctm = state->getCTM();
 	double xCoor = m_doc->currentPage()->xOffset();
 	double yCoor = m_doc->currentPage()->yOffset();
-	QRectF crect = QRectF(0, 0, width, height);
-	m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
-	QLineF cline = QLineF(0, 0, width, 0);
-	QLineF tline = m_ctm.map(cline);
-	QRectF trect = m_ctm.mapRect(crect);
-	double sx = m_ctm.m11();
-	double sy = m_ctm.m22();
-	QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0);
-	if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate))
-	{
-		mm.reset();
-		mm.rotate(-tline.angle());
-		res = res.transformed(mm);
-	}
-	else
-	{
-		if ((sx < 0) || (sy < 0))
-		{
-			if (sx < 0)
-				mm.scale(-1, 1);
-			if (sy < 0)
-				mm.scale(1, -1);
-			res = res.transformed(mm);
-		}
-	}
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None);
+
+	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
+	double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle();
+	QPointF torigin;
+	// In PDF all images considered squares with unit length that are transformed into the proper
+	// dimensions by ctm.
+	// A positive determinant retains orientation. Thus orientation is the same as in the PDF
+	// coordinate system (y-axis increases upwards). As Scribus uses the inverse orientation the
+	// image needs to be flipped (a horizontal flip is applied later).  For a flipped image the
+	// corner that will be origin in Scribus is the upper right corner (1, 1) of the image.
+	// A negative determinant changes the orientation such that the image is already in the Scribus
+	// coordinate orientation and no flip is necessary. The origin will be the upper left corner (0, 1).
+	if (m_ctm.determinant() > 0) {
+		torigin = m_ctm.map(QPointF(1, 1));
+	} else {
+		torigin = m_ctm.map(QPointF(0, 1));
+	}
+
+    // Determine the width and height of the image by undoing the rotation part
+	// of the CTM and applying the result to the unit square.
+	QTransform without_rotation; 
+	without_rotation = m_ctm * without_rotation.rotate(angle);
+	QRectF trect_wr = without_rotation.mapRect(QRectF(0, 0, 1, 1));
+
+	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -2644,327 +2718,16 @@
 	ite->setFillEvenOdd(false);
 	ite->setFillTransparency(1.0 - state->getFillOpacity());
 	ite->setFillBlendmode(getBlendMode(state));
+	if (m_ctm.determinant() > 0)
+	{
+		ite->setRotation(-(angle - 180));
+		ite->setImageFlippedH(true);
+	}
+	else
+		ite->setRotation(-angle);
 	m_doc->adjustItemSize(ite);
-	QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png");
-	tempFile->setAutoRemove(false);
-	if (tempFile->open())
-	{
-		QString fileName = getLongPathName(tempFile->fileName());
-		if (!fileName.isEmpty())
-		{
-			tempFile->close();
-			ite->isInlineImage = true;
-			ite->isTempFile = true;
-			ite->AspectRatio = false;
-			ite->ScaleType   = false;
-			res.save(fileName, "PNG");
-			m_doc->loadPict(fileName, ite);
-		//	ite->setImageScalingMode(false, false);
-			m_Elements->append(ite);
-			if (m_groupStack.count() != 0)
-			{
-				m_groupStack.top().Items.append(ite);
-			//	applyMask(ite);
-			}
-			if ((checkClip()) && (inPattern == 0))
-			{
-				FPointArray out = m_currentClipPath.copy();
-				out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
-				out.translate(-ite->xPos(), -ite->yPos());
-				ite->PoLine = out.copy();
-				FPoint wh = getMaxClipF(&ite->PoLine);
-				ite->setWidthHeight(wh.x(), wh.y());
-				ite->setTextFlowMode(PageItem::TextFlowDisabled);
-				ite->ScaleType   = true;
-				m_doc->adjustItemSize(ite);
-				ite->OldB2 = ite->width();
-				ite->OldH2 = ite->height();
-				ite->updateClip();
-			}
-		}
-		else
-			m_doc->Items->removeAll(ite);
-	}
-	else
-		m_doc->Items->removeAll(ite);
-	delete tempFile;
-	delete imgStr;
-	delete[] buffer;
-	delete image;
-	delete mskStr;
-	delete[] mbuffer;
-}
-
-void SlaOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,  int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GBool maskInterpolate)
-{
-	ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
-	imgStr->reset();
-	unsigned int *dest = nullptr;
-	unsigned char * buffer = new unsigned char[width * height * 4];
-	QImage * image = nullptr;
-	for (int y = 0; y < height; y++)
-	{
-		dest = (unsigned int *)(buffer + y * 4 * width);
-		Guchar * pix = imgStr->getLine();
-		colorMap->getRGBLine(pix, dest, width);
-	}
-	image = new QImage(buffer, width, height, QImage::Format_RGB32);
-	if (image == nullptr || image->isNull())
-	{
-		delete imgStr;
-		delete[] buffer;
-		delete image;
-		return;
-	}
-	ImageStream *mskStr = new ImageStream(maskStr, maskWidth, 1, 1);
-	mskStr->reset();
-	Guchar *mdest = nullptr;
-	int invert_bit = maskInvert ? 1 : 0;
-	unsigned char * mbuffer = new unsigned char[maskWidth * maskHeight];
-	memset(mbuffer, 0, maskWidth * maskHeight);
-	for (int y = 0; y < maskHeight; y++)
-	{
-		mdest = (Guchar *)(mbuffer + y * maskWidth);
-		Guchar * pix = mskStr->getLine();
-		for (int x = 0; x < maskWidth; x++)
-		{
-			if (pix[x] ^ invert_bit)
-				*mdest++ = 0;
-			else
-				*mdest++ = 255;
-		}
-	}
-	if ((maskWidth != width) || (maskHeight != height))
-		*image = image->scaled(maskWidth, maskHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
-	QImage res = image->convertToFormat(QImage::Format_ARGB32);
-	unsigned char cc, cm, cy, ck;
-	int s = 0;
-	for (int yi=0; yi < res.height(); ++yi)
-	{
-		QRgb *t = (QRgb*)(res.scanLine( yi ));
-		for (int xi=0; xi < res.width(); ++xi)
-		{
-			cc = qRed(*t);
-			cm = qGreen(*t);
-			cy = qBlue(*t);
-			ck = mbuffer[s];
-			(*t) = qRgba(cc, cm, cy, ck);
-			s++;
-			t++;
-		}
-	}
-	const double *ctm = state->getCTM();
-	double xCoor = m_doc->currentPage()->xOffset();
-	double yCoor = m_doc->currentPage()->yOffset();
-	QRectF crect = QRectF(0, 0, width, height);
-	m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
-	QLineF cline = QLineF(0, 0, width, 0);
-	QLineF tline = m_ctm.map(cline);
-	QRectF trect = m_ctm.mapRect(crect);
-	double sx = m_ctm.m11();
-	double sy = m_ctm.m22();
-	QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0);
-	if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate))
-	{
-		mm.reset();
-		mm.rotate(-tline.angle());
-		res = res.transformed(mm);
-	}
-	else
-	{
-		if ((sx < 0) || (sy < 0))
-		{
-			if (sx < 0)
-				mm.scale(-1, 1);
-			if (sy < 0)
-				mm.scale(1, -1);
-			res = res.transformed(mm);
-		}
-	}
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None);
-	PageItem* ite = m_doc->Items->at(z);
-	ite->ClipEdited = true;
-	ite->FrameType = 3;
-	m_doc->setRedrawBounding(ite);
-	ite->Clip = flattenPath(ite->PoLine, ite->Segments);
-	ite->setTextFlowMode(PageItem::TextFlowDisabled);
-	ite->setFillShade(100);
-	ite->setLineShade(100);
-	ite->setFillEvenOdd(false);
-	ite->setFillTransparency(1.0 - state->getFillOpacity());
-	ite->setFillBlendmode(getBlendMode(state));
-	m_doc->adjustItemSize(ite);
-	QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png");
-	tempFile->setAutoRemove(false);
-	if (tempFile->open())
-	{
-		QString fileName = getLongPathName(tempFile->fileName());
-		if (!fileName.isEmpty())
-		{
-			tempFile->close();
-			ite->isInlineImage = true;
-			ite->isTempFile = true;
-			ite->AspectRatio = false;
-			ite->ScaleType   = false;
-			res.save(fileName, "PNG");
-			m_doc->loadPict(fileName, ite);
-		//	ite->setImageScalingMode(false, false);
-			m_Elements->append(ite);
-			if (m_groupStack.count() != 0)
-			{
-				m_groupStack.top().Items.append(ite);
-			//	applyMask(ite);
-			}
-			if ((checkClip()) && (inPattern == 0))
-			{
-				FPointArray out = m_currentClipPath.copy();
-				out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
-				out.translate(-ite->xPos(), -ite->yPos());
-				ite->PoLine = out.copy();
-				FPoint wh = getMaxClipF(&ite->PoLine);
-				ite->setWidthHeight(wh.x(), wh.y());
-				ite->setTextFlowMode(PageItem::TextFlowDisabled);
-				ite->ScaleType   = true;
-				m_doc->adjustItemSize(ite);
-				ite->OldB2 = ite->width();
-				ite->OldH2 = ite->height();
-				ite->updateClip();
-			}
-		}
-		else
-			m_doc->Items->removeAll(ite);
-	}
-	else
-		m_doc->Items->removeAll(ite);
-	delete tempFile;
-	delete imgStr;
-	delete[] buffer;
-	delete image;
-	delete mskStr;
-	delete[] mbuffer;
-}
-
-void SlaOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, POPPLER_CONST_082 int* maskColors, GBool inlineImg)
-{
-	ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits());
-//	qDebug() << "Image Components" << colorMap->getNumPixelComps() << "Mask" << maskColors;
-	imgStr->reset();
-	QImage* image = nullptr;
-	if (maskColors)
-	{
-		image = new QImage(width, height, QImage::Format_ARGB32);
-		for (int y = 0; y < height; y++)
-		{
-			QRgb *s = (QRgb*)(image->scanLine(y));
-			Guchar *pix = imgStr->getLine();
-			for (int x = 0; x < width; x++)
-			{
-				GfxRGB rgb;
-				colorMap->getRGB(pix, &rgb);
-				int Rc = qRound(colToDbl(rgb.r) * 255);
-				int Gc = qRound(colToDbl(rgb.g) * 255);
-				int Bc = qRound(colToDbl(rgb.b) * 255);
-				*s = qRgba(Rc, Gc, Bc, 255);
-				for (int i = 0; i < colorMap->getNumPixelComps(); ++i)
-				{
-					if (pix[i] < maskColors[2*i] * 255 || pix[i] > maskColors[2*i+1] * 255)
-					{
-						*s = *s | 0xff000000;
-						break;
-					}
-				}
-				s++;
-				pix += colorMap->getNumPixelComps();
-			}
-		}
-	}
-	else
-	{
-		image = new QImage(width, height, QImage::Format_ARGB32);
-		for (int y = 0; y < height; y++)
-		{
-			QRgb *s = (QRgb*)(image->scanLine(y));
-			Guchar *pix = imgStr->getLine();
-			for (int x = 0; x < width; x++)
-			{
-				if (colorMap->getNumPixelComps() == 4)
-				{
-					GfxCMYK cmyk;
-					colorMap->getCMYK(pix, &cmyk);
-					int Cc = qRound(colToDbl(cmyk.c) * 255);
-					int Mc = qRound(colToDbl(cmyk.m) * 255);
-					int Yc = qRound(colToDbl(cmyk.y) * 255);
-					int Kc = qRound(colToDbl(cmyk.k) * 255);
-					*s = qRgba(Yc, Mc, Cc, Kc);
-				}
-				else
-				{
-					GfxRGB rgb;
-					colorMap->getRGB(pix, &rgb);
-					int Rc = qRound(colToDbl(rgb.r) * 255);
-					int Gc = qRound(colToDbl(rgb.g) * 255);
-					int Bc = qRound(colToDbl(rgb.b) * 255);
-					*s = qRgba(Rc, Gc, Bc, 255);
-				}
-				s++;
-				pix += colorMap->getNumPixelComps();
-			}
-		}
-	}
-	if (image == nullptr || image->isNull())
-	{
-		delete imgStr;
-		delete image;
-		return;
-	}
-	const double *ctm = state->getCTM();
-	double xCoor = m_doc->currentPage()->xOffset();
-	double yCoor = m_doc->currentPage()->yOffset();
-	QRectF crect = QRectF(0, 0, width, height);
-	m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
-	QLineF cline = QLineF(0, 0, width, 0);
-	QLineF tline = m_ctm.map(cline);
-	QRectF trect = m_ctm.mapRect(crect);
-	double sx = m_ctm.m11();
-	double sy = m_ctm.m22();
-	QImage img = image->copy();
-	QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0);
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None);
-	PageItem* ite = m_doc->Items->at(z);
-	ite->ClipEdited = true;
-	ite->FrameType = 3;
-	m_doc->setRedrawBounding(ite);
-	ite->Clip = flattenPath(ite->PoLine, ite->Segments);
-	ite->setTextFlowMode(PageItem::TextFlowDisabled);
-	ite->setFillShade(100);
-	ite->setLineShade(100);
-	ite->setFillEvenOdd(false);
-	ite->setFillTransparency(1.0 - state->getFillOpacity());
-	ite->setFillBlendmode(getBlendMode(state));
-	m_doc->adjustItemSize(ite);
-	if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate))
-	{
-		ite->setImageRotation(-tline.angle());
-		/*QTransform rotMat;
-		rotMat.rotate(tline.angle());
-		QTransform imgMat = m_ctm * rotMat.inverted();
-		double scaleX = sqrt(imgMat.m11() * imgMat.m11() + imgMat.m12() * imgMat.m12());
-		double scaleY = sqrt(imgMat.m21() * imgMat.m21() + imgMat.m22() * imgMat.m22());
-		imgMat.scale(1.0 / scaleX, 1.0 / scaleY);
-		if (!imgMat.isIdentity())
-			img = img.transformed(imgMat);*/
-	}
-	else
-	{
-		if ((sx < 0) || (sy < 0))
-		{
-			if (sx < 0)
-				ite->setImageFlippedH(true);
-			if (sy < 0)
-				ite->setImageFlippedV(true);
-		}
-	}
-	if (colorMap->getNumPixelComps() == 4)
+
+	if (numColorComponents == 4)
 	{
 		QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.tif");
 		tempFile->setAutoRemove(false);
@@ -2981,16 +2744,16 @@
 				TIFF* tif = TIFFOpen(fileName.toLocal8Bit().data(), "w");
 				if (tif)
 				{
-					TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.width());
-					TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.height());
+					TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image.width());
+					TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image.height());
 					TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
 					TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4);
 					TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
 					TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED);
 					TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
-					for (int y = 0; y < img.height(); ++y)
+					for (int y = 0; y < image.height(); ++y)
 					{
-						TIFFWriteScanline(tif, img.scanLine(y), y);
+						TIFFWriteScanline(tif, image.scanLine(y), y);
 					}
 					TIFFClose(tif);
 					m_doc->loadPict(fileName, ite);
@@ -3021,7 +2784,7 @@
 				ite->isTempFile = true;
 				ite->AspectRatio = false;
 				ite->ScaleType   = false;
-				img.save(fileName, "PNG");
+				image.save(fileName, "PNG");
 				m_doc->loadPict(fileName, ite);
 				m_Elements->append(ite);
 				if (m_groupStack.count() != 0)
@@ -3038,13 +2801,19 @@
 	if ((checkClip()) && (inPattern == 0))
 	{
 		FPointArray out = m_currentClipPath.copy();
+		QTransform mm;
+		mm.rotate(-ite->rotation());
 		out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
 		out.translate(-ite->xPos(), -ite->yPos());
+		// Undo the rotation of the clipping path as it is rotated together with the iamge.
+		for (int i = 0; i != out.size(); ++i)
+		{
+			QPointF p = mm.map(out.pointQF(i));
+			out.setPoint(i, p.x(), p.y());
+		}
 		ite->PoLine = out.copy();
 		ite->ClipEdited = true;
 		ite->FrameType = 3;
-		FPoint wh = getMaxClipF(&ite->PoLine);
-		ite->setWidthHeight(wh.x(), wh.y());
 		ite->setTextFlowMode(PageItem::TextFlowDisabled);
 		ite->ScaleType   = true;
 		m_doc->adjustItemSize(ite);
@@ -3052,8 +2821,6 @@
 		ite->OldH2 = ite->height();
 		ite->updateClip();
 	}
-	delete imgStr;
-	delete image;
 }
 
 void SlaOutputDev::beginMarkedContent(POPPLER_CONST char *name, Object *dictRef)
@@ -3911,6 +3678,10 @@
 		if (!m_groupStack.top().maskName.isEmpty())
 		{
 			ite->setPatternMask(m_groupStack.top().maskName);
+			QRectF bbox = m_groupStack.top().maskBBox; 
+			double sx, sy, px, py, r, shx, shy;
+			ite->maskTransform(sx, sy, px, py, r, shx, shy);
+			ite->setMaskTransform(sx, sy, bbox.x() - (ite->xPos() - m_doc->currentPage()->xOffset()) , bbox.y() - (ite->yPos() - m_doc->currentPage()->yOffset()) , r, shx, shy);
 			if (m_groupStack.top().alpha)
 			{
 				if (m_groupStack.top().inverted)

Modified: trunk/Scribus/scribus/plugins/import/pdf/slaoutput.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/plugins/import/pdf/slaoutput.h
==============================================================================
--- trunk/Scribus/scribus/plugins/import/pdf/slaoutput.h	(original)
+++ trunk/Scribus/scribus/plugins/import/pdf/slaoutput.h	Sun Mar 22 15:08:24 2020
@@ -295,6 +295,9 @@
 	QString UnicodeParsedString(POPPLER_CONST GooString *s1);
 	QString UnicodeParsedString(const std::string& s1);
 	bool checkClip();
+
+	void createImageFrame(QImage& image, GfxState *state, int numColorComponents);
+
 	bool pathIsClosed {false};
 	QString CurrColorFill;
 	int CurrFillShade {100};
@@ -314,6 +317,7 @@
 		GBool isolated;
 		GBool alpha;
 		QString maskName;
+		QRectF maskBBox;
 		bool inverted;
 	};
 	QStack<groupEntry> m_groupStack;

Modified: trunk/Scribus/scribus/scribusdoc.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=23525&path=/trunk/Scribus/scribus/scribusdoc.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusdoc.cpp	(original)
+++ trunk/Scribus/scribus/scribusdoc.cpp	Sun Mar 22 15:08:24 2020
@@ -14565,7 +14565,7 @@
 			currItem->moveImageInFrame(-tp2.x() / currItem->imageXScale(), 0);
 		if (!currItem->imageFlippedV())
 			currItem->moveImageInFrame(0, -tp2.y() / currItem->imageYScale());
-		FPoint tp(clipRect.width(), clipRect.height());
+		FPoint tp(clipRect.right(), clipRect.bottom());
 		if (currItem->imageFlippedH())
 			currItem->moveImageInFrame((currItem->width() - tp.x())/currItem->imageXScale(), 0);
 		if (currItem->imageFlippedV())




More information about the scribus-commit mailing list