I'm trying to have an image load in my winform through a TCP message.
At the moment I have a my program set to look in the required directory via the following. This line is held with in a TCP class I've set up:
Image _imageName = Image.FromFile("C:\\Image\\");
What my tcp command will do is send the following string line:
IMG Cat
The first 3 letters aren't important, but need to be in there. With this tcp command I've set up a switch statement that will act depending on those first three letters. So, my new _image name line looks like the following:
Image _imageName = Image.FromFile("C:\\Image\\" + splitString[1]);
The value of _imageName is then stored in a getter called Picture;
Inside my Image class I'm setting the file to be displayed like this:
PictureBox _picBox = new PictureBox();
_picBox.Image = Image.FromFile(_tcp.Picture);
However, I get the following errors:
The best overloaded method match for "System.Drawing.Image.FromFile(string) has some invalid arguments
Argument 1: cannot convert 'System.Drawing.Image' to 'string;
The line that is highlighted is the _picBox.Image line. I've tried googleing an answer. Casting the command as both an Image and a float, changing my getter. But nothing is working.
Does anyone know how I can fix this?
In this lines you are trying to create Image form another Image instance.
PictureBox _picBox = new PictureBox();
_picBox.Image = Image.FromFile(_tcp.Picture);
While FromFile method accepts string path to image file you want to load.
Fix it like this:
PictureBox _picBox = new PictureBox();
_picBox.Image = _tcp.Picture;
Related
I am creating a photo editing app for my c# project. I need to support different image formats, but to begin with, I chose a very simple format - PNM. At the moment, I can open PNM images and change the color scheme, but strange things happen when saving. When saving the image on macOS, everything works fine, but after trying a similar action on Windows, I got a strange effect, the colors were read with a shift of 1 byte with each new opening after saving.
Here is an example of an image:
example image
That’s what is happening after loading and re-opening it on Windows:
damaged image
It is logical to assume that the problem is in the methods of saving the image. I first write the entire file header to the stream, and then write the color bytes one by one.
I can't figure out what exactly the problem is, because when debugging, the array of bytes being written contained nothing extra. Opening the image in the notepad before and after saving, I did not find any visible changes.
Here is my implementation of saving in a file:
public void SaveTo(Stream stream)
{
_filter.WriteHeader(stream, _image);
foreach (var (x, y) in _enumerationStrategy.Enumerate(Width, Height))
{
var triplet = _image[x, y];
_filter.Write(stream, triplet, _converterProvider.Converter);
}
}
public void WriteHeader(Stream stream, IBitmapImage image)
{
var builder = new StringBuilder();
builder.AppendLine("P6");
builder.AppendLine($"{image.Width} {image.Height}");
builder.AppendLine("255");
var header = builder.ToString();
var headerBytes = Encoding.UTF8.GetBytes(header);
stream.Write(headerBytes, 0, headerBytes.Length);
}
I tried to create a header of image without a string builder, and I tried to write the header to the stream in different ways. Trying different encodings to convert bytes didn't work out too. The effect is the same...
I guess your issue is caused by inconsistent line endings between operating systems. When you use AppendLine it adds a \n character after your string which is translated to binary differently, depending on the OS you running.
I suggest you to write a line ending directly like so:
builder.Append((char)10);
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?
I want to add an image as a resource in my project so that I can reference it for programmatically inserting into a range in a spreadsheet.
I added the image by right-clicking the project and selecting Add > Existing Item...
I hoped that the image (.png file) would then be available using this code:
var logoRange = _xlSheet.Range[
_xlSheet.Cells[1, LOGO_FIRST_COLUMN],
_xlSheet.Cells[5, LOGO_LAST_COLUMN]];
//System.Drawing.Bitmap logo =
//ReportRunner.Properties.Resources.pa_logo_notap.png;
System.Drawing.Image logo =
ReportRunner.Properties.Resources.pa_logo_notap.png;
_xlSheet.Paste(logoRange, logo);
...but using either Bitmap or Image, I get, "'ReportRunner.Properties.Resources' does not contain a definition for 'pa_logo_notap'"
This seemed like sensible code based on what I read here, but it seems that the image has to be explicitly marked as a resource for this to work. How do I accomplish that?
UPDATE
I tried this:
System.Drawing.Image logo = (System.Drawing.Image)ReportRunner.Properties.Resources.ResourceManager.GetObject("pa_logo_notag.png");
_xlSheet.Paste(logoRange, logo);
...but not only did I get a confirmation msg about the item being pasted not being the same size and shape as the place where it was being inserted, and did I really want to do that, it also inserted some seemingly unrelated text ("avgOrderAmountCell.Style") instead of the image.
UPDATE 2
Okay, I tried this:
Assembly myAssembly = Assembly.GetExecutingAssembly();
System.Drawing.Image logo = (System.Drawing.Image)myAssembly.GetName().Name + ".pa_logo_notap.png";
Clipboard.SetDataObject(logo, true);
_xlSheet.Paste(logoRange, logo);
...but get, "Cannot convert type 'string' to 'System.Drawing.Image' on the second line of that code.
UPDATE 3
This works:
private System.Drawing.Image _logo;
. . .
_logo = logo; // logo (the image) is passed in an overloaded constructor
. . .
var logoRange = _xlSheet.Range[
_xlSheet.Cells[1, LOGO_FIRST_COLUMN], _xlSheet.Cells[6,
LOGO_LAST_COLUMN]];
Clipboard.SetDataObject(_logo, true);
_xlSheet.Paste(logoRange, _logo);
...but I'm not crazy about it, because I'm using an image that is on a form, and passing the image to this class's constructor. Passing images around seems kind of goofy when it should be possible to store the image as a resource and just load the resource. I still haven't gotten that methodology to work, though...
UPDATE 4
I reckon I'll just stick with what I've got (in Update 3), kludgy as it is, because this:
Assembly myAssembly = Assembly.GetExecutingAssembly();
Stream myStream =
myAssembly.GetManifestResourceStream(myAssembly.GetName().Name +
"pa_logo_notap.png");
Bitmap bmp = new Bitmap(myStream);
Clipboard.SetDataObject(bmp, true);
_xlSheet.Paste(logoRange, bmp);
...fails with, "Value of 'null' is not valid for 'stream'"
You have change the build action of the image to be embedded resource.
Then you can reference by doing:
UPDATED
Assembly myAssembly = Assembly.GetExecutingAssembly();
Stream myStream = myAssembly.GetManifestResourceStream( myAssembly.GetName().Name + ".images.pa_logo_notap.png");
Bitmap bmp = new Bitmap(myStream);
My method is to open Resources.resx under Properties. You'll see all your resources laid out on screen.
Click on the downarrow next to 'Add Resource' and you'll see the option Add Existing File. Choose your image name.
I am working on windowes form application..in show button event i wrote code like this:
Me.PictureBox1.Load("C:/Signature.tif")
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Me.PictureBox1.BorderStyle = BorderStyle.Fixed3D
then save button click i wrote code like this:
Dim exittime As String = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")
Dim ms As New MemoryStream
Dim byt() As Byte
PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
byt = ms.GetBuffer
Dim sqlstr As String = "Update Visitorlogo_tbl set signimage=#pic,exittime='" & exittime & "',status=2 where PassNo='" & txtvisitorid.Text & "'"
Dim cmd1 As New SqlCommand(sqlstr, con.connect)
cmd1.Parameters.Add("#pic", SqlDbType.Image)
cmd1.Parameters("#pic").Value = byt
cmd1.ExecuteNonQuery()
con.disconnect()
PictureBox1.Image = Nothing
If System.IO.File.Exists("C:/Signature.tif") Then
System.IO.File.Delete("C:/Signature.tif")
End If
while saving image image got saving,,but after that i want to delete image from that path.. while coming to this line : System.IO.File.Delete("C:/Signature.tif") am getting error: The process cannot access the file 'C:\Signature.tif' because it is being used by another process
Possible the problem is here.
Me.PictureBox1.Load("C:/Signature.tif")
try this
Me.PictureBox1.Image = new Bitmap("C:\Signature.tif");
UPDATED:
PictureBox1.Load() method will load the file from given location and stores the file path in PictureBox.ImageLocation property. with this method, application will open that image and lock so, other user cannot modify or read it.
PictureBox1.Image = new Bitmap("filePath"); will create the another image object from given file path and it will not lock down the original one. This method will not load the original image from given file location. So, the PictureBox1.ImageLocation property will not be set here. How you can access that image and modify it.
The PictureBox will keep the file open. Therefore you can use the fix suggested by #Shell to release the file after reading the contents. This behavior is by design of the PictureBox.
http://support.microsoft.com/kb/309482
Here is a workaround adapted from the knowledge base article
Using fs as New System.IO.FileStream("C:\Signature.tif", IO.FileMode.Open, IO.FileAccess.Read)
PictureBox1.Image = System.Drawing.Image.FromStream(fs)
End Using
As the error message suggests the image is open by another process. Have you got the image open in a graphics program for example?
Do you have another instance of your application running in the background that has locked the image for reading?
If so close the other programs.
this is how my code look now:
System.Drawing.Image objImage = System.Drawing.Image.FromFile(Server.MapPath("aaa.jpg"));
int height = objImage.Height;
int width = objImage.Width;
System.Drawing.Bitmap bitmapimage = new System.Drawing.Bitmap(objImage, width, height);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmapimage);
System.Drawing.Image bitmap2 = (System.Drawing.Image)Bitmap.FromFile(Server.MapPath("sem.png"));
g.DrawImage(bitmap2, (objImage.Width - bitmap2.Width) / 2, (objImage.Height - bitmap2.Height) / 2);
MemoryStream stream = new MemoryStream();
bitmapimage.Save(stream, ImageFormat.Jpeg);
String saveImagePath = Server.MapPath("ImagesMerge/") + "aaa.jpg";
bitmapimage.Save(saveImagePath);
imgBig.ImageUrl = saveImagePath;
The problem I have now is that the image is not displayed in browser, I don't understand why .
like jmaglasang said, I would suggest to you to use an ashx file and if you don't need to keep the image, just send the image stream directly to the http without saving it on the disk
so you only need to do something like
<img src="Handler.ashx?action=merge&image1=blah.jpg&image2=bloh.jpg">
look at this code for an example of how to send an image made in memory that does not exist on the drive
Bitmap is a subclass of Image, so there no need to convert Bitmap to Image. It already is...
Probably because saveImagePath will be a local path (such as c:\somepath\aaa.jpg) that is not reachable from the browser. You probably want to set the ImageUrl = "ImagesMerge/aaa.jpg" instead.
You can also try:
imgBig.ImageUrl = ResolveUrl(saveImagePath);
EDIT:
If saveImagePath is under the WebApplication Directory, doing some modifications on the directory structure i.e. modifying files, deleting and creating can cause the application pool to recycle, and once it reaches the maximum recycle count the application pool will be stopped causing "Server unavailable" error.
I would suggests to add/save/modify images on a separate directory (not under the Apps Directory) then create a Handler(ASHX) that will read the images, just an advice though.
MapPath will give you a physycal address, not a virtual address which is what the browser needs to get to the image.
You might be forgetting to set the Response.Headers. Check out the following example that shows how to create bar chart images and then display it on the screen:
http://www.highoncoding.com/Articles/399_Creating_Bar_Chart_Using__NET_Graphics_API.aspx