The following HttpHandler is to retrieve image from database. When I initially tested it it was working fine. but now the problem is that it still retieve image but does not display it in image control that is in Listview.
`public void ProcessRequest (HttpContext context)
{
string imageid = context.Request.QueryString["ImID"];
using (SqlConnection connection = ConnectionManager.GetConnection())
{
SqlCommand command = new SqlCommand("select Normal_Thumbs from User_Images where Id=" + imageid, connection);
SqlDataReader dr = command.ExecuteReader();
dr.Read();
if (dr[0] != DBNull.Value)
{
Stream str = new MemoryStream((Byte[])dr[0]);
Bitmap Photo = new Bitmap(str);
int Width = Photo.Width;
int Height = Photo.Height;
int imagesize = 200;
if (Photo.Width > Photo.Height)
{
Width = imagesize;
Height = Photo.Height * imagesize / Photo.Width;
}
else
{
Width = Photo.Width * imagesize / Photo.Height;
Height = imagesize;
}
Bitmap bmpOut = new Bitmap(150, 150);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, Width, Height);
g.DrawImage(Photo, 0, 0, Width, Height);
MemoryStream ms = new MemoryStream();
bmpOut.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] bmpBytes = ms.GetBuffer();
bmpOut.Dispose();
ms.Close();
context.Response.Write(bmpBytes);
context.Response.End();
}
}
}
The Handler Retrieves the image but the listview does not display it.
Try this approach, setting content type to the response.
...
context.Response.Clear();
context.Response.ContentType = System.Drawing.Imaging.ImageFormat.Png.ToString();
context.Response.OutputStream.Write(bmpBytes, 0, bmpBytes.Length);
context.Response.End();
...
Regards.
Related
I am trying to run this code but I always get an error "cannot access a closed Stream"
private MemoryStream GetBitmap(Stream stream, int width, int height)
{
const int size = 150;
const int quality = 75;
using (var image = new Bitmap(System.Drawing.Image.FromStream(stream)))
{
//int width, height;
if (image.Width > image.Height)
{
width = size;
height = Convert.ToInt32(image.Height * size / (double)image.Width);
}
else
{
width = Convert.ToInt32(image.Width * size / (double)image.Height);
height = size;
}
var resized = new Bitmap(width, height);
using (var graphics = Graphics.FromImage(resized))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(image, 0, 0, width, height);
using (var output = new MemoryStream())
{
var qualityParamId = Encoder.Quality;
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(qualityParamId, quality);
var codec = ImageCodecInfo.GetImageDecoders()
.FirstOrDefault(codec => codec.FormatID == ImageFormat.Jpeg.Guid);
resized.Save(output, codec, encoderParameters);
return output;
}
}
}
}
Not sure how can I prevent Memorystream output from closing a Stream stream.
EDIT
After your suggestions here is the new code
public Stream GetBitmap(Stream stream)
{
using (var image = SystemDrawingImage.FromStream(stream))
{
var scaled = ScaledSize(image.Width, image.Height, ThumbnailSize);
var resized = new Bitmap(scaled.width, scaled.height);
using (var graphics = Graphics.FromImage(resized))
using (var attributes = new ImageAttributes())
{
attributes.SetWrapMode(WrapMode.TileFlipXY);
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.AssumeLinear;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.DrawImage(image, Rectangle.FromLTRB(0, 0, resized.Width, resized.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
using (var encoderParams = new EncoderParameters(1))
using (var qualityParam = new EncoderParameter(Encoder.Quality, (long)Quality))
{
encoderParams.Param[0] = qualityParam;
var streamOutput = new MemoryStream();
resized.Save(streamOutput, systemDrawingJpegCodec, encoderParams);
return streamOutput;
}
}
}
}
Here is the controller action method
[HttpGet("{photoId}")]
public async Task<IActionResult> GetPhoto(intphotoId)
{
if (String.IsNullOrEmpty(photoid))
return NotFound();
var response = await _service.GetPhotoAsync(photoId);
Response.Headers.Add("Content-Disposition", new ContentDisposition()
{
FileName = "test.jpg",
Inline = true
}.ToString());
return File(response, "image/jpeg");
}
You're creating the MemoryStream in a using block. When the block goes out of scope the Dispose method is being called. Just remove the using so that it isn't closed:
var output = new MemoryStream())
var qualityParamId = Encoder.Quality;
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(qualityParamId, quality);
var codec = ImageCodecInfo.GetImageDecoders()
.FirstOrDefault(codec => codec.FormatID == ImageFormat.Jpeg.Guid);
resized.Save(output, codec, encoderParameters);
return output;
Also, if you're planning to have the caller read the stream then you'll probably want to reset the Position property so that anyone reading from it starts from the beginning:
output.Position = 0;
return output;
before now, i save 2 size of image in database, real size and thumbnail, then show each of them when i need.
in ashx handler i set which type i need, here is my code:
string field = context.Request.QueryString["field"];
string table = context.Request.QueryString["table"];
string id = context.Request.QueryString["id"];
string conn = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;
SqlConnection myConnection = new SqlConnection(conn);
myConnection.Open();
string sql = "";
sql = "Select " + field + ", pictureType from " + table + " where id=#imageId";
SqlCommand cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.Add("#imageId", SqlDbType.Int).Value = id;
cmd.Prepare();
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
context.Response.ContentType = dr["pictureType"].ToString();
context.Response.BinaryWrite((byte[])dr[field]);
dr.Close();
myConnection.Close();
and i use this way:
<img src="handlers/ShowPic.ashx?table=tblEnBackGrounds&field=image&id=1" alt="s" />
but now i decide to save just real size image, then in ashx file re size and show proper type(here real or thumbnail).
now i need first to now is it good or not? second i don't have any idea how to re size binary data before show in ashx handler
Use the great Image Resize lib http://imageresizing.net/.
You need to resize images proportionally and keep their aspect ratio. Using the Image resize lib, something like this could be the function to do the job:
public static byte[] resizeProportionaly(byte[] imageFile, int pWidth, int pHeight, string crop = "&crop=auto")
{
MemoryStream stream = new MemoryStream(imageFile);
stream.Seek(0, SeekOrigin.Begin);
ResizeSettings resizeCropSettings = new ResizeSettings(string.Format("bgcolor=FFFFFF&width={0}&height={1}&format=jpg" + crop, pWidth, pHeight));
Image originalImage = Image.FromStream(stream, true, false);
Image resizedImage = ImageBuilder.Current.Build(originalImage, resizeCropSettings);
MemoryStream ms = new MemoryStream();
resizedImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
and in your handler something like this:
public void ProcessRequest (HttpContext context) {
// some init code...take care of your query strings here etc.
string cropString = "x1,y1,x2,y2"; // if you need croping?
// change height and width based on your picture type
int outWidth = 640; // whatever you need here
int outHeight = 480;
System.Data.DataRow data = GetDBPhotoRecord(photoId);
byte[] photoStream = (byte[])data[mxmPhotos.Photo];
// if you dont need cropping just remove the last cropString parameter
byte[] outStream = resizeProportionaly(photoStream, outWidth, outHeight, cropString);
// ...
context.Response.Buffer = true;
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(7));
context.Response.BinaryWrite(outStream);
}
I am using the below code to create bitmap. Image is getting created but not with the specified size. Is there any issue with code?
public class ProcessImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var bmpOut = new Bitmap(100, 100);
var request = (HttpWebRequest)WebRequest.Create("http://media.zenfs.com/en_us/Sports/ap/201305061639599673916-p2.jpeg");
request.AllowWriteStreamBuffering = true;
var response = (HttpWebResponse) request.GetResponse();
var myStream = response.GetResponseStream();
var b = new Bitmap(myStream);
var g = Graphics.FromImage(bmpOut);
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(b,0,0,50, 50);
context.Response.ContentType = "image/png";
var stream = new MemoryStream();
b.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
b.Dispose();
stream.WriteTo(HttpContext.Current.Response.OutputStream);
//context.Response.Write("Hello World");
}
private Bitmap ResizeImage(Image image, int width, int height)
{
Bitmap result = new Bitmap(width, height);
result.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(result))
{
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawImage(image, 0, 0, result.Width, result.Height);
}
return result;
}
Following is the code to retrieve image from database and then saving it to a folder.
public string BinarytoNewsImage(int ID)
{
byte[] btimage = null;
string image = "";
string filename = null;
int mediaid;
DataSet dsNews = new DataSet();
adp = new SqlDataAdapter("Select Top 1 * from tblNew Where intNewId=" + ID, offcon);
adp.Fill(dsNews, "tblNews1");
if (dsNews.Tables["tblNews1"].Rows.Count > 0)
{
if (dsNews.Tables["tblNews1"].Rows[0]["strImage"] != DBNull.Value)
{
btimage = (byte[])dsNews.Tables["tblNews1"].Rows[0]["strImage"];
mediaid = Convert.ToInt32(dsNews.Tables["tblNews1"].Rows[0]["intMediaId"].ToString());
filename = dsNews.Tables["tblNews1"].Rows[0]["strfilename"].ToString();
image = BinarytoImage(btimage, mediaid);
}
else
{
filename = dsNews.Tables["tblNews1"].Rows[0]["strfilename"].ToString();
image = "http://www.patrika.com/media/" + filename;
}
}
return image;
}
public string BinarytoImage(byte[] stream, int ID)
{
string ImagePath = "";
string Image = ID + ".jpg";
var URL = System.Configuration.ConfigurationManager.AppSettings["ImagePath"].ToString();
string FolderName = new Uri(URL).LocalPath;
var help = HttpContext.Current.Server.MapPath(FolderName);
if (Directory.Exists(HttpContext.Current.Server.MapPath(FolderName)))
{
string[] files = Directory.GetFiles(HttpContext.Current.Server.MapPath(FolderName), ID + ".jpg");
if (files.Length > 0)
{
ImagePath = URL + ID + ".jpg";
}
else
{
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
img.Save(help + ID + ".jpg", System.Drawing.Imaging.ImageFormat.Gif);
img.Dispose();
img = null;
ImagePath = URL + ID + ".jpg";
}
}
}
return ImagePath;
}
Everything is working fine the images are saving to a folder but my problem is images are getting blur after retrieval.
I just don't know the reason as when I am using another code for retrieval than images are coming fine but are not saved to folder:
DataSet dsNews = new DataSet();
adp = new SqlDataAdapter("Select Top 1 * from tblNew Where intNewId=901371", con);
adp.Fill(dsNews, "tblNews1");
if (dsNews.Tables["tblNews1"].Rows[0]["strImage"] != DBNull.Value)
{
byte[] btimage = (byte[])dsNews.Tables["tblNews1"].Rows[0]["strImage"];
Response.ContentType = "image/jpeg";
Response.BinaryWrite(btimage);
}
I need those images to be saved to folder so that I don't have to call database after once image comes.
Wouldn't it help to change this line
img.Save(help + ID + ".jpg", System.Drawing.Imaging.ImageFormat.Gif);
to store it as JPEG rather? as that's the source format
EDIT:
Your are not moving the stream pointer back to the start.
Try change these lines:
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
...
To
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
MS.Seek(0, SeekOrigin.Begin);
System.Drawing.Image img = System.Drawing.Image.FromStream(MS);
...
I write the common method, all is ok.
Maybe your byte[]stream is not right,pls check.
byte[] stream = File.ReadAllBytes(#"D:\YWG\123.jpg");
using (MemoryStream MS = new MemoryStream(stream, 0, stream.Length))
{
MS.Write(stream, 0, stream.Length);
using (Image img = Image.FromStream(MS))
{
img.Save(#"D:\dd.jpg", System.Drawing.Imaging.ImageFormat.Gif);
}
}
I see the dest file "dd.jpg" is ok.
I have a monitoring system and I want to save a snapshot from a camera when alarm trigger. I have tried many methods to do that…and it’s all working fine.
string ImageName = #"E:\snapshot\pic" + imageid + ".jpg";
WebClient webclient = new WebClient();
webclient.Credentials = new NetworkCredential("admin", "pass");
Uri url = new Uri("http://" + ip + "/cgi-bin/cmd/encoder?SNAPSHOT");
webclient.DownloadFileAsync(url, ImageName);
webclient.Dispose();
the image coming from the cam is(1280*1024). i want to crop the image to get (500*500) Pixel
private void button2_Click(object sender, EventArgs e)
{
string ImageFrom = #"c:\3.jpg";
byte[] imageData = ReadFile(ImageFrom);
byte[] data = CropPicture(imageData, 500, 500);
SqlConnection cn = new SqlConnection("Data Source=.;Initial Catalog=test;Integrated Security=True");
string qry = "insert into val (id,img) values (#OriginalPath, #ImageData)";
SqlCommand SqlCom = new SqlCommand(qry, cn);
SqlCom.Parameters.Add(new SqlParameter("#OriginalPath",(object)"123"));
SqlCom.Parameters.Add(new SqlParameter("#ImageData", (object)data));
cn.Open();
SqlCom.ExecuteNonQuery();
}
byte[] ReadFile(string sPath)
{
byte[] data = null;
FileInfo fInfo = new FileInfo(sPath);
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
data = br.ReadBytes((int)numBytes);
return data;
}
public static byte[] CropPicture(byte[] imgFile, int targetW, int targetH)
{
Image imgPhoto = Image.FromStream(new MemoryStream(imgFile));
int targetX = (imgPhoto.Width - targetW) / 2;
int targetY = (imgPhoto.Height - targetH) / 2;
Bitmap bmpPhoto = new Bitmap(targetW, targetH, PixelFormat.Format24bppRgb);
bmpPhoto.SetResolution(80, 60);
Graphics gfxPhoto = Graphics.FromImage(bmpPhoto);
gfxPhoto.SmoothingMode = SmoothingMode.AntiAlias;
gfxPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfxPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;
gfxPhoto.DrawImage(imgPhoto, new Rectangle(0, 0, targetW, targetH), targetX, targetY, targetW, targetH, GraphicsUnit.Pixel);
MemoryStream mm = new MemoryStream();
bmpPhoto.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
// Dispose of all the objects to prevent memory leaks
imgPhoto.Dispose();
bmpPhoto.Dispose();
gfxPhoto.Dispose();
return mm.GetBuffer();
}
then insert it in the sql database
i got a code to crop the image.and i know how to insert image into sql database
but it all need to read the image as a file in the pc.
i stream the image then save it
then get it and crop it and insert it into db
PLEASE can any one tell me how to get the stream without the need to save it
You should be able to use something like this... (not tested)
Image img = Image.FromStream((new WebClient()).OpenRead("a"));