Conversion og BMP instance to png - c#

I have function name uploadLayerIcons which is as follows:
private void uploadLayerIcon(string LayerName)
{
Bitmap icon= new Bitmap(#"C:\Users\HP\Desktop\911\Prism\Prism_Resources\m.png");
System.IO.MemoryStream stream = new System.IO.MemoryStream();
icon.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] imageBytes = stream.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
HttpWebRequest m_ObjRequest; //Request which needed to be sent to server
HttpWebResponse m_ObjResponse; // Response which is sent back from the server to the client
StreamReader reader = null; // making a stream reader to read the web pageand initialize it to null
string m_Url = "http://192.168.1.30/muneem/erp/uploadIcon.php" + "?bitmap=" + base64String + "&layerName=" + LayerName; // the url of that web page
string m_Response = "";
m_ObjRequest = (HttpWebRequest)WebRequest.Create(m_Url); // creating the url and setting the values
m_ObjRequest.Method = "GET";
m_ObjRequest.ContentType = "application/json; charset=utf-8";
//m_ObjRequest.ContentLength = 500;
m_ObjRequest.KeepAlive = false;
m_ObjResponse = (HttpWebResponse)m_ObjRequest.GetResponse(); // getting response from the server
using (reader = new StreamReader(m_ObjResponse.GetResponseStream())) // using stream reader to read the web page
{
m_Response = reader.ReadToEnd();
reader.Close(); // Close the StreamReader
}
m_ObjResponse.Close();
m_ObjRequest = null;
m_ObjResponse = null;
}
UploadIcon.php file is as follows:
<?php
$bitmap=$_GET['bitmap'];
$name=$_GET['layerName'];
$data = base64_decode($bitmap);
$filepath="app/uams/uploadedImages/".$name.".jpg";
file_put_contents($filepath,$data);
?>
Its not converting correctly the same image which i have sent to server.
I have search on internet many thing but all in vain. I have also tried this thing
Bitmap icon= new Bitmap(#"C:\Users\HP\Desktop\911\Prism\Prism_Resources\m.png");
icon.save("Path of srrver")
But its not working.

So, you are doing it pretty much wrong. First of all, if you change the extension of the file to .jpg it does not automagically become jpg image.
So, what I suggest you to do is to send the raw png data instead of bitmap, and then using something like this in php:
<?
$imagedata = $_POST["data"];
$im = imagecreatefromstring($imagedata);
$filepath="app/uams/uploadedImages/image.jpg";
imagejpeg($im,$filepath);
?>
Also, as pointed out in previous answer by #DoXicK, do not send file by GET method, you should post it instead, and that is what this example is based on.
PHP's function imagecreatefromstring identifies the image type, and creates the gdlib object accordingly (but it does not work very well with bitmaps). That is why I suggested that you use raw png data instead of converting it to bitmap. Also, bitmap data is unneccesary large for transfer.
For imagecreatefromstring to work you need GD Library installed and enabled. To see if it is enabled create an empty file (named for example info.php) and inside it put only
<?
phpinfo();
?>
If you see GD Support set to Enable on the page, when you open the file, you have gdlib enabled. If you do not see it, do the following:
On windows find ;extension=php_gd2.dll in php.ini file of your php installation, and uncomment it (remove ; from the beginning) so it now is extension=php_gd2.dll and then restart Apache.
On linux you need to do sudo apt-get install php5-gd and then restart Apache.

you are loading a PNG to BMP file format
You are sending a file by GET
you are saving the BMP file as JPG te minute you receive the BMP
So:
Don't open as PNG as BMP. open a PNG as PNG as it is either smaller or the same size. There is no need for the BMP here...
POST it
Just because you call it a JPG, doesn't make it a JPG. It currently is a BMP, saved to a JPG.
IF it even saves a .jpg file, it is a .bmp file with the wrong extension.

Related

C# Image.Save() cause Cannot access a closed Stream when saving JPG file (PNG works)

I've got strange behavior.
I have a code, when I am sending byte[] array to the Image (sometimes png, sometimes jpg).
When I save PNG format - everything is ok, but when I am trying to save JPG, there is an exception: "Cannot access a closed Stream"
Code:
imgTarget.Save(wwwroot + "\\ImageBank\\" + TaskRunID + "_" + TestCaseID + "_" + TestDataID + "_" + ImageCounter + Extension, ImageFormat.Jpeg);
What I have checked:
imgTarget is not null
imgTarget contains correct data (even RawFormat is Png or Jpeg as It should)
imgTarget.Save() throws an exception: System.ObjectDisposedException: 'Cannot access a closed Stream.'
I have tried to use Bitmap - copy imgTarget to new Bitmap and then Save (with the same result)
I have tried to call Save() method with the ImageFormat parameter correctly set to jpeg or png (with the same result) - for both for Image.Save() and Bitmap.Save()
I have checked the correct path and file name (it's ok) (in this case it is C:\MyProd\wwwroot\ImageBank\10611_8_-1_1.jpeg)
Strange is that imgTarget contains data just before calling the method Save() - but right after it is null/disposed...
Anyone any ideas?
EDIT:
I have prepared little bit of code which is failing in the same way - it fails at last line .Save()
// This contains only the URL for the downloading of the file
string url = $"***url to download jpg file***";
// Request for the API - which downloads the jpg file via GET and provide the RawData via Response.RawBytes
APIRequest request = new APIRequest(RestSharp.Method.GET, url, new Authentication("user", "password", "-1"));
// Test case is only class which calls RestSharp (get png or jpg file)
TestCase t = new TestCase();
// This downloads the jpg file and store it as byte[] in t.GetDataFromAPI
t.API(request);
// Using downloaded data as byte[]
byte[] APIImageSource = t.GetDataFromAPI;
// Default extensions for saving files is .png
string Extension = ".png";
Image imgTarget;
// Now I use bytes[] and convert them into the image
imgTarget = ConvertBytesToImage(APIImageSource);
if (t.GetImageFormat(APIImageSource) == ExpectedFormat.JPEG)
{
Extension = ".jpeg";
}
string path = "C:\\Temp\\filename" + Extension;
imgTarget.Save(path + Extension, ImageFormat.Jpeg);
There is Method ConvertBytesToImage:
internal static Image ConvertBytesToImage(byte[] bytes)
{
using (var ms = new MemoryStream(bytes))
{
return Image.FromStream(ms);
}
}
Comment from #Simon Mourier is the solution:
remove the using on the MemoryStream, or remove that ConvertBytesToImage and keep the MemoryStream alive until you completely saved the image. – Simon Mourier 1 min ago
I don't understand why, but I have removed the using statement and now it works.
Thank all of You

Is there a function that takes a filename from the Image object

I'm using the Movie Maker Library Timeline SDK Control 6.0 dll
And to add a photo you need a STRING of a file name. So far everything is fine
But I want to insert a function that gets an IMAGE object
But the library does not have a function that cables an IMAGE object
What I need is to get the file name out of the IMAGE object
That is: string fileName = image
Image img = default;
using (WebClient client = new WebClient())
{
string url = textBox1.Text;
Stream stream = client.OpenRead(url);
img = Image.FromStream(stream);
axTimelineControl1.AddImageClip(trackIndex: 1, fileName :img.ToString(),
clipStartTime: axTimelineControl1.GetMediaDuration(img.ToString()), clipStopTime: 4);
}
You've got a small bit of an "XY problem" here--you're asking the wrong question. Your axTimelineControl1 expects an image's file name. This implies that it also expects there to be an image saved to disk with that file name.
But all you have is a remote image, behind some URL. client.OpenRead(url) downloads the image into a Stream, but you can't do anything with that directly.
So, you don't want to take that image, and put it into a WinForms Image object. Instead, you want to save that image to disk with a file name, and then give that file name to your axTimelineControl1.
You have a few options for doing that:
1) You could take the Stream you got from client.OpenRead(), turn it into a FileStream and save it to disk.
2) You could use the WebClient to download the image directly to disk, and then give the image's file name to the axTimelineControl1.
Let's do 2) instead. It'll save a few steps.
First, create the file.
string fileName = System.IO.Path.GetTempFileName();
System.IO.File.Create(fileName).Close();
We're creating a "Temp" file here--these are meant to be treated as disposable. Note that Windows doesn't clean them up for you, so once you're done with it, your program should delete it. System.IO.File.Create() gives us a FileStream object, but we don't need it, so we Close() it right away, so that the WebClient will be able to write to our file.
Next, we download our image, and tell WebClient to save it to our newly-created Temp file:
// Defining my own URL here. Feel free to substitute your own.
string url = "https://derpicdn.net/img/view/2018/5/18/1735426.jpeg";
using (var client = new WebClient())
{
client.DownloadFile(url, fileName);
}
Now we have an image on disk, and we can tell the Movie Maker SDK Control where to find it:
float duration = axTimelineControl1.GetMediaDuration(fileName);
axTimelineControl1.AddImageClip(
trackIndex: 1,
fileName: fileName,
clipStartTime: duration,
clipStopTime: 4);
And that should do it.
The entire code listing:
string fileName = System.IO.Path.GetTempFileName();
System.IO.File.Create(fileName).Close();
// Defining my own URL here. Feel free to substitute your own.
string url = "https://derpicdn.net/img/view/2018/5/18/1735426.jpeg";
using (var client = new WebClient())
{
client.DownloadFile(url, fileName);
}
float duration = axTimelineControl1.GetMediaDuration(fileName);
axTimelineControl1.AddImageClip(
trackIndex: 1,
fileName: fileName,
clipStartTime: duration,
clipStopTime: 4);
Don't forget to clean up your temp file!

