У меня есть мягкая маска на основе TransparencyGroup, как описано в 7.5.4 спецификации PDF. Это работает нормально, когда изображение, к которому я применяю маску, является JPG, но не работает, когда у него есть собственная маска, такая как PNG.
doc = new Document(new Rectangle(ToPdf(210), ToPdf(297)));
pdf = PdfWriter.GetInstance(doc, new FileStream("test.pdf", FileMode.Create));
pdf.PdfVersion = PdfWriter.VERSION_1_4;
pdf.CompressionLevel = PdfStream.NO_COMPRESSION;
doc.Open();
var dc = pdf.DirectContent;
dc.Rectangle(0, 0, ToPdf(210), ToPdf(297));
dc.SetColorFill(BaseColor.BLUE);
dc.Fill();
dc.SaveState();
var mask = Image.GetInstance("mask.jpg");
mask.ScaleAbsoluteHeight(ToPdf(100));
mask.ScaleAbsoluteWidth(ToPdf(100));
mask.SetAbsolutePosition(0, 0);
var transparency = dc.CreateTemplate(ToPdf(100), ToPdf(100));
transparency.Group = new PdfTransparencyGroupEx { ColorSpace = PdfName.DEVICEGRAY };
transparency.AddImage(mask);
var softmask = new PdfSoftMask(PdfName.MASK) {
Subtype = new PdfName("Luminosity"),
Group = transparency.IndirectReference,
};
dc.SetGState(new PdfGStateEx {
SoftMask = softmask,
AlphaIsShape = false,
});
var picture = Image.GetInstance("test.png"); // or test.jpg
//picture.Smask = false;
picture.ScaleAbsoluteHeight(ToPdf(100));
picture.ScaleAbsoluteWidth(ToPdf(100));
picture.SetAbsolutePosition(0, 0);
dc.AddImage(picture);
dc.RestoreState();
doc.Close();
Маска - это просто изображение в градациях серого с фонтанной заливкой:
При использовании PNG изображение будет отображаться с ошибочным фоном:
Помощники:
public static float ToPdf(double mm) => (float)(mm / 25.4 * 72.0);
public class PdfGStateEx : PdfGState {
public PdfObject SoftMask {
set => Put(PdfName.SMASK, value);
}
}
public class PdfTransparencyGroupEx : PdfTransparencyGroup {
public PdfName ColorSpace {
set => Put(PdfName.CS, value);
}
}
public class PdfSoftMask : PdfDictionary {
public PdfSoftMask(PdfName type)
: base(type) {
}
public PdfName Subtype {
set => Put(PdfName.S, value);
}
public PdfIndirectReference Group {
set => Put(new PdfName("G"), value);
}
public PdfArray BackdropColor {
set => Put(PdfName.BC, value);
}
}
Тестовые файлы
Некоторый анализ
во всех случаях изображение вставляется правильно:
/GS1 gs
q 283.46 0 0 283.46 0 0 cm /img1 Do Q
где словарь мягкой маски:
<<
/AIS false
/SMask
<<
/G 1 0 R
/S /Luminosity
/Type /Mask
>>
>>
ссылка на группу прозрачности XObject:
<<
/BBox [0 0 283.46 283.46]
/FormType 1
/Group
<<
/CS /DeviceGray
/S /Transparency
>>
/Length 38
/Matrix [1 0 0 1 0 0]
/Resources
<<
/XObject
<<
/img0 2 0 R
>>
>>
/Subtype /Form
/Type /XObject
>>
Никакой разницы пока нет. Одна из версий PNG фактически очищает запись SMask, после чего маска, присущая PNG, исчезает, чего и следовало ожидать.
Таким образом, это будет вероятным случаем, потому что мягкая маска изображения переопределит мягкую маску в графическом состоянии. Теперь вопрос сводится к следующему: есть ли в iText какая-либо поддержка для смешивания двух масок (одна из PNG, другая из моих собственных) или мне нужно сделать это отдельно перед подачей его в iText?