Image comparison to Properties.Resources.image - c#

Could you tell me why is the following condition false?
List<Image> SelectedImages = new List<Image>();
SelectedImages.Add(Properties.Resources.my_image);
if (SelectedImages[0] == Properties.Resources.my_image) // false
{
...
}
Even if I write:
SelectedImages[0] = Properties.Resources.my_image;
if (SelectedImages[0] == Properties.Resources.my_image) // false
{
...
}
How can I make this comparison work?

They're not equal because Properties.Resources makes a copy of the image and returns that copy back to your code. Everytime you get that image, you're effectively creating an entirely new Image object. It makes a copy because resources should ordinarily behave like constants. You wouldn't want your code to change the picture if you (for example) modified the picture in some way.
So what happens in your code? You end up comparing two different image objects that happen to contain the same data. .NET sees that you have two different objects and returns false. It doesn't do a "deep" comparision to see if the objects have the same data/state.
Here's a link to an article that explains what is going on at a high level: https://navaneethkn.wordpress.com/2009/10/15/understanding-equality-and-object-comparison-in-net-framework/
A quick way to workaround your problem would be to compare the Resource image and your SelectedImage Image pixel by pixel to see if they are "equal". This would obviously perform poorly. Another, more efficient way might be to build a dictionary and use a key to track where the image originally came from.

Just use the Tag property in the Image object. You can store anything you want in there. Just set up your image like this...
Image img_dbActive = MyApp.Properties.Resources.tray_icon_database_active;
img_dbActive.Tag = "tray_icon_database_active";
Image img_dbIdle = MyApp.Properties.Resources.tray_icon_database_idle;
img_dbIdle.Tag = "tray_icon_database_idle";
ToolStripStatusLabel lbl = new ToolStripStatusLabel("Database is doing something...", img_dbActive);
lbl.Image.Tag = "tray_icon_database_active";
if (lbl.Image.Tag == img_dbActive.Tag)
{
//Images match
}

Related

Compare images to see if they're the same

I'm trying to create a slot machine, i have 3 empty pictureboxes and a image list with a bunch of different pictures in it, i use a random number generator to put images into the picturebox from the image list.
Now how do i compare to see if the three random pictures are matching?
picturebox1.image == picturebox2.image;
//doesnt work because names aren't loaded to image property
picturebox1.imagelocation == picture2.imagelocation
//doesn't work because all images come from the same place.
I also can't try comparing the size or the extension because they are all the same
I don't want to use multiple random number generators to select the random pictures and compare the different random numbers. Is there a trick i can do with the imagelist that i haven't thought of
One option would be to use the Tag property... many classes have one, including Bitmap, Image, and PictureBox. You could assign a unique value to each Image.Tag...
var bmp = new Bitmap(1,1);
bmp.Tag = "uniqueTag";
pictureBox1.Image.Tag = bmp; // pictureBox1.Image.Tag == "uniqueTag"
... then check for equality:
if (pictureBox1.Image.Tag == pictureBox2.Image.Tag)
{
...
}
When your random generator picks the index of the element you will pull from your image list, store the index in the picturebox.Tag or picturebox.Text, then compare if both Tag o Text are equal.

Using Imageresizer Watermark plugin to write text: Centered, width and line feeds

I'm trying to use the watermark plugin to write text on images for my project. Right now I'm trying to find out how to set a "width" for a writing box so I can get automatic line returns. Is there a way to do this with the watermark plugin?
Also I'm trying to see if I can get a "text-align: center" effect when I'm writing my text (possibliy in relation to that set width), how could I get that setup?
I'm thinking that the alternative to this would be to have code driven line returns and centering, but this would mean that I would have to count the width of my characters and this seems like a world of pain hehe
Here is a code sample that shows what I'm doing (this currently works):
var c = Config.Current;
var wp = c.Plugins.Get<WatermarkPlugin>();
var t = new TextLayer();
t.Text = panty.Message;
t.TextColor = (System.Drawing.Color) color;
t.Font = fonts[myFunObject.Font];
t.FontSize = fontSize[myFunObject.LogoPosition];
t.Left = new DistanceUnit(5, DistanceUnit.Units.Pixels);
t.Top = new DistanceUnit(5, DistanceUnit.Units.Pixels);
wp.NamedWatermarks["myFunObjectMessage"] = new Layer[] { t };
EDIT: I also have to mention that the text I'm writing is user submitted so it's different everytime. If you want a similar case, think about thos funny cat images with funny text captions on them. This project is quite similar to that. (Minus the cats)
Thanks for the help!
Basically, System.Drawing (and therefore the current version of Watermark) are very primitive about line wrapping.
As you mentioned, you can do hacky stuff with character counting and separate MeasureString calls with loops, but the results are only barely acceptable.
You may try to fork the Watermark source code and hack support for your use case. I don't see a way to improve Watermark in a generic way without replacing the underlying graphics engine first (which may happen anyway).
System.Drawing has unsurpassed image resampling quality. Text wrapping, though, it kind of stinks at.

