AForge.Video.DirectShow bitmap arg ArgumentException - directshow

I'm trying to develop a simple application where I load a video file, and then to display it on my screen frame by frame.
To load the video file I use this code:
FileVideoSource fileVideo = new FileVideoSource(myVideoSource);
fileVideo.NewFrame += fileVideo_NewFrame;
fileVideo.Start();
And then, at the fileVideo_NewFrame, I capture each frame like this:
if (SynchronizationContext.Current != uiContext)
{
uiContext.Post(delegate { fileVideo_NewFrame(sender, eventArgs);}, null);
return;
}
Bitmap bitmap = eventArgs.Frame;
PictureBoxvideo.Image = new Bitmap(bitmap);
bitmap.Dispose();
But I'm receiving System.ArgumentException (so excplicit...). If I stop debugging on the fileVideo I can see this:
The Bitmap seems to not have filled the values.
Any idea on why the video it's not loading fine?
Thanks for help!

I could solve it with the solution posted here.
FileVideoSource fileVideo = new FileVideoSource(dialog.FileName);
AsyncVideoSource asyncVideoSource = new AsyncVideoSource(fileVideo);
asyncVideoSource.NewFrame += asyncVideoSource_NewFrame;
asyncVideoSource.Start();
private void asyncVideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Image temp = PictureBoxvideo.Image;
Bitmap bitmap = eventArgs.Frame;
PictureBoxvideo.Image = new Bitmap(bitmap);
if (temp!= null) temp.Dispose();
bitmap.Dispose();
}

Related

Image resizing script is not returning a proper stream for further handling

Current project:
ASP.NET 4.5.2
MVC 5
I am trying to leverage the TinyPNG API, and if I just pipe the image over to it, it works great. However, since the majority of users will be on a mobile device, and these produce images at a far higher resolution than what is needed, I am hoping to reduce the resolution of these files prior to them being piped over to TinyPNG. It is my hope that these resized images will be considerably smaller than the originals, allowing me to conduct a faster round trip.
My code:
public static async Task<byte[]> TinyPng(Stream input, int aspect) {
using(Stream output = new MemoryStream())
using(var png = new TinyPngClient("kxR5d49mYik37CISWkJlC6YQjFMcUZI0")) {
ResizeImage(input, output, aspect, aspect); // Problem area
var result = await png.Compress(output);
using(var reader = new BinaryReader(await (await png.Download(result)).GetImageStreamData())) {
return reader.ReadBytes(result.Output.Size);
}
}
}
public static void ResizeImage(Stream input, Stream output, int newWidth, int maxHeight) {
using(var srcImage = Image.FromStream(input)) {
var newHeight = srcImage.Height * newWidth / srcImage.Width;
if(newHeight > maxHeight) {
newWidth = srcImage.Width * maxHeight / srcImage.Height;
newHeight = maxHeight;
}
using(var newImage = new Bitmap(newWidth, newHeight))
using(var gr = Graphics.FromImage(newImage)) {
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
newImage.Save(output, ImageFormat.Jpeg);
}
}
}
So the ResizeArea is supposed to accept a stream and output a stream, meaning that the TinyPNG .Compress() should work just as well with the output as it would with the original input. Unfortunately, only the .Compress(input) works -- with .Compress(output) TinyPNG throws back an error:
400 - Bad Request. InputMissing, File is empty
I know TinyPNG has its own resizing routines, but I want to do this before the image is sent out over the wire to TinyPNG so that file size (and therefore transmission time) is reduced as much as possible prior to the actual TinyPNG compression.
…Aaaaand I just solved my problem by using another tool entirely.
I found ImageProcessor. Documentation is a royal b**ch to get at because it only comes in a Windows *.chm help file (it’s not online… cue one epic Whisky. Tango. Foxtrot.), but after looking at a few examples it did solve my issue quite nicely:
public static async Task<byte[]> TinyPng(Stream input, int aspect) {
using(var output = new MemoryStream())
using(var png = new TinyPngClient("kxR5d49mYik37CISWkJlC6YQjFMcUZI0")) {
using(var imageFactory = new ImageFactory()) {
imageFactory.Load(input).Resize(new Size(aspect, 0)).Save(output);
}
var result = await png.Compress(output);
using(var reader = new BinaryReader(await (await png.Download(result)).GetImageStreamData())) {
return reader.ReadBytes(result.Output.Size);
}
}
}
and everything is working fine now. Uploads are much faster now as I am not piping a full-sized image straight through to TinyPNG, and since I am storing both final-“full”-sized images as well as thumbnails straight into the database, I am now not piping the whole bloody image twice.
Posted so that other wheel-reinventing chuckleheads like me will actually have something to go on.