Download a PDF from a third party using ASP.NET HttpWebRequest/HttpWebResponse

I want to send a url as query string e.g.
localhost/abc.aspx?url=http:/ /www.site.com/report.pdf
and detect if the above URL returns the PDF file. If it will return PDF then it gets saved automatically otherwise it gives error.
There are some pages that uses Handler to fetch the files so in that case also I want to detect and download the same.
localhost/abc.aspx?url=http:/ /www.site.com/page.aspx?fileId=223344
The above may return a pdf file.
What is best way to capture this?
Thanks
You can download a PDF like this
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response = req.GetResponse();
//check the filetype returned
string contentType = response.ContentType;
if(contentType!=null)
{
splitString = contentType.Split(';');
fileType = splitString[0];
}
//see if its PDF
if(fileType!=null && fileType=="application/pdf"){
Stream stream = response.GetResponseStream();
//save it
using(FileStream fileStream = File.Create(fileFullPath)){
// Initialize the bytes array with the stream length and then fill it with data
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, bytesInStream.Length);
// Use write method to write to the file specified above
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
}
response.Close();
The fact that it may come from an .aspx handler doesn't actually matter, it's the mime returned in the server response that is used.
If you are getting a generic mime type, like application/octet-stream then you must use a more heuristical approach.
Assuming you cannot simply use the file extension (eg for .aspx), then you can copy the file to a MemoryStream first (see How to get a MemoryStream from a Stream in .NET?). Once you have a memory stream of the file, you can take a 'cheeky' peek at it (I say cheeky because it's not the correct way to parse a PDF file)
I'm not an expert on PDF format, but I believe reading the first 5 chars with an ASCII reader will yield "%PDF-", so you can identify that with
bool isPDF;
using( StreamReader srAsciiFromStream = new StreamReader(memoryStream,
System.Text.Encoding.ASCII)){
isPDF = srAsciiFromStream.ReadLine().StartsWith("%PDF-");
}
//set the memory stream back to the start so you can save the file
memoryStream.Position = 0;

How to convert a byte array to an image and open it with some process without creating a file on the disk?

How to convert Byte array to an image and open with some process (such as Windows Photo Viewer)?
In here i don't want to convert array data to an image file and save it in the disk, what i would like to do is to convert byte array to a memory stream or such a thing and using this i want to open that specific image.
Is it possible? (not to show them in a picture box or such a thing).
You will not be able to open it in an external viewer unless it's a file. However, if you don't care about that file, use a temporary one:
public void ViewImage(Byte[] ImageBytes)
{
try
{
Byte[] ba = new Byte[1];
using (MemoryStream ms = new MemoryStream(ba))
{
Image img = Image.FromStream(ms);
String tmpFile = Path.GetTempFileName();
tmpFile = Path.ChangeExtension(tmpFile, "jpg");
img.Save(tmpFile);
if (File.Exists(tmpFile))
Process.Start(tmpFile); //Windows will use file association to open a viewer
}
}
catch (OutOfMemoryException ex)
{
//React appropriately
}
}
Since this forces saving the image as a JPG, if the type of the original image is important, more logic should be added to deal with that fact.

Using HttpWebRequest with dynamic URI causes "parameter is not valid" in Image.FromStream

I'm trying to obtain an image to encode to a WordML document. The original version of this function used files, but I needed to change it to get images created on the fly with an aspx page. I've adapted the code to use HttpWebRequest instead of a WebClient. The problem is that I don't think the page request is getting resolved and so the image stream is invalid, generating the error "parameter is not valid" when I invoke Image.FromStream.
public string RenderCitationTableImage(string citation_table_id)
{
string image_content = "";
string _strBaseURL = String.Format("http://{0}",
HttpContext.Current.Request.Url.GetComponents(UriComponents.HostAndPort, UriFormat.Unescaped));
string _strPageURL = String.Format("{0}{1}", _strBaseURL,
ResolveUrl("~/Publication/render_citation_chart.aspx"));
string _staticURL = String.Format("{0}{1}", _strBaseURL,
ResolveUrl("~/Images/table.gif"));
string _fullURL = String.Format("{0}?publication_id={1}&citation_table_layout_id={2}",
_strPageURL, publication_id, citation_table_id);
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_fullURL);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream image_stream = response.GetResponseStream();
// Read the image data
MemoryStream ms = new MemoryStream();
int num_read;
byte[] crlf = System.Text.Encoding.Default.GetBytes("\r\n");
byte[] buffer = new byte[1024];
for (num_read = image_stream.Read(buffer, 0, 1024); num_read > 0; num_read = image_stream.Read(buffer, 0, 1024))
{
ms.Write(buffer, 0, num_read);
}
// Base 64 Encode the image data
byte[] image_bytes = ms.ToArray();
string encodedImage = Convert.ToBase64String(image_bytes);
ms.Position = 0;
System.Drawing.Image image_original = System.Drawing.Image.FromStream(ms); // <---error here: parameter is not valid
image_stream.Close();
image_content = string.Format("<w:p>{4}<w:r><w:pict><w:binData w:name=\"wordml://{0}\">{1}</w:binData>" +
"<v:shape style=\"width:{2}px;height:{3}px\">" +
"<v:imagedata src=\"wordml://{0}\"/>" +
"</v:shape>" +
"</w:pict></w:r></w:p>", _word_image_id, encodedImage, 800, 400, alignment.center);
image_content = "<w:br w:type=\"text-wrapping\"/>" + image_content + "<w:br w:type=\"text-wrapping\"/>";
}
catch (Exception ex)
{
return ex.ToString();
}
return image_content;
Using a static URI it works fine. If I replace "staticURL" with "fullURL" in the WebRequest.Create method I get the error. Any ideas as to why the page request doesn't fully resolve?
And yes, the full URL resolves fine and shows an image if I post it in the address bar.
UPDATE:
Just read your updated question. Since you're running into login issues, try doing this before you execute the request:
request.Credentials = CredentialCache.DefaultCredentials
If this doesn't work, then perhaps the problem is that authentication is not being enforced on static files, but is being enforced on dynamic files. In this case, you'll need to log in first (using your client code) and retain the login cookie (using HttpWebRequest.CookieContainer on the login request as well as on the second request) or turn off authentication on the page you're trying to access.
ORIGINAL:
Since it works with one HTTP URL and doesn't work with another, the place to start diagnosing this is figuring out what's different between the two requests, at the HTTP level, which accounts for the difference in behavior in your code.
To figure out the difference, I'd use Fiddler (http://fiddlertool.com) to compare the two requests. Compare the HTTP headers. Are they the same? In particular, are they the same HTTP content type? If not, that's likely the source of your problem.
If headers are the same, make sure both the static and dynamic image are exactly the same content and file type on the server. (e.g. use File...Save As to save the image in a browser to your disk). Then use Fiddler's Hex View to compare the image content. Can you see any obvious differences?
Finally, I'm sure you've already checked this, but just making sure: /Publication/render_citation_chart.aspx refers to an actual image file, not an HTML wrapper around an IMG element, right? This would account for the behavior you're seeing, where a browser renders the image OK but your code doesn't.

Categories