Simple Image Processing in WinRT

I'm working on a WinRT app that should require some image processing. I've done something similar so far but in Java, I would like to do some simple things in WinRT app also... But I can't seem to manage my way with the API...
Long story short, I have in xaml, on my page, an image that obtains an image with a file picker. Then when I click a "negativate" button, the image should get negativated.
Now, the method for the negativation button, I thought to look like this :
private void OnNegativateButtonClick(object sender, RoutedEventArgs e)
{
var imageToNegativate = ImagePanel.Source as WriteableBitmap ;
if (imageToNegativate == null) //Actually is ALWAYS null :(
{
//Wrong code here...
var bitmapSource = ImagePanel.Source as BitmapSource;
imageToNegativate = new WriteableBitmap(imageToNegativate.PixelWidth, imageToNegativate.PixelHeight);
}
imageToNegativate = ImageUtil.Negativate(imageToNegativate);
ImagePanel.Source = imageToNegativate;
}
This is very similar to this sample I found here but that sample project won't even load so I tried to open the files individually... My code is that method for negativation only there is something wrong with wb = new WriteableBitmap(bs); in his if (wb==null) { ... }.
What is the approach to take a WriteableBitmap from an image, do some pixel manipulation, and then set the source of the image with the new WriteableBitmap...
I'm saying about WriteableBitmap because my method for negativation uses one for input, does some processing and outputs it. (same type, WriteableBitmap.
Any suggestions or help is greatly appreciated, thank you!
The first problem is these lines of code:
var imageToNegativate = ImagePanel.Source as WriteableBitmap ;
if (imageToNegativate == null) //Actually is ALWAYS null :(
The null is telling you that ImagePanel.Source is not of type WriteableBitmap; your typecast failed. This is expected; the picker is going to give you something read-only, because read-only images are more performant (WinRT can do some optimizations if it knows the image's content isn't going to change). You only get a WriteableBitmap when you explicitly create one.
The body of your if block also doesn't make much sense -- you're trying to create a new, empty WriteableBitmap with the same size as the original image, and then you try to do an inverse-video on that empty image. Even if you got that far, you'd just get another empty image. You're not doing anything to keep the pixels from the original image.
You do need a WriteableBitmap to get access to the pixel buffer, but you need to make one that's a copy of the original image. Get rid of your cast and if block, and try this instead:
var imageToNegativate = new WriteableBitmap(ImagePanel.Source);
Joe is right in saying what is wrong with your code, but while his answer would probably work in WPF - the constructor he mentions indeed doesn't exist in WinRT/XAML. There is in fact no way to create a WriteableBitmap from a BitmapImage and the only way to attack it is to create a WriteableBitmap from the source of your BitmapImage.
One approach then would be to create a new 1x1-sized WriteableBitmap, then use its SetSource method on the source of your BitmapImage. Since the BitmapImage.UriSource property is a Uri and WriteableBitmap.SetSource() requires a Stream - you need to play with it a bit to find or download the actual image file and open a stream to read it. My toolkit has some extension methods (WriteableBitmap.FromBitmapImage()) to help you with it in case your images come from your application package and you could fairly easy expand it to also work with downloaded images.
The problem is - you get some inefficiencies that way - one is that you need to open and decode the file twice (which might be slow with large images on an ARM device - been there, done that), second is that you might need to re-download the file if it came from the network and third that there is a bug in WinRT/XAML that causes the UriSource property of a BitmapImage to become null if you set CacheMode of an associated Image control to BitmapCache, so you might need to track your sources separately anyway.
The best solution in many ways is to simply make sure you open the source image as a WriteableBitmap from the beginning, so you don't even have to create another bitmap if you want to change it anyway. In your case the user selects the image file, so there is only one file and it seems to have a pretty big chance of being processed afterwards so opening it as a WriteableBitmap sounds like the right thing to do.
Perhaps even if you want to keep both the original and processed version of the image - creating a new WriteableBitmap of same size and copying the pixels of the original might be faster (especially on an ARM device) than decoding a big image file twice.

