How to show an image from an image inputstream in Birt? - jfreechart

I am using birt to develop some reports,I want to display some pie charts in the birt pdf report,I found the birt chart function is not very flexiable,so I want to use jfreechart to generate an image and show it in the report instead. Now I have a question: can we show image in birt with the image inputstream,so that the image do not need to be generated and store in some place?
I know I can generate the image into a jpg file and store it in some place ,then I can access it birt report via the location of this image file.But if I do as that ,each time when we view the birt report ,it will generate a new image file,I do not want to generate so much files.
Any good ideas?

There are two possible solutions.
As you said, you can save the charts as files.
I do this in a report where I generate dozens of control charts (German: "Regelkarten"). To tidy up after the report has finished, I add the generated file names to a list, then I delete the files in the list in the report's afterRender script like this.
var images = vars["images"];
for (var i=0; i<images.size(); i++) {
var fname = images.get(i);
if (new java.io.File(fname)['delete']()) {
log.debug("Temp. image file removed: " + fname);
} else {
log.error("Could not delete temp. image file " + fname);
}
}
Note: This is OK for generating PDF or Word, but probably it wouldn't work for HTML.
In my case, I did this because I could check the generated charts outside of BIRT by just commenting out the clean up routine.
The other option is to generate a byte[]. BIRT complains in the log file then (Rhino, something about unknown type mapping Java<->Javascript), but it works.
I never have used this with JFreeChart, but that's how we do it for generating DataMatrix ("2D-Barcode") with an ancient commercial Java library from a company called "ID Automation".
The image item references row["dataMatrix_AuftID"], which is defined as type: Java Object, expression: barcode.dataMatrix(row["AUFT_ID"],70,70,80,0.03)
The function barcode.dataMatrix in our Javascript wrapper library for the Java library calls the Java library. Its last few lines look like this, which should give you an idea for your case:
var image = new java.awt.image.BufferedImage(siz.width, siz.height, t);
// get graphic context of image
var imgGraphics = image.createGraphics();
// paint DataMatrix in graphics context of image
bc.paint(imgGraphics);
// get the image's bytes in PNG format
var baos = new java.io.ByteArrayOutputStream();
javax.imageio.ImageIO.write(image, "png", baos);
var bytes = baos.toByteArray();
return bytes;
As a side-note, for a proof of concept I showed that it is also possible to generate SVG in memory and use it with BIRT. Never used this in production, however.

Related

Is there any way we can control the size of the image attached in testNG report?

I have been trying to capture Screenshots for Passed/Failed test in my testNG reports captured in Test-Output folder. I have succeeded in doing so, however I want a bit more improvement in the way things are right now.
The Screenshot is displayed in full size and covers the whole screen, I would like to make it appear smaller in report and then user can click on it to see the image maximized.
I am capturing the Screenshot with the help of Reporter.log(ScreenshotPath) in the static TakeScreenshot method which is a part of finally block in my test case.
public static void TakeScreenshotMethod() throws IOException {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
File ScreenshotName = new File(UtilityClass.ScreenshotPathCustomerPortal + count +".jpg");
FileUtils.copyFile(scrFile, ScreenshotName);
String filePath = ScreenshotName.toString();
String path = "<img src=\"file://" + filePath + "\" alt=\"\"/>";
Reporter.log(path);
count++;
}
I would like to control the size of the image being displayed in my report.
You can a bit modify the <img> tag by adding a style like normal html with some property (width, height), like this:
String path = "<img src=\"file://" + filePath + "\" alt=\"\" style=\"width: 230px; height :500px;\" />";
If you are asking for this behavior in the default TestNG reports, then the answer is NO its not possible. TestNG reports are agnostic to the content that gets embedded in them. So TestNG doesn't know if an image or if a video for that matter is being embedded in it. So it also doesn't different on how to get them rendered.
If you would like to control these behaviors, you should do one of the following:
Build your own custom reporter that has this behavior by implementing the org.testng.IReporter interface and then wiring in this listener via the <listeners> tag or via #Listeners interface or via a Service Provider Interface mechanism. You can learn about wiring in listeners in general from my blog post here.
You can explore some of the reporting solutions that exist already out there such as allure reports (or) extent reports etc., and see if one of them fits your requirement and use them instead.
TestNG doesn't have any role to play in this.

