C# XNA 4.0 Exception: "Cannot Open File" - c#

I am working in XNA 4.0 Game Studio (C#), and I am trying to load an image using the LoadContent() method. I have loaded numerous image files into this game and they all work 100% fine, but for some reason, XNA will not open files inside one of my loadContent methods. Here is the method:
protected override void LoadContent()
{
//spriteBatch = new SpriteBatch(GraphicsDevice);
//Sets up an array of textures to be used in the Icon class
Texture2D[] icons = new Texture2D[24];
#region Loading talent textures
//These are all of the icons that need to be loaded for the talents
//Paladin
icons[0] = Content.Load<Texture2D>(#"C:\Users\Student\Desktop\Dropbox\Public\platformer\Platformer\Content\Talents\blade_of_light3.jpg");
icons[1] = Content.Load<Texture2D>("Talents\\divine_grace");
icons[2] = Content.Load<Texture2D>("Talents\\divine_storm");
icons[3] = Content.Load<Texture2D>("Talents\\hammer_of_the_righteous");
icons[4] = Content.Load<Texture2D>("Talents\\healing_hands");
icons[5] = Content.Load<Texture2D>("Talents\\heavenly_fury");
icons[6] = Content.Load<Texture2D>("Talents/momentum_of_light");
icons[7] = Content.Load<Texture2D>("Talents/retribution");
icons[8] = Content.Load<Texture2D>("Talents/righteous_fury");
icons[9] = Content.Load<Texture2D>("Talents/sanctuary");
icons[10] = Content.Load<Texture2D>("Talent/searing_light");
icons[11] = Content.Load<Texture2D>("Talent/wrath_of_the_heavens");
//Warrior
icons[12] = Content.Load<Texture2D>(#"Talents\bloodstorm");
icons[13] = Content.Load<Texture2D>(#"Talents\bloodthirst");
icons[14] = Content.Load<Texture2D>(#"Talents\die_by_the_sword");
icons[15] = Content.Load<Texture2D>(#"Talents\furious_blades");
icons[16] = Content.Load<Texture2D>(#"Talents\unleash_rage");
icons[17] = Content.Load<Texture2D>(#"Talents\lifeblood");
icons[18] = Content.Load<Texture2D>(#"Talents\red_like_my_rage");
icons[19] = Content.Load<Texture2D>(#"Talents\eternal_thirst");
icons[20] = Content.Load<Texture2D>(#"Talents\bladesurge");
icons[21] = Content.Load<Texture2D>(#"Talents\bathed_in_blood");
icons[22] = Content.Load<Texture2D>(#"Talents\bladerunner");
icons[23] = Content.Load<Texture2D>(#"Talents\bloodfury");
icons[24] = Content.Load<Texture2D>(#"Talents\grapple_chain");
#endregion
As you can see, I have tried using the ENTIRE file location. It finds the file, but throws an exception when the LoadContent() method is called and says "Cannot open file blade_of_light3."
I do not get any errors about escape paths or anything like that, and I have used this sort of file path for other images, and they work fine. It's just here, in this class, in this loadContent method, that they won't work.

The Content.Load methods does not load files, it loads specialized content or assets. Have a look at this.
You can't load files directly, you can only load assets. These assets are generated via the content pipeline.
This is mainly to provide an abstract layer for content. Because XNA is platform independent, and on one machine you may be use a bigger image or different image, you only need to change the asset in the pipeline and can reuse the code.

Just to add to dowhilefor's excellent answer, if you want to load a raw .jpg file (or .png), you can do so like this:
using(var s = File.OpenRead(fileName))
{
Texture2D texture = Texture2D.FromStream(GraphicsDevice, s);
}
Unlike when you load something using ContentManager, you "own" it in this case. This means you are responsible for calling Dispose() on it in UnloadContent.
Also unlike when you go through the content pipeline (using the default settings), the texture that you load will not have premultiplied-alpha. You need to apply premultiplication yourself, or render it with BlendState.NonPremultiplied.
Of course, unless you are unable to for some reason (eg: you're downloading images from the internet, or you're letting your end user pick them), you should use the content pipeline.

Related

Accessing Images in PowerPoint file via VSTO Add-In (C#)

I am trying to build a PowerPoint add-in that will allow me to do a one-click optimization of the current presentation by removing unused master slides and converting huge 24-bit PNG files to slightly-compressed JPGs.
I have the first part handled already, and now I'm working on the images. Although I can easily find the Shape object containing the image, I cannot find a way to access the source image through the managed API. At best, I can copy the shape to the clipboard, which does give me the image but in a different format (MemoryBmp).
using PPTX = Microsoft.Office.Interop.PowerPoint;
...
foreach (PPTX.Slide slide in Globals.ThisAddIn.Application.ActivePresentation.Slides)
{
foreach (PPTX.Shape shape in slide.Shapes)
{
if (shape.Type == MsoShapeType.msoPicture)
{
// Now, how can I access the source image contained within this shape?
// I -can- copy it via the clipboard, like this:
shape.Copy();
System.Drawing.Image image = Clipboard.GetImage();
// ...but image's format reflects a MemoryBmp ImageFormat, as noted here:
// https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/ImageFormat.cs
// ...which doesn't help me determine if the source image is something that should be optimized.
}
}
}
Obviously, I can get to the images directly via other methods (e.g. accessing the contents of the file as a ZIP, or using OpenXML SDK), but I'm trying to perform all the steps from within the already-opened presentation (which means I can't update the open file). Any thoughts on how I can do this?
You could use a Microsoft.Office.Interop.PowerPoint.Shape Export function.
void Export(string PathName, PpShapeFormat Filter, int ScaleWidth = 0, int ScaleHeight = 0, PpExportMode ExportMode = PpExportMode.ppRelativeToSlide)
There is a very little documentation of this function.
I've found it in the Shape interface definition.
So your code would look something like:
shape.Export(<some_file>, PpShapeFormat.ppShapeFormatPNG);
More info on MSDN

How to write and view converted pdfs to and from memory?

Right now I am using ghostscript in Unity to convert pdfs to jpgs and view them in my project.
Currently it flows like so:
-Pdfs are converted into multiple jpegs (one for each page)
-The converted jpegs are written to disk
-They are then read in by bytes into a 2D texture
-And this 2D texture is assigned to a GameObjects RawImage component
This works perfectly in Unity, but... (now comes the hiccup) my project is intended to run on the Microsoft Hololens.
The Hololens runs on the Windows 10 API, but in a limited capacity.
Where the issue arises is when I try to convert pdfs and view them on the Hololens. Quite simply, the Hololens cannot create or delete files outside of its known folders (Pictures, Documents, etc).
My imagined solution to this problem is to instead of write the converted jpeg files to disk, write them to memory and view them from there.
In talking with GhostScript devs, I was told GhostScript.NET does what I am looking to do - convert pdfs and view them from memory (It does this with the Rasterizer/Viewer classes, I believe, but again I don't understand it quite well).
I've been lead to look at the latest GhostScript.NET docs to route out how this is done, but I simply don't understand them well enough to approach this.
My question is then, based on how I'm using ghostscript now, how do I use GhostScript.NET in my project to write the converted jpegs into memory and view them there?
Here's how I'm doing it now (code-wise):
//instantiate
byte[] fileData;
Texture2D tex = null;
//if a PDF file exists at the current head path
if (File.Exists(CurrentHeadPath))
{
//Transform pdf to jpg
PdfToImage.PDFConvert pp = new PDFConvert();
pp.OutputFormat = "jpeg"; //format
pp.JPEGQuality = 100; //100% quality
pp.ResolutionX = 300; //dpi
pp.ResolutionY = 500;
pp.OutputToMultipleFile = true;
CurrentPDFPath = "Data/myFiles/pdfconvimg.jpg";
//this call is what actually converts the pdf to jpeg files
pp.Convert(CurrentHeadPath, CurrentPDFPath);
//this just loads the first image
if (File.Exists("Data/myFiles/pdfconvimg" + 1 + ".jpg"))
{
//reads in the jpeg file by bytes
fileData = File.ReadAllBytes("Data/myFiles/pdfconvimg" + 1 + ".jpg");
tex = new Texture2D(2, 2);
tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
//Read Texture into RawImage component
PdfObject.GetComponent<RawImage>().texture = tex;
PdfObject.GetComponent<RawImage>().rectTransform.sizeDelta = new Vector2(288, 400);
PdfObject.GetComponent<RawImage>().enabled = true;
}
else
{
Debug.Log("reached eof");
}
}
The convert function is from a script called PDFConvert which I obtained from code project. Specifically How To Convert PDF to Image Using Ghostscript API.
From the GhostScript.Net documentation, take a look at the example code labeled: "Using GhostscriptRasterizer class". Specifically the following lines:
Image img = _rasterizer.GetPage(desired_x_dpi, desired_y_dpi, pageNumber);
img.Save(pageFilePath, ImageFormat.Png);
The Image class seems to be part of the System.Drawing package, and System.Drawing.Image has another Save method where the first parameter is a System.IO.Stream.

Xamarin Forms: Default Image if Url not found

In xamarin forms we can create images like this:
Image i = new Image { Source = "http://www.foo.com/foo.jpg };
After adding this to layout if url returns an image it will display it. What I want to now is is there a way to know if ths Url is an actual image. Otherwise I am going to show an default image.
Regards.
Edit
I have created a function:
public string GetImageSourceOrDefault(string orgUrl)
{
var req = (HttpWebRequest)WebRequest.Create(orgUrl);
req.Method = "HEAD";
try
{
using (var resp = req.GetResponse())
{
bool res = resp.ContentType.ToLower(CultureInfo.InvariantCulture)
.StartsWith("image/");
if (res)
return orgUrl;
else
return "defualt_logo.jpg";
}
}
catch
{
return "default_logo.jpg";
}
}
This function does the trick. However, for every image it does a request. I have a listview which shows like 220 entries. Using this method messed up the time that listview gets loaded.
Note: this function is natively called using dependency injection.
Maybe further improvements will do. Any ideas?
FFImageLoading CachedImage supports Loading and Error Placeholders (and much more). It's basically a API compatible replacement for Image with additional properties. You could try that.
var cachedImage = new CachedImage() {
LoadingPlaceholder = "Loading.png",
ErrorPlaceholder = "Error.png"
};
https://github.com/molinch/FFImageLoading
With Xamarin.Forms UriImageSource you can specify different caching length, and whether caching is used by using the properties CacheValidity and CachingEnabled.
By default it will automatically cache results for 1 day on the local storage of the device.
In your function, as you mention, you are downloading the image every single time.
You have no current functionality that is storing and caching the result for later re-use.
By implementing something like this on the platform specific layer would get around your current solution of re-downloading the image every single time.
Alternatively as a workaround, if you didn't want to implement the above, you could try putting two Image controls stacked upon each other, maybe in a Grid, with the bottom image showing a default placeholder image, and on-top another Image control that would show the intended image, if successfully downloaded, using the UriImageSource.
You could also possibly hook hook into the PropertyChange notification of the Image.Source and detect it being set, with the image then being displayed. Upon detection you could then release the image from the temporary place holder Image control perhaps?

Resizing gif images using Imageresizer

I attempted to use imageresizer and the animated gif plugin to resize an animated gif. It did resize but I lost the animation in the process. I did set the format to gif even after following the example given on the site. Any help would be appreciated.
Thanks for the response. I should first point out that I am building a desktop application. Here is the code I am using:
var fileName = ofdChiImage.FileName;
Dictionary<string, string> versions = new Dictionary<string, string>();
versions.Add("_thumb1", "maxwidth=200&maxheight=200&format=gif");
string basepath = ImageResizer.Util.PathUtils.RemoveExtension(fileName);
foreach (string suffix in versions.Keys)
{
ImageBuilder.Current.Build(fileName, basepath + suffix, new ResizeSettings(versions[suffix]), false, true);
}
in .NET4+, Console and desktop applications do not automatically load DLLs that are not explicitly referenced through code (even if they are referenced within App.config). Thus for these types of applications we always recommend the code-based (instead of xml-based) installation method for ImageResizer plugins.

XNA ContentLoadException

I'm starting to learn "some" XNA and - as expected - I've run into an obstacle pretty early.
I've created a WP7 XNA Game solution
I've removed the default content project
I've added my own content project "Sprites"
I've added 3x *.png files to the "Sprites" project (MyImage1.png, MyImage2.png, MyImage3.png)
I've added a Content reference, referencing the "Sprites" to the main game project
/**/
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
logoTexture = Content.Load<Texture2D>("Sprites/MyImage1");
// TODO: use this.Content to load your game content here
}
I'm getting a ContentLoadException saying "not found" when trying to load one my *.png's
I did check the output directory, a "Sprites" subfolder containing *.xnb files is present
I did check the properties of the images, all are marked as Texture2Ds and have content importers and processors set to default XNA values
I'm pretty sure I'm making a common n00b'ish mistake, but I'm failing to see it, so I'd apreciate some guidance.
Problem Fixed
Content.RootDirectory = "Content"; // The cause of the problem
Regards
Why did you remove the content project?
My guess is that you need to set the RootDirectory
Content.RootDirectory = "Content";
which BTW creates ContentManager object.
You should try the following path formatting instead:
".\\Sprites\\MyImage1"
According to MSDN, the path must be relative to the current directory. And the directory separator is '\'.

Categories