Editor plugin: Image

This commit is contained in:
Jakub Melka 2024-06-15 16:03:54 +02:00
parent 05cf65b381
commit aa92fabd79
5 changed files with 74 additions and 5 deletions

View File

@ -226,7 +226,7 @@ bool EditorPlugin::save()
const pdf::PDFPageContentImageElement* elementImage = element->asElementImage();
const pdf::PDFPageContentElementTextBox* elementTextBox = element->asElementTextBox();
// TODO: Impelement all things
// TODO: Implement all things
if (editedElement)
{
@ -263,11 +263,35 @@ bool EditorPlugin::save()
contentStreamBuilder.writeStyledPath(path, elementLine->getPen(), elementLine->getBrush(), true, false);
}
if (elementDot)
{
QPen pen = elementDot->getPen();
const qreal radius = pen.widthF() * 0.5;
QPainterPath path;
path.addEllipse(elementDot->getPoint(), radius, radius);
contentStreamBuilder.writeStyledPath(path, Qt::NoPen, QBrush(pen.color()), false, true);
}
if (elementFreehandCurve)
{
QPainterPath path = elementFreehandCurve->getCurve();
contentStreamBuilder.writeStyledPath(path, elementFreehandCurve->getPen(), elementFreehandCurve->getBrush(), true, false);
}
if (elementImage)
{
QImage image = elementImage->getImage();
if (!image.isNull())
{
contentStreamBuilder.writeImage(image, elementImage->getRectangle());
}
else
{
// It is probably an SVG image
}
}
}
}

View File

@ -709,16 +709,17 @@ void PDFPageContentEditorContentStreamBuilder::writeImage(QTextStream& stream, c
array.appendItem(PDFObject::createName("FlateDecode"));
QImage codedImage = image;
codedImage = codedImage.convertToFormat(QImage::Format_ARGB32);
codedImage = codedImage.convertToFormat(QImage::Format_RGB888);
QByteArray decodedStream(reinterpret_cast<const char*>(image.constBits()), image.sizeInBytes());
// Compress the content stream
QByteArray compressedData = PDFFlateDecodeFilter::compress(decodedStream);
PDFDictionary imageDictionary;
imageDictionary.setEntry(PDFInplaceOrMemoryString("Subtitle"), PDFObject::createName("Image"));
imageDictionary.setEntry(PDFInplaceOrMemoryString("Subtype"), PDFObject::createName("Image"));
imageDictionary.setEntry(PDFInplaceOrMemoryString("Width"), PDFObject::createInteger(image.width()));
imageDictionary.setEntry(PDFInplaceOrMemoryString("Height"), PDFObject::createInteger(image.height()));
imageDictionary.setEntry(PDFInplaceOrMemoryString("Predictor"), PDFObject::createInteger(1));
imageDictionary.setEntry(PDFInplaceOrMemoryString("ColorSpace"), PDFObject::createName("DeviceRGB"));
imageDictionary.setEntry(PDFInplaceOrMemoryString("BitsPerComponent"), PDFObject::createInteger(8));
imageDictionary.setEntry(PDFInplaceOrMemoryString("Length"), PDFObject::createInteger(compressedData.size()));
@ -811,4 +812,26 @@ void PDFPageContentEditorContentStreamBuilder::writeStyledPath(const QPainterPat
writePainterPath(stream, path, isStroking, isFilling);
}
void PDFPageContentEditorContentStreamBuilder::writeImage(const QImage& image,
const QRectF& rectangle)
{
QTextStream stream(&m_outputContent, QDataStream::WriteOnly | QDataStream::Append);
stream << "q" << Qt::endl;
QTransform imageTransform(rectangle.width(), 0, 0, -rectangle.height(), rectangle.left(), rectangle.bottom());
PDFReal m11 = imageTransform.m11();
PDFReal m12 = imageTransform.m12();
PDFReal m21 = imageTransform.m21();
PDFReal m22 = imageTransform.m22();
PDFReal x = imageTransform.dx();
PDFReal y = imageTransform.dy();
stream << m11 << " " << m12 << " " << m21 << " " << m22 << " " << x << " " << y << " cm" << Qt::endl;
writeImage(stream, image);
stream << "Q" << Qt::endl;
}
} // namespace pdf

View File

@ -29,7 +29,6 @@ class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorContentStreamBuilder
public:
PDFPageContentEditorContentStreamBuilder(PDFDocument* document);
void writeStateDifference(QTextStream& stream, const PDFPageContentProcessorState& state);
void writeEditedElement(const PDFEditedPageContentElement* element);
const QByteArray& getOutputContent() const;
@ -49,7 +48,11 @@ public:
bool isStroking,
bool isFilling);
void writeImage(const QImage& image, const QRectF& rectangle);
private:
void writeStateDifference(QTextStream& stream, const PDFPageContentProcessorState& state);
void writePainterPath(QTextStream& stream,
const QPainterPath& path,
bool isStroking,

View File

@ -30,6 +30,7 @@
#include <QSvgRenderer>
#include <QApplication>
#include <QImageReader>
#include <QXmlStreamReader>
namespace pdf
{
@ -1257,7 +1258,22 @@ void PDFPageContentImageElement::setContent(const QByteArray& newContent)
if (m_content != newContent)
{
m_content = newContent;
if (!m_renderer->load(m_content))
m_renderer = std::make_unique<QSvgRenderer>();
QXmlStreamReader xml(m_content);
while (!xml.atEnd() && !xml.hasError())
{
xml.readNext();
}
bool isSvgLoaded = false;
if (!xml.hasError())
{
isSvgLoaded = m_renderer->load(m_content);
}
if (!isSvgLoaded)
{
QByteArray imageData = m_content;
QBuffer buffer(&imageData);

View File

@ -329,6 +329,9 @@ public:
const QRectF& getRectangle() const;
void setRectangle(const QRectF& newRectangle);
const QSvgRenderer* getRenderer() const { return m_renderer.get(); }
const QImage& getImage() const { return m_image; }
private:
QRectF m_rectangle;
QByteArray m_content;