Out Of Memory exception if files to big

I'm currently working on a data-check for images. I need to request the Size (width & height) and the resolution of the image. Files over 70MB throw an "out of memory" exception on GDI Problem. Is there an alternative way to get the file-information? The same error on parse it through FromStream...
Using myfile = Image.FromFile(filePath)
...
End Using
You can use the following code to get image properties (it loads metadata only):
using (var fs = new FileStream(#"C:\Users\Dmitry\Pictures\blue-earth-wallpaper.jpg", FileMode.Open, FileAccess.Read)) {
var decoder = BitmapDecoder.Create(fs, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var size = decoder.Frames[0].PixelWidth;
var height = decoder.Frames[0].PixelHeight;
var dpiX = decoder.Frames[0].DpiX;
var dpiY = decoder.Frames[0].DpiY;
}
I found this link http://www.fastgraph.com/help/image_file_header_formats.html that tells where in the file you can find the type and its dimensions. I guess, if you use something like this below to seek and get the first few bytes and close once you are done, shouldnt be using much resources
Untested code below...
// This really needs to be a member-level variable;
private static readonly object fsLock = new object();
// Instantiate this in a static constructor or initialize() method
private static FileStream fs = new FileStream("myFile.txt", FileMode.Open);
public string ReadFile(int fileOffset) {
byte[] buffer = new byte[bufferSize];
int arrayOffset = 0;
lock (fsLock) {
fs.Seek(fileOffset, SeekOrigin.Begin);
int numBytesRead = fs.Read(bytes, arrayOffset , bufferSize);
// Typically used if you're in a loop, reading blocks at a time
arrayOffset += numBytesRead;
}
// Do what you want to the byte array and close
}

how to get the image dimesion without using bitmap or graphics object in .net

i want to create SQL CLR integrated function from Visual C#, now my requirement is user will pass a folder path as a paramter, and the function should get all the image file from the the folder, and get its basic property like FileSize, dimension etc.. but it seems SQL project does not supports System.Drawing Namespace... as i created the same function in normal project it worked fine, as i was able to use System.Drawing Namespace, but here i cannot use, System.Drawing Namespace.. so is there any other way to get the image dimension...
below is the code i have used in my normal project.
public DataTable InsertFile(string FolderPath)
{
DataTable dt = new DataTable();
DataColumn[] col = new DataColumn[] { new DataColumn("FileName", typeof(System.String)), new DataColumn("FileSize", typeof(System.Int32)), new DataColumn("FilePath", typeof(System.String)), new DataColumn("Width", typeof(System.Int32)), new DataColumn("Height", typeof(System.Int32)) };
dt.Columns.AddRange(col);
FileInfo info= null;
Bitmap bmp = null;
foreach (String s in Directory.GetFiles(FolderPath, "*.jpg"))
{
info = new FileInfo(s);
bmp = new Bitmap(s);
DataRow dr = dt.NewRow();
dr["FileName"] = Path.GetFileName(s);
dr["FileSize"] = info.Length / 1024;
dr["FilePath"] = s;
dr["Width"] = bmp.Width;
dr["Height"] = bmp.Height;
dt.Rows.Add(dr);
}
return dt;
}
does anyone have any idea how to get image dimension without using System.Drawing Namespace.
wow never seen anyone try this before, but if using Drawing in a SQL project isn't allowed try reading the header info like this http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx
Edit included the code, with the change to remove the dependency on Size.
while (binaryReader.ReadByte() == 0xff)
{
byte marker = binaryReader.ReadByte();
ushort chunkLength = binaryReader.ReadLittleEndianInt16();
if (marker == 0xc0)
{
binaryReader.ReadByte();
int height = binaryReader.ReadLittleEndianInt16();
int width = binaryReader.ReadLittleEndianInt16();
return new int[] { width, height };
}
binaryReader.ReadBytes(chunkLength - 2);
}
Is the Image object any better for you?
System.Drawing.Image forSize = System.Drawing.Image.FromFile(s);
dr["Width"] = forSize.Width;
and so forth.
That any better or same problem?

Replace multiple different images on one PDF template page with itext (itextsharp)

We have an ASP.NET application that users use to generate certain reports. So far we had one PDF template that had one image on it, and we would just replace that image with our programatically generated one (graph).
We have used code from this site for that:http://blog.rubypdf.com/2007/12/12/how-to-replace-images-in-a-pdf/
Problem now is that we have two different images on one PDF page, and the code from link above selects both images on one page and replaces them all at once with our generated image.
Does anyone have any idea how to replace multiple different images on one page with itext?
Thanks
Ugh. First, let me rewrite some of that source.
PdfReader pdf = new PdfReader("in.pdf");
PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
PdfWriter writer = stp.getWriter();
Image img = Image.getInstance("image.png");
PdfDictionary pg = pdf.getPageN(1);
PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
if (xobj != null) {
for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
PdfObject obj = xobj.get(it.next());
if (obj.isIndirect()) {
PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
PdfName type = tg.getAsName(PdfName.SUBTYPE));
if (PdfName.IMAGE.equals(type)) {
PdfReader.killIndirect(obj);
Image maskImage = img.getImageMask();
if (maskImage != null)
writer.addDirectImageSimple(maskImage);
writer.addDirectImageSimple(img, (PRIndirectReference)obj);
break;
}
}
}
}
Whew. the getAs functions can save you quite a bit of knuckle-grease and make your code much clearer.
Now. You need to be able to differentiate between the various images. If you're willing to hard-code things, you could find out what the resource names are and go that route:
String imageResName[] = {"Img1", "Img2" ... };
Image img[] = {Image.getInstance("foo.png"), Image.getInstance("bar.png"), ... };
for (int i = 0; i < imageResName.length; ++i) {
PdfName curKey = new PdfName(imageResName[i]);
PdfIndirectReference ref = xobj.getAsIndirect(curKey);
PdfReader.killIndirect( ref );
Image maskImage = img[i].getImageMask();
if (maskImage != null) {
writer.addDirectImageSimple(maskImage);
}
writer.addDirectImageSimple(img[i], (PRIndirectReference)ref);
}
If you're not willing to go with hardcoded resource names (and no one would fault you, quite the opposite, particularly when the order they appear (and thus the number on the end) depends on their order in a hash map... [shudder]), you may be able to differentiate based on image width and height.
//keep the original for loop, stepping through resource names
if (PdfName.IMAGE.equals(type)) {
float width = tg.getAsNumber(PdfName.WIDTH).floatValue();
float height = tg.getAsNumber(PdfName.HEIGHT).floatValue();
Image img = getImageFromDimensions(width, height);
Image maskImage = img.getImageMask();
...
}
Just a note that sometimes the image will be nested in a form, so it is wise to make a function that will be called recursively.
Something like this:
public void StartHere()
{
PdfReader pdf = new PdfReader("in.pdf");
PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
PdfWriter writer = stp.getWriter();
Image img = Image.getInstance("image.png");
PdfDictionary pg = pdf.getPageN(1);
replaceImage(pg, writer,img);
}
private void replaceImage(PdfDictionary pg, PdfWriter writer,Image img)
{
PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
if (xobj != null) {
for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
PdfObject obj = xobj.get(it.next());
if (obj.isIndirect()) {
PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
PdfName type = tg.getAsName(PdfName.SUBTYPE));
if (PdfName.IMAGE.equals(type))
{
PdfReader.killIndirect(obj);
Image maskImage = img.getImageMask();
if (maskImage != null)
writer.addDirectImageSimple(maskImage);
writer.addDirectImageSimple(img, (PRIndirectReference)obj);
break;
}
else if(PdfName.FORM.equals(type))
{
replaceImage(tg, writer,img);
}
}
}
}

