pdfbox showText width and height setting - fabricjs

I am creating web based app where you annotate a pdf at browser(using pdf.js and fabricjs) and save the annotations at server side (java servlet REST endpoint) using Apache pdfbox (2.0.x). I can overlay images and text using PDPageContentStream's drawImage and showText methods. Also the user may scale the annotations at browser by selecting and dragging it at corners. This is properly scaled for drawImage by adjusting the width parameter based on the scaleX factor set by fabricjs. But for showText I cannot find any options to scale the text. I can adjust the font size, but that won't translate correctly against the corner.
Any thoughts on how to scale (or change height and width) and put a text on pdf using showText method of PDPageContentStream
Thanks in advance
Prem
PDPageContentStream contentStream = new PDPageContentStream(doc, page, AppendMode.APPEND, true, true);
scaleX = signObj.get("scaleX").getAsFloat();
scaleY = signObj.get("scaleY").getAsFloat();
annoType = signObjWrapper.get("annoType").getAsInt();
float x_adjusted = (signObj.get("left").getAsFloat()) + page.getCropBox().getLowerLeftX();
float y_adjusted = -(signObj.get("top").getAsFloat()) + page.getCropBox().getUpperRightY();
if (annoType == SIGN) // this annotation is a sign object
{
contentStream.drawImage(pdImage, x_adjusted,
y_adjusted - (signObj.get("height").getAsFloat() * scaleY),
signObj.get("width").getAsFloat() * scaleX, signObj.get("height").getAsFloat() * scaleY);
contentStream.close();
} else if (annoType == TEXT) {
//Begin the Content stream
contentStream.beginText();
//Setting the font to the Content stream
contentStream.setFont(PDType1Font.COURIER,signObj.get("fontSize").getAsInt());
//Setting the position for the line
contentStream.newLineAtOffset(x_adjusted, y_adjusted - (signObj.get("height").getAsFloat() * scaleY));
//Adding text in the form of string
contentStream.showText(signObj.get("text").getAsString());
//Ending the content stream
contentStream.endText();
//Closing the content stream
contentStream.close();
}

Related

How to place image on right corner of pdf using node js?

I have one pdf file and one image file which is the signature of the client. I need to place the client signature image on the top right corner of every page of pdf. This whole process is in node js so I have used the pdf-lib npm package to attach image on pdf. The current issue I'm unable to place the image on the top-right corner.
Below is the logic which I used to set an image on the top-right corner of the pdf but this logic is not true for every case in some cases when the width of the image or pdf changes then it's not worked as expected. Sometimes images are getting too much small or sometimes too much large.Just because I set fix height and width. As I don't know how to calculate it dynamically
const pages = pdfDoc.getPages();
for (let i = 0; i < pdfDoc.getPageCount(); i++) {
let imagePage='';
imagePage = pdfDoc.getPage(i);
console.log(i+1)
console.log(imagePage.getWidth())
let xx=imagePage.getWidth()
console.log(imagePage.getHeight())
console.log(img.width)
console.log(img.height)
let yy=imagePage.getHeight()
imagePage.drawImage(img, {
x: xx-150,
y: yy-70,
width: 70,
height: 70
})
}
Please check console values below
595.5 ​​​​​at ​​​​​​​​imagePage.getWidth()​​​
842.2499787 ​​​​​at ​​​​​​​​imagePage.getHeight()​​​
1200 ​​​​​at ​​​​​​​​img.width​​​
700 ​​​​​at ​​​​​​​​img.height
please check the above image where I attached the signature to pdf but in this case, the signature image is not properly visible so how can I set the image to pdf on the top-right corner?
How can I calculate the x and y position dynamically for any pdf?
I got the solution to get dynamic x and y values to set an image on the top-right corner of the pdf
let xx=imagePage.getWidth();
console.log(imagePage.getHeight());
console.log("[PAGE_HEIGHT]",imagePage.getHeight());
const imgHeight = img.height;
const imgWidth = img.width;
console.log("[SIGNATURE_IMAGE_WIDTH]",img.width);
console.log("[SIGNATURE_IMAGE_HEIGHT]",img.height);
const marginX = 50;
let yy=imagePage.getHeight();
imagePage.drawImage(img, {
x: xx -marginX-imgWidth,
y: yy- marginX-imgHeight,
width: imgWidth,
height: imgHeight
})
margin is a fixed value to move an image from the top and right sides to get a proper view.
I have removed image height and width from the actual page width and height that will return top right corner.

Resize canvas using fabric.js lanczos filter

I am a fabric.js novice, I have got through a great deal of documentation and code samples, but still can't figure out how can I achieve such simple goal.
I start from a DOM canvas, and would like to obtain a downsized canvas, using the lanczos filter.
var canvas = /* a DOM canvas, obtained through prior processing */
var width = /* target width, smaller than source canvas width */
var height = /* target height, smaller than source canvas height */
I create the filter:
var filter = new fabric.Image.filters.Resize();
filter.resizeType = 'lanczos';
filter.LanczosLobes = 3;
I calculate the scaling:
var scalingX = width / canvas.width;
var scalingY = height / canvas.height;
Now it is not clear to me how can I apply the filter to the canvas, and get the downsized canvas.
Or could someone suggest another javascript library or function, as simple as possible, to perform a canvas-to-canvas lanczos downsize?

How to create zoomable text

