I am trying to replace an image stream within an SDF document, using PDFNet 7.0.4
and netcoreapp3.1
. As much as possible, I want to maintain the original object and its metadata; same dimensions, color system, compression, etc. Ideally object number and even generation would remain the same as well - the goal is that a before and after comparison would show only the changed pixels within the stream.
I'm getting the raw pixel data as a Stream
object with this method:
private Stream GetImageData(int objectNum)
{
var image = new PDF.Image(sdfDoc.GetObj(objectNum));
var bits = image.GetBitsPerComponent();
var channels = image.GetComponentNum();
var bytesPerChannel = bits / 8;
var height = image.GetImageHeight();
var width = image.GetImageWidth();
var data = image.GetImageData();
var len = height * width * channels * bytesPerChannel;
using (var reader = new pdftron.Filters.FilterReader(data))
{
var buffer = new byte[len];
reader.Read(buffer);
return new MemoryStream(buffer);
}
}
After manipulating the image data, I want to update it before saving the underlying SDFDoc
object. I've tried using the following method:
private void SetImageData(int objectNum, Stream stream)
{
var image = new PDF.Image(sdfDoc.GetObj(objectNum));
var bits = image.GetBitsPerComponent();
var channels = image.GetComponentNum();
var bytesPerChannel = bits / 8;
var height = image.GetImageHeight();
var width = image.GetImageWidth();
var len = height * width * channels * bytesPerChannel;
if (stream.Length != len) { throw new DataMisalignedException("Stream length does not match expected image dimensions"); }
using (var ms = new MemoryStream())
using (var writer = new pdftron.Filters.FilterWriter(image.GetImageData()))
{
stream.CopyTo(ms);
writer.WriteBuffer(ms.ToArray());
}
}
This runs without error, but nothing actually appears to get updated. I've tried playing around with SDFObj.SetStreamData()
, but haven't been able to make that work either. What is the lowest impact, highest performance way to directly replace just the raw pixel data within an image stream?
edit
I have this halfway working with this method:
private void SetImageData(int objectNum, Stream stream)
{
var sdfObj = sdfDoc.GetObj(objectNum);
var image = new PDF.Image(sdfObj);
var bits = image.GetBitsPerComponent();
var channels = image.GetComponentNum();
var bytesPerChannel = bits / 8;
var height = image.GetImageHeight();
var width = image.GetImageWidth();
var len = height * width * channels * bytesPerChannel;
if (stream.Length != len) { throw new DataMisalignedException("Stream length does not match expected image dimensions"); }
var buffer = new byte[len];
stream.Read(buffer, 0, len);
sdfObj.SetStreamData(buffer);
sdfObj.Erase("Filters");
}
This works as expected, but with the obvious caveat that it just ignores any existing compression and turns the image into a raw uncompressed stream.
I've tried sdfObj.SetStreamData(buffer, image.GetImageData());
and sdfObj.SetStreamData(buffer, image.GetImageData().GetAttachedFilter());
and this does update the object in the file, but the resulting image fails to render.