Image masks
This example was written in response to the question Click How to make an image a qualified mask candidate in itext?
makejpgmask
JAVA
JAVA
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2023 Apryse Group NV
Authors: Apryse Software.
For more information, please contact iText Software at this address:
sales@itextpdf.com
*/
package com.itextpdf.samples.sandbox.images;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.io.source.ByteArrayOutputStream;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MakeJpgMask {
public static final String DEST = "./target/sandbox/images/make_jpg_mask.pdf";
public static final String IMAGE = "./src/main/resources/img/javaone2013.jpg";
public static final String MASK = "./src/main/resources/img/berlin2013.jpg";
public static void main(String[] args) throws Exception {
File file = new File(DEST);
file.getParentFile().mkdirs();
new MakeJpgMask().manipulatePdf(DEST);
}
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
PageSize pageSize = PageSize.A4.rotate();
Document doc = new Document(pdfDoc, pageSize);
ImageData image = ImageDataFactory.create(IMAGE);
ImageData mask = convertToBlackAndWhitePng(MASK);
mask.makeMask();
image.setImageMask(mask);
Image img = new Image(image);
img.scaleAbsolute(pageSize.getWidth(), pageSize.getHeight());
img.setFixedPosition(0, 0);
doc.add(img);
doc.close();
}
private static ImageData convertToBlackAndWhitePng(String image) throws IOException {
BufferedImage bi = ImageIO.read(new File(image));
BufferedImage newBi = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_USHORT_GRAY);
newBi.getGraphics().drawImage(bi, 0, 0, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(newBi, "png", baos);
return ImageDataFactory.create(baos.toByteArray());
}
}
C#
C#
using System;
using System.Drawing;
using System.IO;
using iText.IO.Image;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Layout;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using iText.Kernel.Pdf.Xobject;
using Image = iText.Layout.Element.Image;
namespace iText.Samples.Sandbox.Images
{
public class MakeJpgMask
{
public static readonly String DEST = "results/sandbox/images/make_jpg_mask.pdf";
public static readonly String IMAGE = "../../../resources/img/javaone2013.jpg";
public static readonly String MASK = "../../../resources/img/berlin2013.jpg";
public static void Main(String[] args)
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
new MakeJpgMask().ManipulatePdf(DEST);
}
protected void ManipulatePdf(String dest)
{
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
PageSize pageSize = PageSize.A4.Rotate();
Document doc = new Document(pdfDoc, pageSize);
ImageData image = ImageDataFactory.Create(IMAGE);
ImageData mask = ConvertToBlackAndWhitePng(MASK);
mask.MakeMask();
image.SetImageMask(mask);
/* For soft image masks grayscale 8 bit images are usually used. As described in
* the ConvertToBlackAndWhitePng, for image masks actual image colorspace doesn't
* matter, only image pixel values are important. Grayscale images are just
* convenient for this purpose.
* Here we adjust SMask image dictionary, in order to accommodate to the hacks
* that we've performed in ConvertToBlackAndWhitePng method. There we've created
* an image in indexed color space and by default C# will add transparency to the
* image. Both these properties are forbidden for images that serve as masks.
* That's why we explicitly override colorspace to /DeviceGray (which corresponds
* to grayscale) and we just erase own transparency (/Mask) from the dictionary
* of mask-image.
*/
PdfImageXObject imageXObject = new PdfImageXObject(image);
PdfStream imageXObjectStream = imageXObject.GetPdfObject().GetAsStream(PdfName.SMask);
imageXObjectStream.Put(PdfName.ColorSpace, PdfName.DeviceGray);
// Remove a redundant submask
imageXObjectStream.Remove(PdfName.Mask);
Image img = new Image(imageXObject);
img.ScaleAbsolute(pageSize.GetWidth(), pageSize.GetHeight());
img.SetFixedPosition(0, 0);
doc.Add(img);
doc.Close();
}
private static ImageData ConvertToBlackAndWhitePng(String image)
{
FileStream fileStream = new FileStream(image, FileMode.Open);
/* Image masks shall have either 8 bit or 1 bit color depth.
* In this example we create a soft mask, for which 8 bit image is used.
* For images used as masks, image color space is not relevant, only the
* values of image pixels are important because they define transparency
* level.
* In C#, however, 8 bits per pixel (bpp) images are not well supported,
* therefore we need to perform some tricks to convert RGB 24bpp image
* to 8 bit image. We will manually set image pixel 8 bit values according
* to original image RGB pixel values.
* Note that even though we create image with indexed colorspace
* (Format8bppIndexed), we don't care what are the actual colors in color
* palette, because as mentioned, we don't care about color space for masks.
*/
Bitmap original = new Bitmap(fileStream);
fileStream.Close();
Bitmap result = new Bitmap(original.Width, original.Height, PixelFormat.Format8bppIndexed);
BitmapData data = result.LockBits(new System.Drawing.Rectangle(0, 0, result.Width, result.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
byte[] bytes = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
// Convert all pixels to grayscale
for (int y = 0; y < original.Height; y++)
{
for (int x = 0; x < original.Width; x++)
{
var c = original.GetPixel(x, y);
var rgb = (byte) ((c.R + c.G + c.B) / 3);
bytes[y * data.Stride + x] = rgb;
}
}
Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
result.UnlockBits(data);
using (var stream = new MemoryStream())
{
result.Save(stream, ImageFormat.Png);
return ImageDataFactory.Create(stream.ToArray());
}
}
}
}