How do I asynchronously display and save bitonal Tiff images in Silverlight?

Our company has an application that receives bitonal TIFF images via fax or scanner and saves them to a database; currently, we display the images from the database using an ActiveX control, but now we want to use a Silverlight control to display those images instead. However, we are not able to display or save the images as bitonal TIFF images; using the following code in our ashx handler, we get a blank image:
pageno = Convert.ToInt32(context.Request.QueryString("page"))
'Get image data from database
Dim bmp() As Byte = ShowDocumentImage(documentID)
'Get current page of TIFF image as bitmap
Dim newBmp As Bitmap = GetTifPage(bmp, pageno)
Dim info As Imaging.ImageCodecInfo = Nothing
Dim ice As Imaging.ImageCodecInfo
For Each ice In Imaging.ImageCodecInfo.GetImageEncoders()
If ice.MimeType = "image/tiff" Then
info = ice
End If
Next
Dim enc As Imaging.Encoder = Imaging.Encoder.SaveFlag
Dim ep As New Imaging.EncoderParameters(2)
ep.Param(0) = New Imaging.EncoderParameter(enc, CLng(Imaging.EncoderValue.MultiFrame))
ep.Param(1) = New Imaging.EncoderParameter(enc, CLng(Imaging.EncoderValue.CompressionCCITT4))
If newBmp IsNot Nothing Then
newBmp.Save(context.Response.OutputStream, info, ep)
newBmp.Dispose()
End If
Instead, we have to save them as JPEG, which does display to the user but which also increases the bit depth and the size of the files; it also increases the time it takes to save the image. It takes about 6 seconds to convert a 1728x2079 JPEG to a byte array so that it can be uploaded to the database.
Is there a way to display and save the image as a bitonal TIFF, and/or a faster way to convert the image to a byte array?
As far as I know, support for TIFF images in Silverlight is very limited.
There are 3-rd party libraries that can help you with your task. I am personally recommend you to try LibTiff.Net library. The library is completely free (even for commercial use) and open source.
Source code package of LibTiff.Net contains Silverlight Test Application that shows how to asynchronously load and display TIFF images in a Silverlight app. It can display various TIFF flavors including bitonal ones.
You might find this answer to a similar question useful too.

Creating XPS in WPF - used image files are being locked until my app quits