I am looking to add zoomable text to the rendered image in OpenSeadragon. The desired functionality is that when you are zoomed out, the text is very small, and as you zoom in, the text increases in size.
I have tried to add text to an overlay div DOM element. This adds text, but as you zoom out, the size of the div gets smaller but the text doesn't. The text gets squeezed to multiple lines.
I use the Render2 class in Angular 7 to manipulate the DOM, but this can be done in any framework/library:
// create the DOM element need for SeaDragon's overlay
let div = this.renderer.createElement('div');
const text = this.renderer.createText(`x: ${xaxis}, y: ${yaxis}`);
// append text to div element
this.renderer.appendChild(div, text);
// add id for Seadragon overlay creation and styling of overlay
this.renderer.setAttribute(div, 'id', overlayname);
this.renderer.setAttribute(div, 'class', 'image-ruler');
// now append the div tag to ViewChild div
this.renderer.appendChild(this.singleOverlay.nativeElement, div);
I expect the text to zoom with the image. Is this possible?
I figured out how to do it. I saw this example that uses an svg plugin so d3 can be used to draw an overlay. After downloading this plugin, I noticed that when I printed text on the screen, it was incredibly large. Too large to read.
As d3 at this zoom level uses the scale of 0-1 for the size of the image, I had to divide the scale by the width of my image.
var p = viewer.viewport.pixelFromPoint(new OpenSeadragon.Point(0, 0), true);
var zoom = viewer.viewport.getZoom(true);
var rotation = viewer.viewport.getRotation();
var imageSize = viewer.world.getItemAt(0).getContentSize();
var scale = viewer.viewport._containerInnerSize.x * zoom / imageSize.x;
g.attr('transform',
'translate(' + p.x + ',' + p.y + ') scale(' + scale + ') rotate(' + rotation + ')');
I then reimplemented the plugin's resize function in my component as not to modify a node module. The result was small text on my enormous image that was readable when you zoom in.

How to find bit length of text with specific font and font size

I'm developing NativeScript JavaScript code to create dynamic text marker for maps. I have the code working that creates a marker for a specific string. My next step is to take any given string, determine its height and width in bits, and create the marker sized to contain the text.
My problem is finding the size of the text, given the text string itself, the font size, and the font family.
It looks like getMeasuredWidth could work, except that the string must already be loaded on a page before that function will return a value. In my case, I simply need to compute the size; the text won't otherwise appear as such on a page (the text in the marker becomes an image).
Is there a way to do this?
var bmp = BitmapFactory.create(200);
bmp.dispose(function (b) {
try {
b.drawRect(
"100,34", // size
'0,0', // upper-left coordinate
KnownColors.Black, // border color
KnownColors.Cornsilk // fill color
);
b.writeText(
"Parking",
"2,25",
{ color: KnownColors.Black, size: 8, name: 'fontawesome-webfont', });
...
In the code above, the width of "100" of the bounding rectangle actually represents the bit width of "Parking" with a small amount of padding. What I want to does calculate the rectangle's height and width and not hard-code it.
Try this, finding label size without adding it to Page upon button click
export function onFindButtonTap(args: EventData) {
const button = <any>args.object;
const label = new Label();
label.text = "Hello, found my size?"
label.fontSize = 20;
(<any>label)._setupAsRootView(button._context);
label.onLoaded();
label.measure(0, 0);
console.log(`Width : ${label.getMeasuredWidth()} x Height : ${label.getMeasuredHeight()}`);
}
Playground Sample
Note: I didn't get a chance to test it with iOS yet, let me know if you hit any issues.

Bitmap Image: cropping with portrait orientation

Adding camera functionality to my app is killing me! Started with the basic UWP camera sample, but I have to add zooming capability which added a ScrollViewer around the preview control and complicated my life. Found the cropping code in a different sample. Everything works in landscape, but when you rotate the tablet to portrait the cropped image (even without any actual cropping) is rotated 90.
The cropping logic takes originX/Y, ScrollViewer.ViewportWidth/Height & ScrollViewer.ExtentWidth/Height. I don't understand how these values change with the rotation! In Landscape I use topLeft for the X/Y. What would I do for Portrait? I'm setting the width to 400 and in both views it's STILL 400 so I don't believe width/height should be flipped.
Here's the cropping code. Can anyone comment on what should be different for the 2 (actually 4) orientations?
async public static Task<WriteableBitmap> GetCroppedBitmapAsync(StorageFile originalImageFile,
Point startPoint, Size cropSize, Size previewSize)
{
using (IRandomAccessStream stream = await originalImageFile.OpenReadAsync())
{
// Create a decoder from the stream. With the decoder, we can get the properties of the image.
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Adjust the start x/y to the stream size
uint scaledStartPointX = (uint)Math.Round((decoder.PixelWidth * (startPoint.X / previewSize.Width)));
uint scaledStartPointY = (uint)Math.Round((decoder.PixelHeight * (startPoint.Y / previewSize.Height)));
// Now get the scaled size of the viewport (ie the cropped area)
uint selectedAreaWidth = (uint)Math.Round(decoder.PixelWidth * (cropSize.Width / previewSize.Width));
uint selectedAreaHeight = (uint)Math.Round(decoder.PixelHeight * (cropSize.Height / previewSize.Height));
// Get the cropped pixels.
byte[] pixels = await GetPixelData(decoder, scaledStartPointX, scaledStartPointY, selectedAreaWidth, selectedAreaHeight,
decoder.PixelWidth, decoder.PixelHeight);
// Stream the bytes into a WriteableBitmap
WriteableBitmap cropBmp = new WriteableBitmap((int)selectedAreaWidth, (int)selectedAreaHeight);
Stream pixStream = cropBmp.PixelBuffer.AsStream();
pixStream.Write(pixels, 0, (int)(selectedAreaWidth * selectedAreaHeight * 4));
return cropBmp;
}
}

Resources