Adicionar Imagem a PDF usando C++
Adicionar Imagem em um Arquivo PDF Existente
Cada página PDF contém propriedades de Recursos e Conteúdos. Recursos podem ser imagens e formulários, por exemplo, enquanto o conteúdo é representado por um conjunto de operadores PDF. Cada operador tem seu nome e argumento. Este exemplo usa operadores para adicionar uma imagem a um arquivo PDF.
Para adicionar uma imagem a um arquivo PDF existente:
-
Crie um objeto Document e abra o documento PDF de entrada.
-
Obtenha a página na qual você deseja adicionar uma imagem.
-
Adicione a imagem à coleção de Recursos da página.
-
Use operadores para colocar a imagem na página:
-
Use o operador GSave para salvar o estado gráfico atual.
-
Use o operador ConcatenateMatrix para especificar onde a imagem deve ser colocada.
-
Use o operador Do para desenhar a imagem na página.
-
Finalmente, use o operador GRestore para salvar o estado gráfico atualizado.
-
Salve o arquivo. O trecho de código a seguir mostra como adicionar a imagem em um documento PDF.
using namespace System;
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Text;
void WorkingWithImages::AddImageToExistingPDF()
{
String _dataDir("C:\\Samples\\");
// Abrir documento
auto document = MakeObject<Document>(_dataDir + u"AddImage.pdf");
// Definir coordenadas
int lowerLeftX = 50;
int lowerLeftY = 750;
int upperRightX = 100;
int upperRightY = 800;
// Obter a página na qual você deseja adicionar a imagem
auto page = document->get_Pages()->idx_get(1);
// Carregar imagem no stream
auto imageStream = System::IO::File::OpenRead(_dataDir + u"logo.png");
// Adicionar uma imagem à coleção de Imagens dos recursos da página
page->get_Resources()->get_Images()->Add(imageStream);
// Usando o operador GSave: este operador salva o estado gráfico atual
page->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::GSave>());
// Criar objetos Rectangle e Matrix
auto rectangle = MakeObject<Rectangle>(lowerLeftX, lowerLeftY, upperRightX, upperRightY);
auto matrix = MakeObject<Matrix>(
MakeArray<double>({
rectangle->get_URX() - rectangle->get_LLX(),
0, 0,
rectangle->get_URY() - rectangle->get_LLY(),
rectangle->get_LLX(), rectangle->get_LLY() }));
// Usando o operador ConcatenateMatrix (concatenar matriz):
// define como a imagem deve ser posicionada
page->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::ConcatenateMatrix>(matrix));
auto ximage = page->get_Resources()->get_Images()->idx_get(page->get_Resources()->get_Images()->get_Count());
// Usando o operador Do: este operador desenha a imagem
page->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::Do>(ximage->get_Name()));
// Usando o operador GRestore: este operador restaura o estado gráfico
page->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::GRestore>());
// Salvar o novo PDF
document->Save(_dataDir + u"updated_document.pdf");
// Fechar o stream de imagem
imageStream->Close();
}
Adicionar Referência de uma única Imagem várias vezes em um Documento PDF
Às vezes temos a necessidade de usar a mesma imagem várias vezes em um documento PDF. Adicionar uma nova instância aumenta o documento PDF resultante. O método XImageCollection.Add(XImage) permite adicionar referência ao mesmo objeto PDF como imagem original, otimizando o tamanho do Documento PDF.
void WorkingWithImages::AddReferenceOfaSingleImageMultipleTimes() {
String _dataDir("C:\\Samples\\");
auto imageRectangle = MakeObject<Rectangle>(0, 0, 30, 15);
auto document = MakeObject<Document>(_dataDir + u"sample.pdf");
document->get_Pages()->Add();
document->get_Pages()->Add();
auto imageStream = System::IO::File::OpenRead(_dataDir + u"aspose-logo.png");
SharedPtr<Aspose::Pdf::XImage> image;
for (auto page : document->get_Pages()) {
auto annotation = MakeObject<Aspose::Pdf::Annotations::WatermarkAnnotation>(page, page->get_Rect());
auto form = annotation->get_Appearance()->idx_get(u"N");
form->set_BBox(page->get_Rect());
String name;
if (image != nullptr) {
name = form->get_Resources()->get_Images()->Add(imageStream);
image = form->get_Resources()->get_Images()->idx_get(name);
}
else {
form->get_Resources()->get_Images()->AddWithName(image);
}
form->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::GSave>());
form->get_Contents()->Add(
MakeObject<Aspose::Pdf::Operators::ConcatenateMatrix>(
MakeObject<Matrix>(imageRectangle->get_Width(), 0, 0, imageRectangle->get_Height(), 0, 0)));
form->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::Do>(name));
form->get_Contents()->Add(MakeObject<Aspose::Pdf::Operators::GRestore>());
page->get_Annotations()->Add(annotation, false);
imageRectangle = MakeObject<Rectangle>(0, 0, imageRectangle->get_Width() * 1.01, imageRectangle->get_Height() * 1.01);
}
document->Save(_dataDir + u"AddReferenceOfaSingleImageMultipleTimes_out.pdf");
}
Colocar imagem na página e preservar (controlar) a proporção
Se não conhecermos as dimensões da imagem, há todas as chances de obter uma imagem distorcida na página. O exemplo a seguir mostra uma das maneiras de evitar isso.
void WorkingWithImages::AddingImageAndPreserveAspectRatioIntoPDF() {
String _dataDir("C:\\Samples\\");
auto bitmap = System::Drawing::Image::FromFile(_dataDir + u"3410492.jpg");
int width;
int height;
width = bitmap->get_Width();
height = bitmap->get_Height();
auto document = MakeObject<Document>();
auto page = document->get_Pages()->Add();
int scaledWidth = 400;
int scaledHeight = scaledWidth * height / width;
page->AddImage(_dataDir + u"3410492.jpg", new Rectangle(10, 10, scaledWidth, scaledHeight));
document->Save(_dataDir + u"sample_image.pdf");
}
Identificar se a imagem dentro do PDF é Colorida ou Preto e Branco
Para reduzir o tamanho da imagem, você precisa comprimi-la. Antes de poder determinar o tipo de compressão de uma imagem, você precisa saber se ela é colorida ou em preto e branco.
O tipo de compressão aplicado à imagem depende do Espaço de Cor da imagem original, ou seja, se a imagem estiver em cores (RGB), use a compressão JPEG2000, e se for em preto e branco, use a compressão JBIG2 / JBIG2000.
Um arquivo PDF pode conter elementos como Texto, Imagem, Gráfico, Anexo, Anotação, etc., e se o arquivo PDF de origem contiver imagens, podemos determinar o espaço de cor da imagem e aplicar a compressão apropriada para reduzir o tamanho do arquivo PDF.
O trecho de código a seguir mostra as etapas para identificar se a imagem dentro do PDF é colorida ou em preto e branco.
void WorkingWithImages::CheckColors() {
String _dataDir("C:\\Samples\\");
auto document = MakeObject<Document>(_dataDir + u"test4.pdf");
try {
// iterar por todas as páginas do arquivo PDF
for (auto page : document->get_Pages()) {
// criar instância de Image Placement Absorber
auto abs = MakeObject<ImagePlacementAbsorber>();
page->Accept(abs);
for (auto ia : abs->get_ImagePlacements()) {
/* Tipo de Cor */
auto colorType = ia->get_Image()->GetColorType();
switch (colorType) {
case ColorType::Grayscale:
Console::WriteLine(u"Imagem em Escala de Cinza");
break;
case ColorType::Rgb:
Console::WriteLine(u"Imagem Colorida");
break;
}
}
}
}
catch (Exception ex) {
Console::WriteLine(u"Erro ao ler o arquivo = {0}", document->get_FileName());
}
}
Controlar a Qualidade da Imagem
É possível controlar a qualidade de uma imagem que está sendo adicionada a um arquivo PDF. Use o método sobrecarregado Replace na classe XImageCollection.
O trecho de código a seguir demonstra como converter todas as imagens do documento em JPEGs que usam 80% de qualidade para compressão.
void WorkingWithImages::ControlImageQuality() {
String _dataDir("C:\\Samples\\");
auto document = MakeObject<Document>(_dataDir + u"sample_with_images.pdf");
for (auto page : document->get_Pages())
{
int idx = 1;
for (auto image : page->get_Resources()->get_Images())
{
auto imageStream = MakeObject<System::IO::MemoryStream>();
image->Save(imageStream, System::Drawing::Imaging::ImageFormat::get_Jpeg());
page->get_Resources()->get_Images()->Replace(idx, imageStream, 80);
idx = idx + 1;
}
}
document->Save(_dataDir + u"sample_with_images_out.pdf");
}