In my WPF app, I am creating a FlowDocument by building its XAML markup as a string, and then using XamlReader.Parse to turn the string into a FlowDocument object, which I then save to an XPS document file. It works.
I needed to include an image in my document, and so to achieve this, I create and save the image as a temporary file in the temp directory, and then reference it with an absolute path in my FlowDocument's XAML. This works too - during the XPS document creation process, the image actually gets embedded into the XPS document, which is great.
But the problem is, my app retains a file lock on this image until the app quits.
I am cleaning up all resources. There is NO file lock on my generated XPS file - just the image file. If I comment out the part of my code which creates the XPS file, then the image file does not get locked.
My code (I'm on .NET 4 CP):
var xamlBuilder = new StringBuilder();
// many lines of code like this
xamlBuilder.Append(...);
// create and save image file
// THE IMAGE AT THE PATH imageFilePath IS GETTING LOCKED
// AFTER CREATING THE XPS FILE
var fileName = string.Concat(Guid.NewGuid().ToString(), ".png");
var imageFilePath = string.Format("{0}{1}", Path.GetTempPath(), fileName);
using (var stream = new FileStream(imageFilePath, FileMode.Create)) {
var encoder = new PngBitmapEncoder();
using (var ms = new MemoryStream(myBinaryImageData)) {
encoder.Frames.Add(BitmapFrame.Create(ms));
encoder.Save(stream);
}
stream.Close();
}
// add the image to the document by absolute path
xamlBuilder.AppendFormat("<Paragraph><Image Source=\"{0}\" ...", imageFilePath);
// more lines like this
xamlBuilder.Append(...);
// create a FlowDocument from the built string
var document = (FlowDocument) XamlReader.Parse(xamlBuilder.ToString());
// set document settings
document.PageWidth = ...;
...
// save to XPS file
// THE XPS FILE IS NOT LOCKED. IF I LEAVE OUT THIS CODE
// AND DO NOT CREATE THE XPS FILE, THEN THE IMAGE IS NOT LOCKED AT ALL
using (var xpsDocument = new XpsDocument(filePath, FileAccess.ReadWrite)) {
var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
documentWriter.Write(((IDocumentPaginatorSource) document).DocumentPaginator);
xpsDocument.Close();
}
(Actually, the fact that's it's a dynamically generated image in the temp directory is irrelevant - this issue occurs if I hard code in the path of any image file on my machine - it will get locked.)
One would think that there is a bug in the XPS creation code that causes the file lock.
Is there something else I can try? Or a way to remove the file lock via code?
You could change your xaml like this instead:
<Image>
<Image.Source>
<BitmapImage CacheOption="None" UriSource="your path" />
</Image.Source>
</Image>
to be able to play with the CacheOption parameter, to specify how the Xaml Builder should load the image file, as the default value seems to be keeping a lock on it (waiting for the GC to do its work it seems).
Here is some related question here on SO: How do you make sure WPF releases large BitmapSource from Memory?

Silverlight: Business Application Needs Access To Files To Print and Move

I have the following requirement for a business application:
(All of this could be on local or server)
Allow user to select folder location
Show contents of folder
Print selected items from folder (*.pdf)
Display which files have been printed
Potentially move printed files to new location (sub-folder of printed)
How can I make this happen in Silverlight?
Kind regards,
ribald
First of all, all but the last item can be done (the way you expect). Due to security protocols, silverlight cannot access the user's drive and manipulate it. The closest you can get is accessing silverlight's application storage which will be of no help to you whatsoever in this case. I will highlight how to do the first 4 items.
Allow user to select folder location & Show contents of folder
public void OnSelectPDF(object sender)
{
//create the open file dialog
OpenFileDialog ofg = new OpenFileDialog();
//filter to show only pdf files
ofg.Filter = "PDF Files|*.pdf";
ofg.ShowDialog();
byte[] _import_file = new byte[0];
//once a file is selected proceed
if (!object.ReferenceEquals(ofg.File, null))
{
try
{
fs = ofg.File.OpenRead();
_import_file = new byte[fs.Length];
fs.Read(_import_file, 0, (int)fs.Length);
}
catch (Exception ex)
{
}
finally
{
if (!object.ReferenceEquals(fs, null))
fs.Close();
}
//do stuff with file - such as upload the file to the server
};
}
If you noticed, in my example, once the file is retrieved, i suggest uploading it to a webserver or somewhere with temporary public access. I would recommend doing this via a web service. E.g
//configure the system file (customn class)
TSystemFile objFile = new TNetworkFile().Initialize();
//get the file description from the Open File Dialog (ofg)
objFile.Description = ofg.File.Extension.Contains(".") ? ofg.File.Extension : "." + ofg.File.Extension;
objFile.FileData = _import_file;
objFile.FileName = ofg.File.Name;
//upload the file
MasterService.ToolingInterface.UploadTemporaryFileAsync(objFile);
Once this file is uploaded, on the async result, most likely returning the temporary file name and upload location, I would foward the call to some javascript method in the browser for it to use the generic "download.aspx?fileName=givenFileName" technique to force a download on the users system which would take care of both saving to a new location and printing. Which is what your are seeking.
Example of the javascript technique (remember to include System.Windows.Browser):
public void OnInvokeDownload(string _destination)
{
//call the browser method/jquery method
//(I use constants to centralize the names of the respective browser methods)
try
{
HtmlWindow window = HtmlPage.Window;
//where BM_INVOKE_DOWNLOAD is something like "invokeDownload"
window.Invoke(Constants.TBrowserMethods.BM_INVOKE_DOWNLOAD, new object[] { _destination});
}
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }
}
Ensure you have the javascript method existing either in an included javaScript file or in the same hosting page as your silverlight app. E.g:
function invokeDownload(_destination) {
//some fancy jquery or just the traditional document.location change here
//open a popup window to http://www.myurl.com/downloads/download.aspx? fileName=_destination
}
The code for download.aspx is outside the scope of my answer, as it varies per need and would just lengthen this post (A LOT MORE). But from what I've given, it will "work" for what you're looking for, but maybe not in exactly the way you expected. However, remember that this is primarily due to silverlight restrictions. What this approach does is rather than forcing you to need a pluging to view pdf files in your app, it allows the user computer to play it's part by using the existing adobe pdf reader. In silverlight, most printing, at least to my knowledge is done my using what you call and "ImageVisual" which is a UIElement. To print a pdf directly from silverlight, you need to either be viewing that PDF in a silverlight control, or ask a web service to render the PDF as an image and then place that image in a control. Only then could you print directly. I presented this approach as a lot more clean and direct approach.
One note - with the temp directory, i would recommend doing a clean up by some timespan of the files on the server side everytime a file is being added. Saves you the work of running some task periodically to check the folder and remove old files. ;)

