How to Find the Image That is not Found on Ios - xamarin.ios

I'm getting the error below when I reopen the application to see the image:
Could not initialize an instance of the type 'UIKit.UIImage': the native 'initWithContentsOfFile:' method returned nil
Is it possible to ignore this condition by setting
MonoTouch.ObjCRuntime.Class.ThrowOnInitFailure
to false?
Below method is used to displaying the image
private async Task DisplayImageFromImageUrl()
{
UIImage image;
image = new UIImage(eventImageEntity.EventsImageUrl);
}
while executing the above code "image" showing "null" value.

If your trying to create an image from a URL, you need to use the following code:
if (!string.IsNullOrEmpty(eventImageEntity.EventsImageUrl.Trim()))
{
var url = new NSUrl(eventImageEntity.EventsImageUrl);
using (var data = NSData.FromUrl(url))
{
UIImage image = UIImage.LoadFromData(data);
}
}
Otherwise you will just end up with a Null UIImage. That is what's causing your problem.
EDIT:
If you're trying to get the image from a resource location, then the following is necessary:
This assumes that it's from a specific user created folder:
UIImage image = UIImage.FromFile(#"Assets/NavigationBarAssets/HomePC.png")
OR
This assumes that the image is just say in the root of iOS 'Resources' folder
UIImage image = new UIImage("HomePC.png")

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.

Accessing Local Resource (local directory- outside project) in Vaadin 14/RapidclipseX IMG component

How to access the local image file from my hard drive (outside project folder) in the image component (to make an image gallery)? How to write the path of the file? in Vaadin 14/RapidclipseX.
It only takes either path from the project or URL. In my project users have to upload the images and I want to make a gallery that will show the images.
I tried all the below way but didn't work:
D:\\Canavans\\Reports\\256456\\424599_320943657950832_475095338_n.jpg
D:\Canavans\Reports\256456\424599_320943657950832_475095338_n.jpg
code (Tried this way as well):
for(final File file: files)
{
System.out.println(file.getName());
this.log.info(file.getName());
this.log.info(file.getAbsolutePath());
final String path = "file:\\\\" + file.getAbsolutePath().replace("\\", "\\\\");
this.log.info(path);
final Image img = new Image();
img.setWidth("300px");
img.setHeight("300px");
img.setSrc("file:\\\\D:\\\\Canavans\\\\Reports\\\\256456\\\\IMG20171002142508.jpg");
this.flexLayout.add(img);
}
Please Help! Thanks in advance. Or is there any other way to create an image gallery?
Hmm as far as I know if you want to access resources outside the resource folder you can create a StreamResource and initialize the image with that. If you want to use the images "src" property then the file has to be inside one of Vaadin's resource folders (for example the 'webapp' folder).
Here is a simple example on how to create the image with a StreamResource:
final StreamResource imageResource = new StreamResource("MyResourceName", () -> {
try
{
return new FileInputStream(new File("C:\\Users\\Test\\Desktop\\test.png"));
}
catch(final FileNotFoundException e)
{
e.printStackTrace();
return null;
}
});
this.add(new Image(imageResource, "Couldn't load image :("));
Hope this helps :)

How to set a custom store URL for NSPersistentContainer

