I'm trying to read the width and height of a locally loaded image. This seems to work for images that do not exceed the dimensions limited by the Flash Player 10 (http://kb2.adobe.com/cps/496/cpsid_49662.html), but as soon as the images are bigger, the width and height remain 0. The strange thing is that now and then, I can read the dimension of these bigger images, but most of the times not. I understand that this might be because of the player limitation, but then I would at least expect the error to be consistent.
I want to check this since there is no use in loading such a big image as it will not be displayed anyway, but it would be good to provide a detailed error message to the user.
Any ideas on this?
Here's the code that I use to load the image locally and read the dimension:
private function chooseImageButton_clickHandler(event:Event):void {
var allowedTypes:String = "*.jpg;*.png";
m_uploadFileReference = new FileReference();
m_uploadFileReference.addEventListener(Event.SELECT, uploadFileReference_selectHandler);
m_uploadFileReference.addEventListener(Event.COMPLETE, uploadFileReference_completeHandler);
m_uploadFileReference.browse([new FileFilter("Image Files (" + allowedTypes + ")", allowedTypes)]);
}
private function uploadFileReference_selectHandler(event:Event):void {
m_uploadFileReference.load();
}
private function uploadFileReference_completeHandler(event:Event):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.loadBytes(m_uploadFileReference.data);
}
private function onImageLoaded(e:Event):void {
trace(e.target.content.width);
}
You can skip loading the entire image and just reading the headers with this class.
var je : JPGSizeExtractor = new JPGSizeExtractor( );
je.addEventListener( JPGSizeExtractor.PARSE_COMPLETE, sizeHandler );
je.extractSize( your_jpg_file.jpg );
function sizeHandler( e : Event ) : void {
trace( "Dimensions: " + je.width + " x " + je.height );
}
Should be both faster and more reliable.
I would at least expect the error to be consistent.
Well, at least Adobe are pretty clear on that point: "...if you choose to develop beyond these boundaries we cannot guarantee consistent behavior."
Could you perhaps upload your image to a php pre-processor? (Here's one from Google)
Related
I am trying to understand and implement a piece of code for Tiff compression.
I have already used 2 separate techniques - Using 3rd party dll's LibTiff.NEt (1st method is bulky) and the Image save method, http://msdn.microsoft.com/en-us/library/ytz20d80%28v=vs.110%29.aspx (2nd method works only on windows 7 machine but not on windows 2003 or 2008 server).
Now I am looking to explore this 3rd method.
using System.Windows.Forms;
using System.Windows.Media.Imaging;
using System.Drawing.Imaging;
int width = 800;
int height = 1000;
int stride = width/8;
byte[] pixels = new byte[height*stride];
// Try creating a new image with a custom palette.
List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
colors.Add(System.Windows.Media.Colors.Red);
colors.Add(System.Windows.Media.Colors.Blue);
colors.Add(System.Windows.Media.Colors.Green);
BitmapPalette myPalette = new BitmapPalette(colors);
// Creates a new empty image with the pre-defined palette
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
System.Windows.Media.PixelFormats.BlackWhite,
myPalette,
pixels,
stride);
FileStream stream = new FileStream(Original_File, FileMode.Create);
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.Ccitt4;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
But I don't have a full understanding of what is happening here.
There is obviously some kind of a memory stream that the compression technique is being applied to. But I am a bit confused how to apply this to my specific case. I have an original tiff file, I want to use this method to set its compression to CCITT and save it back. Can anyone help?
I copied the above code and the code runs. But my end output file is a solid black background image. Although on the positive side it is of the correct compression type.
http://msdn.microsoft.com/en-us/library/ms616002%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.tiffcompressoption%28v=vs.100%29.aspx
http://social.msdn.microsoft.com/Forums/vstudio/en-US/1585c562-f7a9-4cfd-9674-6855ffaa8653/parameter-is-not-valid-for-compressionccitt4-on-windows-server-2003-and-2008?forum=netfxbcl
LibTiff.net is a little bulky because it's based off LibTiff, which has its own set of problems.
My company (Atalasoft) has the ability to do that fairly easily, and the free version of the SDK will do the task you want with a few restrictions. The code for re-encoding a file would look like this:
public bool ReencodeFile(string path)
{
AtalaImage image = new AtalaImage(path);
if (image.PixelFormat == PixelFormat.Pixel1bppIndexed)
{
TiffEncoder encoder = new TiffEncoder();
encoder.Compression = TiffCompression.Group4FaxEncoding;
image.Save(path, encoder, null); // destroys the original - use carefully
return true;
}
return false;
}
Things you should be aware of:
this code will only work properly on 1bpp images
this code will NOT work properly on multi-page TIFFs
this code does NOT preserve metadata within the original file
and I would want the code to at least check for that. If you are inclined to have a solution that better preserves what's in the content of the file, you would want to do this:
public bool ReencodeFile(string origPath, string outputPath)
{
if (origPath == outputPath) throw new ArgumentException("outputPath needs to be different from input path.");
TiffDocument doc = new TiffDocuemnt(origPath);
bool needsReencoding = false;
for (int i=0; i < doc.Pages; i++) {
if (doc.Pages[i].PixelFormat == PixelFormat.Pixel1bppIndexed) {
doc.Pages[i] = new TiffPage(new AtalaImage(origPath, i, null), TiffCompression.Group4FaxEncoding);
needsReencoding = true;
}
}
if (needsReendcoding)
doc.Save(outputPath);
return needsReencoding;
}
This solution will respect all pages within the document as well as document metadata.
Hi I am using selenium webdriver 2.25.0 & faceing the some serious issues,
how to find broken images in a page using Selenium Webdriver
How to find the image is replace by another image having same name (This is also bug) using webdriver.
Thanks in advance for your value-able suggestions.
The accepted answer requires that you use a proxy with an extra call to each image to determine if the images are broken or not.
Fortunately, there is another way you can do this using only javascript (I'm using Ruby, but you can use the same code in any executeScript method across the WebDriver bindings):
images = #driver.find_elements(:tag_name => "img")
broken_images = images.reject do |image|
#driver.execute_script("return arguments[0].complete && typeof arguments[0].naturalWidth != \"undefined\" && arguments[0].naturalWidth > 0", image)
end
# broken_images now has an array of any images on the page with broken links
# and we want to ensure that it doesn't have any items
assert broken_images.empty?
To your other question, I would recommend just taking a screenshot of the page and having a human manually verify the resulting screenshot has the correct images. Computers can do the automation work, but humans do have to check and verify its results from time to time :)
The next lines are not optimized, but they could find broken images:
List<WebElement> imagesList = _driver.findElements(By.tagName("img"));
for (WebElement image : imagesList)
{
HttpResponse response = new DefaultHttpClient().execute(new HttpGet(image.getAttribute("src");));
if (response.getStatusLine().getStatusCode() != 200)
// Do whatever you want with broken images
}
Regarding your second issue, I think I didn't understand it correctly. Could you explain it with more detail?
Based on the other answers, the code that eventually worked for me in an angular / protractor / webdriverjs setting is:
it('should find all images', function () {
var allImgElts = element.all(by.tagName('img'));
browser.executeAsyncScript(function (callback) {
var imgs = document.getElementsByTagName('img'),
loaded = 0;
for (var i = 0; i < imgs.length; i++) {
if (imgs[i].naturalWidth > 0) {
loaded = loaded + 1;
};
};
callback(loaded);
}).then(function (loadedImagesCount) {
expect(loadedImagesCount).toBe(allImgElts.count());
});
});
The webdriver code counts the number of img elements, and the function executed within the browser context counts the number of successfully loaded elements. These numbers should be the same.
So there's been a new "feature" in the flash player since version 10.1, which reduces the player's framerate to 2 fps when the application window is out of view. This is good news for performance, but it can break some functionality, such as the Timer class.
I have an application which uses a Timer to display a countdown. Given the nature of the application, it is required for the Timer to complete its countdown even if the user is not there to see it. Imagine that you need to give the user only 10 seconds to perform a task. If the user minimizes the window halfway through the counter, they can take as much time as they want and still have 5 seconds left when they return to the window. This apparently can not be avoided with the newer flash players.
In Air applications there is the backgroundFrameRate property which can be set to prevent this behavior, but this is part of the WindowedApplication class, so it seems that it is not available in a web application. Does anyone know a way to keep a constant frame rate even when the window is not visible? Thanks
Setting the wmode parameter of the embedded swf to opaque will prevent the framerate throttling.
Brian
I've not tried myself, but maybe you can try to force the framerate onDeactivate:
stage.addEventListener(Event.DEACTIVATE, onDeactivate);
function onDeactivate (e:Event):void
{
//eg myFrameRate=24
stage.frameRate = myFrameRate;
}
Let me know if this works.
Testing with:
private var numer:int = 0;
private var prevNumer:int = 0;
private var timer:Timer = new Timer( 1000, 0 )
[...]
var tf:TextField = new TextField ();
addChild (tf);
addEventListener ( Event.ENTER_FRAME, onEnterFrame )
timer.addEventListener (TimerEvent.TIMER, onTimer )
timer.start()
function onTimer ( e:TimerEvent ):void
{ tf.appendText (' ' + (numer - prevNumer)); prevNumer = numer;}
function onEnterFrame ( e:Event ):void { numer++ }
shows clearly, that when You see the flash, tf appends numbers equal to Your FPS. If timer would get changed together with FPS, You wouldn't see a difference when minimizing a window. But, coming back You see 2 2 2 2 2, that is, FPS dropped to 2.
onDeactivate solution by AsTheWormTurns doesn't work. Event is fired, but fps not changed.
wmode=opaque solution by Mr Brian Bishop doesn't work too
something obvious to try: change onEnterFrame function to set FPS:
function onEnterFrame ( e:Event ):void { numer++; stage.frameRate = 30 }
Obviously You can't set FPS when flash is not visible! Well, You can't set FPS unless You set it to 1.
Workaround to Your problem is simple, just make another timer similar to this above but with additional conditional:
function onTimer ( e:TimerEvent ):void {
if ( numer - prevNumer == 2 ) adjustOriginalTimer();
tf.appendText (' ' + (numer - prevNumer)); prevNumer = numer;
}
E: You can read about it here: http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-8000.html
I am loading multiple images into a class instance and I would like to keep track of how large the complete amount of loaded data is at any given point.
I have grabbed the totalbytes from my directory of images via a PHP script... but collecting the new bytes from the ProgressEvent on each image seems tricky for some reason.
Let's assume that the totalBytes variable is correct and that I am totally unfamiliar with the way that ProgressEvent works...
Does an event get fired every time ProgressEvent gets a new byte?
If not, how do I keep track of the current total bytes?
I'm sure I've got it wrong, but here's what I am trying:
public function thumbProgress(e:ProgressEvent):void
{
//trying to check for a new data amount, in case the progress event updates
//insignificantly
if(e.bytesLoaded != this.newByte)
{
this.newByte = this.currentLoadedBytes - e.bytesLoaded;
this.currentLoadedBytes += this.newByte;
this.textprog.text = this.currentLoadedBytes.toString() + " / " + this.totalBytes.toString();
this.newByte = e.bytesLoaded;
}
if(this.currentLoadedBytes >= this.totalBytes)
{
this.textprog.text = "done loading.";
}
}
Are you using a flash.display.Loader to load your images? Then you can use the Loader.contentLoaderInfo.bytesTotal property, which should contain the right number of bytes once the image has finished loading. The Loader.contentLoaderInfo property references the LoaderInfo instance of the loaded content, which contains a lot of data about the file, such as total size, the amount that have finished loading, and the URL from which it was loaded. Check out the LoaderInfo reference.
Sum the values of this property for all of your loaders, to get the total amount of loaded data, e.g. in the COMPLETE handler for each loader.
Cheers
Maybe this isn't exactly an answer to your question, but I suggest that you take a look at bulk-loader library. It will greatly simplify loading multiple assets. Here is a quick and dirty example of usage. We've got simple application with progressbar and we want to update progressbar as images are downloaded.
<mx:Script>
<![CDATA[
import br.com.stimuli.loading.BulkProgressEvent;
import br.com.stimuli.loading.BulkLoader;
private function init():void {
loadImages();
}
private function loadImages():void {
var loader : BulkLoader = new BulkLoader("main-site");
loader.add("http://www.travelblog.org/Wallpaper/pix/tb_turtle_diving_sipadan_malaysia.jpg", {id:"a"});
loader.add("http://www.travelblog.org/Wallpaper/pix/tb_fiji_sunset_wallpaper.jpg", {id:"b"});
loader.addEventListener(BulkLoader.COMPLETE, onAllLoaded);
loader.addEventListener(BulkLoader.PROGRESS, onAllProgress);
loader.addEventListener(BulkLoader.ERROR, onAllError);
loader.start();
}
private function onAllLoaded(evt : BulkProgressEvent):void {
}
private function onAllProgress(evt : BulkProgressEvent):void {
progressBar.setProgress(evt.ratioLoaded * 100, progressBar.maximum);
}
private function onAllError():void {
}
]]>
</mx:Script>
<mx:ProgressBar x="304" y="360" width="582" id="progressBar" mode="manual" minimum="0" maximum="100"/>
I have an image uploader and cropper which creates thumbnails and I occasionally get an Out Of Memory exception on the following line:
Dim bm As Bitmap = System.Drawing.Image.FromFile(imageFile)
The occurance of the error is tiny and very rare, but I always like to know what might be causing it. The imageFile variable is just a Server.MapPath to the path of the image.
I was curious if anyone had experience this issue previously and if they had any ideas what might be causing it? Is it the size of the image perhaps?
I can post the code if necessary and any supporting information I have, but would love to hear people's opinions on this one.
It's worth knowing that OutOfMemoryException doesn't always really mean it's out of memory - particularly not when dealing with files. I believe it can also happen if you run out of handles for some reason.
Are you disposing of all your bitmaps after you're done with them? Does this happen repeatably for a single image?
If this wasn't a bad image file but was in fact the normal issue with Image.FromFile wherein it leaves file handles open, then the solution is use Image.FromStream instead.
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (Image original = Image.FromStream(fs))
{
...
Using an explicit Dispose(), a using() statement or setting the value to null on the bitmap doesn't solve the issue with Image.FromFile.
So if you App runs for a time and opens a lot of files consider using Image.FromStream() instead.
I hit the same issue today while creating Thumbnail images for a folder full of images. It turns out that the "Out Of Memory" occured exactly at the same point each time. When I looked at the folder with the images to be converted I found that the file that was creating the problem was thumbs.db. I added some code to make sure that only image files were being converted and the issue was resolved.
My code is basically
For Each imageFile as FileInfo in fileList
If imageFile.Extension = ".jpg" Or imageFile.Extension = ".gif" Then
...proceed with the conversion
End If
Next
Hope this helps.
Also check if you haven't opened the same file somewhere else. Apparently, when you open a file twice (even with File.Open()) OutOfMemoryException is thrown too...
Also you can open it in read mode, (if you want to use it in two place same time)
public Image OpenImage(string previewFile)
{
FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Image.FromStream(fs);
}
This happens when the image file is corrupted. It is a bad error message, because memory has nothing to do with it. I haven;t worked out the coding, but a try/catch/finally will stop the program from abending.
I had a similar problem today when I was trying to resize an image and then crop it, what happened is I used this code to resize the image.
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
And then this code for the crop...
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea,
bmpImage.PixelFormat);
return (Image)(bmpCrop);
}
Then this is how I called the above code...
Image img = Image.FromFile(#"C:\Users\****\Pictures\image.jpg");
img = ImageHandler.ResizeImage(img, new Size(400, 300));
img = ImageHandler.CropImage(img, new Rectangle(0, 25, 400, 250));
long quality = 90;
I kept getting errors on the crop part, the resizer worked fine!
Turns out, what was happening inside the resizer was throwing errors in the crop function. The resized calculations were making the actual dimensions of the image come out to be like 399 rather than 400 that I passed in.
So, when I passed in 400 as the argument for the crop, it was trying to crop a 399px wide image with a 400px width bmp and it threw the out of memory error!
Most of the above code was found on http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing
If an image is an icon then different loading handling is required, like in next function:
public static Image loadImage(string imagePath)
{
Image loadedImage = null;
if (!File.Exists(imagePath)) return loadedImage;
try
{
FileInfo fileInfo = new FileInfo(imagePath);
if (fileInfo.Extension.Equals(".jpg") || fileInfo.Extension.Equals(".jpeg") ||
fileInfo.Extension.Equals(".bmp") || fileInfo.Extension.Equals(".png") ||
fileInfo.Extension.Equals(".gif"))
{
loadedImage = Image.FromFile(imagePath);
}
else if (fileInfo.Extension.Equals(".ico"))
{
Bitmap aBitmap = Bitmap.FromHicon(new
Icon(imagePath, new Size(200, 200)).Handle);
loadedImage = ImageFuncs.ResizeImage(aBitmap, new Size(30, 30));
}
}
catch (Exception eLocal)
{
MessageBox.Show(imagePath + " loading error: " + eLocal.Message);
}
return loadedImage;
}
I had the same problem with a utility I wrote to convert TIFF(s) to PDF(s). Often I would get the "out of memory" error on the same line as you.
System.Drawing.Image.FromFile(imageFile)
Then I discovered the error only happened when the file extension was ".tiff" and worked fine after I renamed it with an extension of ".tif"
I have had the same issue, before looking else where in the code wanted to make sure if I can open the Image with any Image viewer and figured out that the Image is corrupted/damaged though it's a .PNG file with 1KB size. Added a new Image in the same location, then It worked fine.
I am having same problem batch processing Tiff files. Most of the files aren't throwing an exception but few files are throwing "Out of Memory" exception in ASP.NET 4.0. I have used binary data to find out why just for few files and from within same folder. It can't be permission issue for ASP.NET ASPNET or NETWORK SERVICE account because other files are working file.
I have opened iTextSharp.text.Image class and found that there are many overloaded methods for GetInstance(). I have resolved my problem using following code: note: catch block will run for problematic files.
iTextSharp.text.Image image = null;
try
{
var imgStream = GetImageStream(path);
image = iTextSharp.text.Image.GetInstance(imgStream);
}
catch {
iTextSharp.text.pdf.RandomAccessFileOrArray ra = null;
ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(path);
image = iTextSharp.text.pdf.codec.TiffImage.GetTiffImage(ra, 1);
if (ra != null)
ra.Close();
}
If you're serving from IIS, try recycling the Application Pool. This solved a similar image upload "Out of Memory" error for me.
I created a minimal form example that still gives me errors.
private void button1_Click(object sender, EventArgs e)
{
string SourceFolder = ImageFolderTextBox.Text;
string FileName = "";
DirectoryInfo Mydir = new DirectoryInfo(SourceFolder);
FileInfo[] JPEGS = Mydir.GetFiles("*.jpg");
for (int counter = 0; counter < JPEGS.Count(); counter++)
{
FileName = Mydir + "\\" + JPEGS[counter].Name;
//using (Image MyImage = System.Drawing.Image.FromFile(FileName))
using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
StatusBtn.BackColor = Color.Green;
}
}
}
I tried both the commented out line using Image.FromFile() as well as the line using FileStream(). Both produced file errors.
The Image.FromFile() error was:
System.OutOfMemoryException: 'Out of Memory'
The filestream() error was:
System.UnaurthorizedAccessException: 'Access to the path 'E:\DCIM\100Canon\dsc_7218.jpg' is denied.
I placed a Breakpoint just prior to the lines producing the error and I am able to open the image file using the Windows image viewer. I then closed the viewer and after I advanced to the next line and get the error, I can no longer view the image with the Windows viewer. Instead, I get a message that I do not have permission to access the file. I am able to delete the file.
This error is repeatable. I've done it over 10 times. Each time, after I get the error, I delete the file used for FileName.
All files were verified to be non-corrupt.
My original code that used Image.FromFile() worked fine when I compiled it 2 years ago. In fact, the .exe file runs just fine. I made a minor change somewhere else in the code and was surprised to find that the code would not compile without this error. I tried the FileStream() method based on the information on this page.