IText, batik and vaadin charts scales wrong on linux - svg

I've been having some trouble getting my charts out to PDF.
Recently i posted this: Generating PDF with iText and batik which was solved as suggested with some tweaking to the scales.
I run amy testenviroment on a local glassfishserver on a windows 10 machine, and when I export to PDF I actually get a pretty result now.
But when I pushed the results to the RHEL server, the results differed. The charts shown on the website is great, but when I export to pdf, I get this:
As you can see, the title is pushed down, for some reason the Y-axis with labels are cropped, and the data-labels are squished together. I've tried playing around with different scales, with and without scaletofit, scaletoabsolute and so on, but no matter what I do, it keeps doing that weird thing.
Does anybody has any idea whats going on - and even better, how to fix it? I've doublechecked that phantomjs is the same version, to make sure the SVG is the right one-.
The code is as follows:
private Image createSvgImage(PdfContentByte contentByte, Chart chart) throws IOException {
Configuration configuration = chart.getConfiguration();
configuration.setExporting(false);
SVGGenerator generator = SVGGenerator.getInstance();
generator.withHeigth(600);
generator.withWidth(1200);
String svg = generator.generate(configuration);
Image image = drawUnscaledSvg(contentByte, svg);
image.scaleToFit(800, 370);
configuration.setExporting(true);
return image;
}
private Image drawUnscaledSvg(PdfContentByte contentByte, String svgStr) throws IOException {
GraphicsNode imageGraphics = buildBatikGraphicsNode(svgStr);
float width = 1200;
float height = 600;
PdfTemplate template = contentByte.createTemplate(width, height);
Graphics2D graphics = template.createGraphics(width, height);
try {
imageGraphics.paint(graphics);
graphics.translate(-10, -10);
return new ImgTemplate(template);
} catch (BadElementException e) {
throw new RuntimeException("Couldn't generate PDF from SVG", e);
} finally {
graphics.dispose();
}
}
private GraphicsNode buildBatikGraphicsNode(String svgStr) throws IOException {
UserAgent agent = new UserAgentAdapter();
SVGDocument svgdoc = createSVGDocument(svgStr, agent);
DocumentLoader loader = new DocumentLoader(agent);
BridgeContext bridgeContext = new BridgeContext(agent, loader);
bridgeContext.setDynamicState(BridgeContext.STATIC);
GVTBuilder builder = new GVTBuilder();
GraphicsNode imageGraphics = builder.build(bridgeContext, svgdoc);
return imageGraphics;
}
private SVGDocument createSVGDocument(String svg, UserAgent agent)
throws IOException {
SVGDocumentFactory documentFactory = new SAXSVGDocumentFactory(
agent.getXMLParserClassName(), true);
SVGDocument svgdoc = documentFactory.createSVGDocument(null,
new StringReader(svg));
return svgdoc;
}
UPDATE I've tried reading a SVG file from disk, that I knew was correct, and that is put correctly within the PDF. So the problem lies somewhere within the SVG Generator. Anyone knows about this?

Using an older version of PhantomJS (1.9.8) fixes the problem.
I've made a ticket with Vaadin.

Related

Need to dispaly svg on an image in Xamarin

I have an url that gets team logos but it returns svg https://www.mlbstatic.com/team-logos/141.svg.
How can i display this in a Image for xamarin forms?
Searched and only found complex huge amounts of code.
looking for
Download image -- I have this but what do i need to save it in GetResponsestream preferrable i would like to stay in memory and not write to disk or file.
Attach it to an image to display.
Thanks.
Ok, thought i would post my solution here.
I used SkiSharp:
SkiaSharp.Extended.Svg.SKSvg svg = new SkiaSharp.Extended.Svg.SKSvg();
using (WebClient client = new WebClient())
{
// ie for theurl: https://www.mlbstatic.com/team-logos/141.svg
svg.Load(new MemoryStream(client.DownloadData(new Uri(theurl))));
var bitmap = new SKBitmap((int)svg.CanvasSize.Width, (int)svg.CanvasSize.Height);
var canvas = new SKCanvas(bitmap);
canvas.DrawPicture(svg.Picture);
canvas.Flush();
canvas.Save();
string filename = "";
using (var image = SKImage.FromBitmap(bitmap))
using (var data = image.Encode(SKEncodedImageFormat.Png, 80))
{
// save the data to a stream
filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp.png");
using (var stream = File.OpenWrite(filename ))
{
data.SaveTo(stream);
}
}
}
use FileName from above to assign source to Xamarin image.
this accomplished the task with the least amount of code lines i tried.

Rendering a ID3D11Texture2D into a SkImage (Skia)