Converting byte[] of a PDF file original source to MemoryStream for loading into PDF viewer? (component one)

I'm working with a ComponentOne (C1) silverlight PDF viewer control.
It has a "LoadDocument" method that accepts a "Stream".
I'm making an HTTP get call from my client app to get a PDF document.
This document, on the server side, has been streamed in through File.ReadAllBytes(), then converted to a base64 string using Convert.ToBase64String().
This string is sent across the wire back to my silverlight app where it's then reversely converted back into a byte array with Convert.FromBase64String(val).
Then I'm creating a MemoryStream with that byte array and passing "LoadDocument()" that memory stream.
The viewer is rendering nothing. It shows the toolbar and scrollbars, but the contents are blank and the save button is grayed out, suggesting that no document loaded.
I know for certain the file made it across because the byte array size on the client matches teh byte array pre-conversion on the server side.
Here's my code: (in the interest of time/space, i've truncated, removing validation, etc.)
SERVERSIDE
string sendingToClient = Convert.ToBase64String(File.ReadAllBytes(filePath))
CLIENTSIDE
byte[] image = null;
image = Convert.FromBase64String(stringFromServerCall);
MemoryStream stream = new MemoryStream(image);
docViewer.LoadDocument(stream);
edit As a potential workaround, I attempted to save the file into isolated storage with a ".pdf" extension. Then I use the IsolatedStorageFileStream to send to LoadDocument().
I've come to an actual error, it now says "PdfParserException was unhandled by user code: invalid file format (missing pdf header)"
Can anyone shed some light on this PDF header?
Here is an experiment I would conduct.
Add a button to your Xaml and on click use OpenFileDialog to get a FileInfo. From that FileInfo use its Open method to get a stream and pass that to docViewer.LoadDocument.
Now run it, click the button and select the same PDF document you are trying to send from the server.
If that succeeds you need to continue investigating your server streaming strategy. On the other hand if you still have the same problem, well it doesn't get more raw than that. Try other PDF files and start investigating the PDF component. Have you ever actually used it successfully, if so how does this current usage differ.
you should get the stream pointer back to 0 ,so this should do the trick
byte[] image = null;
image = Convert.FromBase64String(stringFromServerCall);
MemoryStream stream = new MemoryStream(image);
stream.Position = 0;
docViewer.LoadDocument(stream);

Resources