Umbraco v4 vs Cute AJAX Uploader Control

I have a custom user control that i use in a page in Umbraco CMS... since upgrading to version 4, it seems this user control wont work any longer.
The user control contains an ajax uploader control (support request post here: http://cutesoft.net/forums/53732/ShowThread.aspx#53732), which allows users to upload images, then displays the uploaded images to the user. The control and image displays are contained within an UpdatePanel, which is where this problem is - seems the data getting sent back to the updatePanel is not valid, so the client is spitting the dummy and throwing this error:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '
<!DOCTYPE html PUBL'.
I think its somethihng to do with how Master Pages is implemented in Umbraco v4 that is causing this. Any ideas as to why this may have happened, and what i can look at to try to solve it?
FYI, here's a blog post that describes the error and its possible causes:
http://weblogs.asp.net/leftslipper/archive/2007/02/26/sys-webforms-pagerequestmanagerparsererrorexception-what-it-is-and-how-to-avoid-it.aspx
i'm doing any Response.write or Response.Redirect in the updatePanel
I'm not using any response filters
I've disabled server trace
I'm not using response.transfer
But, regardless of the above, this works fine using the same usercontrol on an Umbraco v3 site, which leads me to believe its somethign to do with v4 that's caused this.
Any suggestions greatly appreciated
I know that this whole answer is not directly a fix for your problem, but more like a workaround. this is because I am not familiar with the custom control you use.
i will however take a look tonight at your problem and see if i can find a solution for the code and plugin you use currently.
in the mean time i might give you some idea of the ajax upload i am using myself.
i know its a big chunk of code, but if you are interested you can go for it :)
my example case
I have an upload control in my own website and it works perfectly with umbraco.
the form and upload are powered with jQuery (upload is handled by jQuery.AjaxUpload plugin)
and i created a generic handler inside my umbraco folder which handles the file on the server.
creating a media item in the media library for it (and in my case beeing an avatar uploader on your profile page, it also adds the newly created mediaitem to the member's avatar property)
jQuery code: (stored in script block in the head of your page, or in a separate script)
initializeChangeAvatarForm = function() {
var button = $('#submitChangeAvatar'), interval;
new AjaxUpload(button,{
action: '/umbraco/AjaxFileUpload.ashx',
name: 'myfile',
onSubmit : function(file, ext){
// change button text to uploading + add class (with animating background loading image)
button.text('Uploading').addClass('loading');
// If you want to allow uploading only 1 file at time,
// you can disable upload button
this.disable();
},
onComplete: function(file, response){
button.text('Upload nieuw').removeClass('loading');
// Although plugins emulates hover effect automatically,
// it doens't work when button is disabled
button.removeClass('hover');
window.clearInterval(interval);
// enable upload button
this.enable();
}
});
};
$(document).ready(function(){
initializeChangeMailForm();
});
html code in your body:
<div id="container"><h2>Upload Avatar</h2><button class="button" id="submitChangeAvatar" type="button">Upload new</button></div>
jQuery ajaxupload plugin: (/scripts/jQuery.ajaxupload.js)
'since this code is too long i added a link directly to the .js file i use
'and another link to the page where i got the plugin
handler .ashx: (stored inside /umbraco/AjaxFileUpload.ashx)
using System;
using System.Collections;
using System.Data;
using System.Web;
using System.Web.SessionState;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Xml;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;
namespace SH.umbServices
{
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AjaxFileUpload : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
string strResponse = "error";
try
{
//string strFileName = Path.GetFileName(context.Request.Files[0].FileName);
//string strExtension = Path.GetExtension(context.Request.Files[0].FileName).ToLower();
//string strSaveLocation = context.Server.MapPath("../images/temp") + "\\" + strFileName;
//context.Request.Files[0].SaveAs(strSaveLocation);
UmbracoSave(context);
strResponse = "success";
}
catch
{
}
context.Response.ContentType = "text/plain";
context.Response.Write(strResponse);
}
public bool IsReusable
{
get
{
return false;
}
}
#region "umbMediaItem"
protected string UmbracoSave(HttpContext context)
{
string mediaPath = "";
if (context.Request.Files[0] != null)
{
if (context.Request.Files[0].FileName != "")
{
// Find filename
string _text = context.Request.Files[0].FileName;
string _ext = Path.GetExtension(context.Request.Files[0].FileName);
string filename;
string _fullFilePath;
//filename = _text.Substring(_text.LastIndexOf("\\") + 1, _text.Length - _text.LastIndexOf("\\") - 1).ToLower();
filename = Path.GetFileName(_text);
string _filenameWithoutExtention = filename.Replace(_ext, "");
int _p = 1212; // parent node.. -1 for media root)
// create the Media Node
umbraco.cms.businesslogic.media.Media m = umbraco.cms.businesslogic.media.Media.MakeNew(
_filenameWithoutExtention, umbraco.cms.businesslogic.media.MediaType.GetByAlias("image"), User.GetUser(0), _p);
// Create a new folder in the /media folder with the name /media/propertyid
System.IO.Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.Path + "/../media/" + m.Id.ToString()));
_fullFilePath = System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.Path + "/../media/" + m.Id.ToString() + "/" + filename);
context.Request.Files[0].SaveAs(_fullFilePath);
// Save extension
//string orgExt = ((string)_text.Substring(_text.LastIndexOf(".") + 1, _text.Length - _text.LastIndexOf(".") - 1));
string orgExt = Path.GetExtension(context.Request.Files[0].FileName).ToLower();
orgExt = orgExt.Trim(char.Parse("."));
try
{
m.getProperty("umbracoExtension").Value = orgExt;
}
catch { }
// Save file size
try
{
System.IO.FileInfo fi = new FileInfo(_fullFilePath);
m.getProperty("umbracoBytes").Value = fi.Length.ToString();
}
catch { }
// Check if image and then get sizes, make thumb and update database
if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + orgExt + ",") > 0)
{
int fileWidth;
int fileHeight;
FileStream fs = new FileStream(_fullFilePath,
FileMode.Open, FileAccess.Read, FileShare.Read);
System.Drawing.Image image = System.Drawing.Image.FromStream(fs);
fileWidth = image.Width;
fileHeight = image.Height;
fs.Close();
try
{
m.getProperty("umbracoWidth").Value = fileWidth.ToString();
m.getProperty("umbracoHeight").Value = fileHeight.ToString();
}
catch { }
// Generate thumbnails
string fileNameThumb = _fullFilePath.Replace("." + orgExt, "_thumb");
generateThumbnail(image, 100, fileWidth, fileHeight, _fullFilePath, orgExt, fileNameThumb + ".jpg");
image.Dispose();
}
mediaPath = "/media/" + m.Id.ToString() + "/" + filename;
m.getProperty("umbracoFile").Value = mediaPath;
m.XmlGenerate(new XmlDocument());
Member mbr = Member.GetCurrentMember();
umbraco.cms.businesslogic.property.Property avt = mbr.getProperty("memberAvatar");
avt.Value = m.Id;
mbr.XmlGenerate(new XmlDocument());
mbr.Save();
//string commerceFileName = mediaPath;
//CommerceSave(commerceFileName);
}
}
return mediaPath;
}
protected void generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName)
{
// Generate thumbnail
float fx = (float)fileWidth / (float)maxWidthHeight;
float fy = (float)fileHeight / (float)maxWidthHeight;
// must fit in thumbnail size
float f = Math.Max(fx, fy); //if (f < 1) f = 1;
int widthTh = (int)Math.Round((float)fileWidth / f); int heightTh = (int)Math.Round((float)fileHeight / f);
// fixes for empty width or height
if (widthTh == 0)
widthTh = 1;
if (heightTh == 0)
heightTh = 1;
// Create new image with best quality settings
Bitmap bp = new Bitmap(widthTh, heightTh);
Graphics g = Graphics.FromImage(bp);
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// Copy the old image to the new and resized
Rectangle rect = new Rectangle(0, 0, widthTh, heightTh);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
// Copy metadata
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codec = null;
for (int i = 0; i < codecs.Length; i++)
{
if (codecs[i].MimeType.Equals("image/jpeg"))
codec = codecs[i];
}
// Set compresion ratio to 90%
EncoderParameters ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
// Save the new image
bp.Save(thumbnailFileName, codec, ep);
bp.Dispose();
g.Dispose();
}
#endregion
}
}
I hope this shed some light on what i use.
Pfew,..That's a lot of code.
I was only interessted in saving media in Umbraco but it's nice to see a jQuery upload too.
What upload jQuery lib your using? I've found serveral.
You could make the code a bit simpler by using Path.Combine, FileInfo.Extension merging if's and a few extra variables here an there. But hey I've got Resharper to make my live easier.

Resources