I'm currently trying to create an interop layer to render my render target texture into a Skia SkImage. This is being done to facilitate rendering from my graphics API into Avalonia.
I've managed to piece together enough code to get everything running without any errors (at least, none that I can see), but when I draw the SkImage I see nothing but a black image.
Of course, these things are easier to describe with code:
private EglPlatformOpenGlInterface _platform;
private AngleWin32EglDisplay _angleDisplay;
private readonly int[] _glTexHandle = new int[1];
IDrawingContextImpl context // <-- From Avalonia
_platform = (EglPlatformOpenGlInterface)platform;
_angleDisplay = (AngleWin32EglDisplay)_platform.Display;
IntPtr d3dDevicePtr = _angleDisplay.GetDirect3DDevice();
// Device5 is from SharpDX.
_d3dDevice = new Device5(d3dDevicePtr);
// Texture.GetSharedHandle() is the shared handle of my render target.
_eglTarget = _d3dDevice.OpenSharedResource<Texture2D>(_target.Texture.GetSharedHandle());
// WrapDirect3D11Texture calls eglCreatePbufferFromClientBuffer.
_glSurface = _angleDisplay.WrapDirect3D11Texture(_platform, _eglTarget.NativePointer);
using (_platform.PrimaryEglContext.MakeCurrent())
{
_platform.PrimaryEglContext.GlInterface.GenTextures(1, _glTexHandle);
}
var fbInfo = new GRGlTextureInfo(GlConsts.GL_TEXTURE_2D, (uint)_glTexHandle[0], GlConsts.GL_RGBA8);
_backendTarget = new GRBackendTexture(_target.Width, _target.Height, false, fbInfo);
using (_platform.PrimaryEglContext.MakeCurrent())
{
// Here's where we find the gl surface to our texture object apparently.
_platform.PrimaryEglContext.GlInterface.BindTexture(GlConsts.GL_TEXTURE_2D, _glTexHandle[0]);
EglBindTexImage(_angleDisplay.Handle, _glSurface.DangerousGetHandle(), EglConsts.EGL_BACK_BUFFER);
_platform.PrimaryEglContext.GlInterface.BindTexture(GlConsts.GL_TEXTURE_2D, 0);
}
// context is a GRContext
_skiaSurface = SKImage.FromTexture(context, _backendTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888, SKAlphaType.Premul);
// This clears my render target (obviously). I should be seeing this when I draw the image right?
_target.Clear(GorgonColor.CornFlowerBlue);
canvas.DrawImage(_skiaSurface, new SKPoint(320, 240));
So, as far as I can tell, this should be working. But as I said before, it's only showing me a black image. It's supposed to be cornflower blue. I've tried calling Flush on the ID3D11DeviceContext, but I'm still getting the black image.
Anyone have any idea what I could be doing wrong?

GET TEXT FROM IMAGE EMBEDDED IN A .docx FILE USING TIKA

I've been working on Text Extractor that works on .docx file using Tika. And it is working file for basic text and text in tables and textboxes, but it fails for images.
How do I get text from Image, tesseract along with tika can be used to get text from an image alone but for that I would need to extract out the image from document. How do I do this?
Kindly help if anybody has worked upon something like this.
This the code that works fine for text, textbox and tables,but not for images:
public class BasicDocumentExtractor {
public static void main(final String[] args) throws IOException,SAXException, TikaException {
//detecting the file type
BodyContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata();
FileInputStream inputstream=new FileInputStream(new File("D:\\Nidhi\\sw\\ws\\Hello.docx"));
ParseContext pcontext=new ParseContext();
//OOXml parser
OOXMLParser msofficeparser=new OOXMLParser ();
msofficeparser.parse(inputstream, handler,metadata,pcontext);
System.out.println("Contents of the document:" +handler.toString());
/*System.out.println("Metadata of the document:");
String[] metadataNames = metadata.names();
for(String name : metadataNames){
System.out.println(name + ": " + metadata.get(name));
}*/
}
}
You need to enable recursion in Tika in order to get the embedded images. The simplest way is normally just to use the RecursiveParserWrapper to do it for you.
If you use it, your code would instead be roughly
BodyContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata();
TikaInputStream input = TikaInputStream.get(new File("D:\\Nidhi\\sw\\ws\\Hello.docx"));
Parser wrapped = new AutoDetectParser();
RecursiveParserWrapper wrapper = new RecursiveParserWrapper(wrapped,
new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, 60));
wrapper.parse(stream, handler, metadata, context);
// Get metadata from children
List<Metadata> list = wrapper.getMetadata();
// Get metadata from main document
System.out.println("Main doc name is " + metadata.get(TikaCoreProperties.TITLE));
System.out.println("Contents of the document:" +handler.String());
As I was trying really hard to do this since las 24hours, I figured out a way, a pretty easy one. Since, Tika is built on the top of POI, using POI this task can be efficiently executed. Also, it is not a direct solution so alomost no tutorials are available for this purpose, I hope nobody else has to face this issue in future. This is the running code that extracts all images from a .docx document:
public static void getImages() throws Exception {
XWPFDocument doc=new XWPFDocument(new FileInputStream("D:\\Nidhi\\CDAC\\Images\\test1.docx"));
List images=doc.getAllPictures();
int i =0;
while (i<images.size()) {
XWPFPictureData pic= (XWPFPictureData) images.get(i);
System.out.println(pic.getFileName() + " "+ pic.getPictureType() +" "+ pic.getData());
FileOutputStream fos=new FileOutputStream("D:\\Nidhi\\CDAC\\Images\\b" + i+".jpg");
fos.write(pic.getData());
i++;
}
}
Also, if it will work on all MS Office 2007+ files, for .doc and such files use HWPF in the exactly same manner.