Removing an image from a label at runtime

In C#, I have a 2d array of labels who's image I want to change depending on conditions. More specifically, I'd like to get it toggle between a given image and no image at all (turning it into a transparent label) and back again when conditions are met. Currently, to wipe the label clear again, I'm using this:
someLabelArray[i][j].Image = null;
But it always throws a Null Reference Exception, which makes me suspect this isn't the 'right' way to do things. Or perhaps I'm misunderstanding the error? Is there a better way to do this?
I suspect that would be absolutely fine - but that either someLabelArray is null, or someLabelArray[i] is null for whatever value of i you're using.
Simple way to test this: change your code to:
someLabelArray[i][j].Text = "foo";
which obviously has nothing to do with images, and will definitely work if your array is okay. I suspect this will fail in the same way, in which case you need to look carefully at how you're constructing your array.
If this works - well, I'll have another look then :)

Get document vector count in a pdf document?

I have a problem with some user provided pdf documents. They are created from 3d packages and are basically a HUGE list of vector lines that take and age to render (over 60 secs).
How can I generate a report on the number of vector lines present in a pdf document using iTextSharp (5.0.5)?
I can get text and image data but can't see where to get a handle on vector. They don't seems to be represented as an image.
iText[Sharp]'s parser package doesn't yet handle lineTo or curveTo commands. It's a goal, but not one that's been important enough to implement as yet. Other Things are getting attention at the moment.
If you're feeling adventurous, you should check out PdfContentStreamProcessor. In a private function populateOperators, there's a long list of commands that are currently handled (in one fashion or another).
You'd need to write similar command classes for all the line art commands (moveTo, lineTo, rect, stroke, fill, clip), and expose them in some way.
Actually, if all you want to do is COUNT the number of paths, you could just implement stroke and fill to increment some static integer[s], then check them after parsing. Should be fairly simple (I'm writing in Java, but it's easy enough to translate):
private static class CountOps implements ContentOperator {
public static int operationCount = 0;
public void invoke(PdfContentStreamProcessor processor, PdfLiteral operator, ArrayList<PdfObject> operands) {
++operationCount;
}
}
Ah! registerContentOperator is a public function. You don't need to change iText's source at all:
PdfContentStreamProcessor proc = new PdfContentStreamProcessor(null);
CountOps counter = new CountOps();
proc.registerContentOperator("S", countOps); // stroke the path
proc.registerContentOperator("s", countOps); // close & stroke
proc.registerContentOperator("F", countOps); // fill, backward compat
proc.registerContentOperator("f", countOps); // fill
proc.registerContentOperator("f*", countOps); // fill with event-odd winding rule
proc.registerContentOperator("B", countOps); // fill & stroke
proc.registerContentOperator("B*", countOps); // fill & stroke with even-odd
proc.registerContentOperator("b", countOps); // close, fill, & stroke
proc.registerContentOperator("b*", countOps); // close, fill, & stroke with even-odd
proc.processContent( contentBytes, pageResourceDict );
int totalStrokesAndFills = CountOps.operationCount; // note that stroke&fill operators will be counted once, not twice.
Something like that. Only a null RenderListener will cause a null pointer exception if you run into any text or images. You could whip up a no-op listener yourself or use one of the existing ones and ignore its output.
PS: iTextSharp 5.0.6 should be released any day now if it isn't out already.
There is no specific Vector image. Normally it is just added to the content stream which is essentially a Vector data stream for drawing the whole page.
There is a blog article which you might find useful for understanding this at http://www.jpedal.org/PDFblog/2010/11/grow-your-own-pdf-file-%E2%80%93-part-5-path-objects/

Categories