How can I set a custom store.sqlite URL to NSPersistentContainer?
I have found an ugly way, subclassing NSPersistentContainer:
final public class PersistentContainer: NSPersistentContainer {
private static var customUrl: URL?
public init(name: String, managedObjectModel model: NSManagedObjectModel, customStoreDirectory baseUrl:URL?) {
super.init(name: name, managedObjectModel: model)
PersistentContainer.customUrl = baseUrl
}
override public class func defaultDirectoryURL() -> URL {
return (customUrl != nil) ? customUrl! : super.defaultDirectoryURL()
}
}
Is there a nice way?
Background: I need to save to an App Groups shared directory.
You do this with the NSPersistentStoreDescription class. It has an initializer which you can use to provide a file URL where the persistent store file should go.
let description = NSPersistentStoreDescription(url: myURL)
Then, use NSPersistentContainer's persistentStoreDescriptions attribute to tell it to use this custom location.
container.persistentStoreDescriptions = [description]
Note: myURL must provide the complete /path/to/model.sqlite, even if it does not exist yet. It will not work to set the parent directory only.
Expanding on Tom's answer, when you use NSPersistentStoreDescription for any purpose, be sure to init with NSPersistentStoreDescription(url:) because in my experience if you use the basic initializer NSPersistentStoreDescription() and loadPersistentStores() based on that description, it will overwrite the existing persistent store and all its data the next time you build and run. Here's the code I use for setting the URL and description:
let container = NSPersistentContainer(name: "MyApp")
let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
// or
let storeDirectory = NSPersistentContainer.defaultDirectoryURL()
let url = storeDirectory.appendingPathComponent("MyApp.sqlite")
let description = NSPersistentStoreDescription(url: url)
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { (storeDescription, error) in
if let error = error as? NSError {
print("Unresolved error: \(error), \(error.userInfo)")
}
}
I just find out that the location of db created by PersistentContainer is different from db created by UIManagedDocument. Here is a snapshot of db location by UIManagedDocument:
and the following codes are used to create the db:
let fileURL = db.fileURL // url to ".../Documents/defaultDatabase"
let fileExist = FileManager.default.fileExists(atPath: fileURL.path)
if fileExist {
let state = db.documentState
if state.contains(UIDocumentState.closed) {
db.open()
}
} else {
// Create database
db.save(to: fileURL, for:.forCreating)
}
It looks like that the db referred by PersistentContainer is actually the file further down under folder "StoreContent" as "persistentStore"
This may explain why the db "defaultDatabase" in my case cannot be created by PersistentContainer if you want to specify your customized db file, or causing crash since folder already existed. I further verified this by appending a file name "MyDb.sqlite" like this:
let url = db.fileURL.appendingPathComponent("MyDb.sqlite")
let storeDesription = NSPersistentStoreDescription(url: url)
container.persistentStoreDescriptions = [storeDesription]
print("store description \(container.persistentStoreDescriptions)"
// store description [<NSPersistentStoreDescription: 0x60000005cc50> (type: SQLite, url: file:///Users/.../Documents/defaultDatabase/MyDb.sqlite)
container.loadPersistentStores() { ... }
Here is the new MyDb.sqlite:
Based on the above analysis, if you have codes like this:
if #available(iOS 10.0, *) {
// load db by using PersistentContainer
...
} else {
// Fallback on UIManagedDocument method to load db
...
}
Users' device may be on iOS pre 10.0 and later be updated to 10+. For this change, I think that the url has to be adjusted to avoid either crash or creating a new(empty) db (losing data).
This is the code that I use to initialize a pre-populated sqlite db that works consistently. Assuming you will use this db as read only then there is no need to copy it to the Documents dir on the device.
let repoName = "MyPrepopulatedDB"
let container = NSPersistentContainer(name: repoName)
let urlStr = Bundle.main.path(forResource: "MyPrepopulatedDB", ofType: "sqlite")
let url = URL(fileURLWithPath: urlStr!)
let persistentStoreDescription = NSPersistentStoreDescription(url: url)
persistentStoreDescription.setOption(NSString("true"), forKey: NSReadOnlyPersistentStoreOption)
container.persistentStoreDescriptions = [persistentStoreDescription]
container.loadPersistentStores(completionHandler: { description, error in
if let error = error {
os_log("ERROR: Failed to initialize persistent store, error is \(error.localizedDescription)")
} else {
os_log("Successfully loaded persistent store, \(description)")
}
})
Some very important steps/items to keep in mind:
when constructing the URL to the sqlite file use the URL(fileURLWithPath:) form of the initializer. It seems that core data requires file based URLs, otherwise you will get an error.
I used a unit test to run some code in order to create/pre-populate the db in the simulator.
I located the full path to the sqlite file by adding a print statement inside the completion block of loadPersistentStores(). The description parameter of this block contains the full path to the sqlite file.
Then using Finder you can copy/paste that file in the app project.
At the same location as the sqlite file there are two other files (.sqlite-shm & .sqlite-wal). Add these two to the project also (in the same directory as the sqlite file). Without them core data throws an error.
Set the NSReadOnlyPersistentStoreOption in persistentStoreDescription (as shown above). Without this you get a warning (possible future fatal error).

IText, batik and vaadin charts scales wrong on linux

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.

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.

Resources