WinXP Only Bitmap.Save ArgumentException Parameter Not Valid

Basically the code is trying to take a source image, draw some custom text on it and save the new image to the file system.
When I run the code in Windows 7, it runs fine, but when I run it in WinXP it creates an exception in the imgCopy.Save line anytime after the first DrawString.
The exception is ArgumentException (parameter is not valid). It's like the DrawString corrupts the image under WinXP...?
The build is for the x86/.NET 4.0 runtime. Any ideas why the exception under XP?
// imgSrc is actually passed into the method with the rec object
// this is just for repro
using (var imgSrc = new System.Drawing.Bitmap(rec.SrcFile))
using (var imgCopy = imgSrc.Clone() as Bitmap)
using (var gImg = Graphics.FromImage(imgCopy)) //shorten var names for this post
{
imgCopy.Save(rec.DstFile, ImageFormat.Jpeg); //Happy here
gImg.SmoothingMode = SmoothingMode.AntiAlias;
imgCopy.Save(rec.DstFile, ImageFormat.Jpeg); //Also no problem
gImg.DrawString(rec.Name, fntArial16, Brushes.Black, new Rectangle(170, 105, 650, 50), sfCenter);
imgCopy.Save(rec.DstFile, ImageFormat.Jpeg); //<-- Fails here
}
Edit: Code for the parameters:
private static Font fntArial16 = new Font("Arial", 16, FontStyle.Bold);
private static StringFormat _sfCenter;
private static StringFormat sfCenter {
get {
if (_sfCenter == null) {
_sfCenter = new StringFormat();
sfCenter.Alignment = StringAlignment.Center;
sfCenter.LineAlignment = StringAlignment.Center;
}
return _sfCenter;
}
}
We narrowed the problem down to the .jpg file containing XMP (Extensible Metadata Platform) data. Once we removed that from the file it worked on WinXP correctly. Unfortunately the tool that generated the file didn't have the option to exclude this, so we went with the .png file instead and that works fine as well.

Generate Screenshot From WebBrowser Control

I grabbed some code from the link below to generate a screenshot from a web browser control:
http://pietschsoft.com/post/2008/07/C-Generate-WebPage-Thumbmail-Screenshot-Image.aspx
Then, I modified to be an extension method like so:
public static Bitmap GetScreenshot(this WebBrowser webBrowser)
{
// Load the webpage into a WebBrowser control
using (WebBrowser wb = new WebBrowser())
{
wb.ScrollBarsEnabled = false;
wb.ScriptErrorsSuppressed = true;
wb.Navigate(webBrowser.Url);
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
// Set the size of the WebBrowser control
wb.Width = wb.Document.Body.ScrollRectangle.Width;
wb.Height = wb.Document.Body.ScrollRectangle.Height;
// Get a Bitmap representation of the webpage as it's rendered in the WebBrowser control
Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
return bitmap;
}
}
It works great for most web pages, but I am trying to use it for a SharePoint site and the image is coming out as 250x250 every time. :-s
Any geniuses here that can give me a solution?
Thanks in advance
Well, the reason for this seems to be that my new WebBrowser (wb) is uninitialized even after I call Navigate(). The Url property shows as null. This is weird. Does it mean I cannot create a WebBrowser in code and never display it? It would be a shame to have to display the thing. :-(
You can check that question taking-screenshot-of-a-webpage-programmatically.
It is based on this webpage_thumbnailer which uses Web Browser control.
For one, the DrawToBitmap class does not exist under the webbrowser control. I suggest using CopyFromScreen. Here is a code snippet:
Bitmap b = new Bitmap(wb.ClientSize.Width, webBrowser1.ClientSize.Height);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(this.PointToScreen(wb.Location), new Point(0, 0), wb.ClientSize);
//The bitmap is ready. Do whatever you please with it!
b.Save(#"c:\screenshot.jpg", ImageFormat.Jpeg);
MessageBox.Show("Screen Shot Saved!");

Resources