Right now I have a form with a PictureBox on the form. I'm using two partially transparent images and trying to put one on top of the other.
sideMenuWide = rounded rectangle with transparent background (.png) [Bottom image]
labelPointer = triangle with transparent background (.png) [Top image]
Here is my approach:
// METHOD #1 //
Image img1 = Image.FromFile(#"C:\sideMenuWide.png");
Image img2 = Image.FromFile(#"C:\labelPointer.png");
picBox.Image = CombineImages(img1, img2);
// METHOD #2 //
Image imgA = RBS.Properties.Resources.sideMenuWide;
Image imgB = RBS.Properties.Resources.labelPointer;
picBox.Image = CombineImages(imgA, imgB);
And the CombineImage function: (I did not write this function, only modified)
public static Bitmap CombineImages(Image imgA, Image imgB)
{
//a holder for the result (By default, use the first image as the main size)
Bitmap result = new Bitmap(imgA.Size.Width, imgA.Size.Height);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the images into the target bitmap
graphics.DrawImage(imgA, 0, 0, imgA.Width, imgA.Height);
graphics.DrawImage(imgB, 100, 70, imgB.Width, imgB.Height);
}
return result;
}
Method #1 DOES work how I want it to, displays imgB perfectly on top of imgA.
Method #2 however shows imgA just fine but imgB is really faint.
Any ideas on how to overcome this? I would like to be able to do this using Resources instead of having to pull from a file.
If the files work when loaded, but the resources don't, then it sounds like the resx build process or the ResourceManager is doing something undesirable. I'd try embedding the files and reading them directly from a stream rather than relying on the ResourceManager to do it for you.
In your Solution Explorer, Add Existing File to add the file to your project. Get properties on the added file and set it to Embedded Resource=. (Don't add it to a resx file)
In your code, you can now get a stream containing the file's data:
Stream instream = Assembly.GetExecutingAssembly().
GetManifestResourceStream("RBS.labelPointer.png"));
(Hint: The compiler generates an obtuse name for the embedded resource, so after adding the files you can add temporary code to call Assembly.GetExecutingAssembly().GetManifestResourceNames() to get a list of them all and find the file you're interested in)
Load your bitmap/image from the stream:
Image img2 = new Bitmap(inStream);
Related
I have been tasked with capturing an image, copy it to the clipboard, and paste it to the application below. I must be able to support pretty much any rich text field, and it must preserve transparency. My current solution first renders a white background. Here is my code:
The RenderTargetBitmap contains the image that I wish to copy as a .PNG
public static void CopyImageToClipboard(RenderTargetBitmap b)
{
MemoryStream stream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(b));
encoder.Save(stream);
Bitmap bmp = new Bitmap(stream);
Bitmap blank = new Bitmap(Convert.ToInt32(b.Width), Convert.ToInt32(b.Height));
Graphics g = Graphics.FromImage(blank);
g.Clear(System.Drawing.Color.White);
System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
g.DrawImage(img, 0, 0, Convert.ToInt32(b.Width), Convert.ToInt32(b.Height));
Bitmap tempImage = new Bitmap(blank);
blank.Dispose();
img.Dispose();
bmp = new Bitmap(tempImage);
tempImage.Dispose();
System.Windows.Forms.Clipboard.SetImage(bmp);
stream.Dispose();
}
Just pick a random color to use it as background, let's say
var background = Color.FromArgb(1, 255, 1, 255);
Erase background to it:
g.Clear(background); // instead of System.Drawing.Color.White
Then make that color transparent:
Bitmap tempImage = new Bitmap(blank);
tempImage.MakeTransparent(background);
Note that also default transparent color works pretty well, no need to pick a magic color (check if you need to Clear() background, it may be - I didn't check - default bitmap background):
g.Clear(Color.Transparent);
// ...
tempImage.MakeTransparent();
EDIT Some older RTF control versions won't handle transparency and there is nothing (AFAIK) you can do for it. A half decent workaround (if you can't detect control class of paste target and read its background color) is to use Color.FromArgb(254, 255, 255, 255). White where transparency isn't supported and...completely transparent (because of MakeTransparent()) where it is.
The Windows clipboard, by default, does not support transparency, but you can put content on the clipboard in many types together to make sure most applications find some type in it that they can use. Generally, if, in addition to the normal nontransparent clipboard Bitmap format, you put the image on the clipboard in both PNG and DIB formats, most applications will be able to use at least one of them to get the image in a format they support as being transparent.
These formats are put on the clipboard in a specific way, though. They need to have their data (for png, that's not the loaded image object but the actual png file's bytes) put in a MemoryStream that is then put on the clipboard.
PNG put on the clipboard like that will be accepted by a multitude of applications, including Gimp and the newer MS Office. And of course, if you implement reading for it too, you can use it in your own application. The (rather dirty) DIB format should take care of most other applications, if they indeed support transparent image pasting at all.
I detailed how to do both the copying and the retrieving in this answer:
https://stackoverflow.com/a/46424800/395685
I'm trying to process the typical 16 megapixel images from a modern camera. Picking a random image, both the file system and my image editing software says the image is 4608 x 3456. When I load the image in C# (VS2013 .Net 4.5) using either new Bitmap(filename) or Image.FromFile(filename), I get an image successfully loaded. However, the resulting image has a size of 1613 x 1210. Now, in some cases I want to create custom size thumbnails, and this will work ok. However, I have another need where I detect "non normal" orientations and I simply want to flip/rotate for display, then save.
Saving these images (without any adjustments, just load and save) creates a valid image on disk. However, both the file system AND my image tool says the size is 1613 x 1210.
How do I load the full size image and preserve all info back to disk? Any ideas as to what I'm doing wrong? I just want to rotate the image where needed, I don't want to shrink it!
Here's a snippet of what I tried, as promised in a comment below:
Bitmap bm = new Bitmap(fileName);
Image jpg = Image.FromFile(fileName);
jpg.Save("e:\\test.jpg");
bm.Save("e:\\test2.jpg");
Both files are smaller than their original size, and match the width and height the debugger shows for both in-memory images.
Per a suggested answer, I tried this code but saw no difference in the results:
long width = 0;
long height = 0;
byte[] imageBytes = File.ReadAllBytes(fileName);
using (MemoryStream ms = new MemoryStream(imageBytes))
{
Image jpg3 = Image.FromStream(ms);
width = jpg3.Width;
height = jpg3.Height;
jpg3.Save("e:\\test3.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
}
Thanks in advance.
[EDIT]
User Error from a followup post:
While it's true I do have a 4608x3456 size image of the very picture I
am trying to load, I selected the wrong directory in my OpenFileDialog
and was actually selected a, you guessed it, 1613 x 1210 version of
this image. The code WAS loading the full thing, the silly operator
(me) was gumming it up.
Before I post, I'll try the full-size image ... yeah, it works fine.
Can you show your program code?
I downloaded 5169x3423 size sample image.
Load this image using program and when i restored it, original and new image are same.
I load image file to byte array and save it to Bitmap.
private Image LoadImage()
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.ShowDialog();
byte[] byteImage = File.ReadAllBytes(openFile.FileName);
Image myImage;
using (var ms = new MemoryStream(byteImage))
{
myImage = Image.FromStream(ms);
}
return myImage;
}
private void SaveImage(Image myImage)
{
Bitmap bmp = new Bitmap(myImage);
// Temp save location
bmp.Save("c:\\test\\myImage.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
I have a problem adding cliparts (from png files) to bmp object. I add some cliparts to a jpeg image and after I save it, I get a mistery: some cliparts are present in saved image, but some not.
Here is code how I add cliparts to image:
using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(this._image))
{
gfx.CompositingMode = CompositingMode.SourceOver;
gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.DrawImage(image, posX, posY, newWidth, newHeight);
gfx.Save();
}
Can anybode explain what am I doing wrong or why this situation appears?
edited:
it happens when I use this code inside a ASP.NET Application, when I use it in windows application everything is fine
I'm not sure if this is the cause of Your issue, but line gfx.Save() does not save the image you painted back to the image, but saves state of the Graphics object. In order to save the changes back to the image, make sure to call Image.Save() method and double check to make sure You are not restoring the previous image somewhere in the code. More information about it Graphics.Save method can be found here: http://msdn.microsoft.com/en-us/library/system.drawing.graphics.save(v=vs.100).aspx.
Update
You wrote in the comments that it's a transparency issue. If this is the cause, take a look at the code loading the clipart images from files. This also may be caused by various pixel formats used in your image files. Changing You images loading algorithm to something like this may solve the issue:
load your background image, let's say it's done like this: Image backgroundImg = new Bitmap(backgroundImgPath);
create a new empty image as a base for all the images: this._image = new Bimap(backgroundImg.Width, backgroundImg.Height, PixelFormat.Format32bppArgb);
draw the contents of backgroundImg onto this._image with gfx.CompositingMode = CompositingMode.SourceCopy;
then, you can draw the cliparts as You're doing it now (just comment out gfx.Save(); method)
Let me know if this helped.
I was wondering if someone can direct me or guide me in order to use a .gif image and convert it into a .bmp strip image file.
First, you need to get the gif's size. Then you need to find out how many frames there are.
After that you need to create a new image with Height = original height, and Width = Frames * Gif Width.
Then you must paste the original Gif's frames into the strip like so: Frame N starts at pixel N*Width.
That is if you're making a horizontal strip.
And here is the complete code for a console application:
using System.Drawing;
using System.Drawing.Imaging;
foreach (var arg in args)
{
Image gif = Image.FromFile(arg);
FrameDimension dim = new FrameDimension(gif.FrameDimensionsList[0]);
int frames = gif.GetFrameCount(dim);
Bitmap resultingImage = new Bitmap(gif.Width * frames, gif.Height);
for (int i = 0; i < frames; i++)
{
gif.SelectActiveFrame(dim, i);
Rectangle destRegion = new Rectangle(gif.Width * i, 0, gif.Width, gif.Height);
Rectangle srcRegion = new Rectangle(0, 0, gif.Width, gif.Height);
using (Graphics grD = Graphics.FromImage(resultingImage))
{
grD.DrawImage(gif, destRegion, srcRegion, GraphicsUnit.Pixel);
}
}
resultingImage.Save("res.png", ImageFormat.Png);
}
The resulting image is saved in the compiled console app binary file directory under the name res.png. You can make the app save the resulting image right where the source file is, ask whether to make a horizontal or vertical strip, etc.
Making an image strip can be easily done with Photoshop (you can get a free trial version, or Elements)
Open .gif - Photoshop will open each frame as a layer
Resize canvas to (height of the gif * layers) pixels
Remove all frame information, keep layers
Select last layer, and move it to very bottom
Select all layers and click 'Distribute vertical centers'. Now you have a perfectly arranged strip.
If you are using Photoshop, you can just export as BMP. Thats it.
The method what works for sure is:
Download an install Easy GIF Animator
Open tour gif with it and export the frames to separate files
Download and install any program which can create the layers (eg. Photoshop CS3 Little)
Create a new file width as your picture; Height = Height of Your pic. X number of pictures
Copy each pic. as a layers in to Your new file and move them one after the other.
Save it as a .png file
Download an install iPAQ 31x Image Explorer
Open Your .png in it
Save it as aRGB file (normal BMP may don't work)
DONE!!
Maybe it's not the easiest method but it gives the possibility of precise editing and allows you to make strips of icons that are on a transparent background (but not limited to icons)
Just load .gif in Bitmap and save it in .bmp. If you want to export the frames of .gif I have no idea how to do this. You can have look at this www.eggheadcafe.com/articles/stripimagefromanimatedgif.asp, it seems to be what what you're looking for.
I am looking for a solution\software that I can use in order to render buttons in real time.
That is, I have an image and text, and I want them to be an image altogether in realtime.
Thank you
You can dynamically create an image based on text using the System.Drawing namespace.
private Bitmap CreateBitmapImage(string imageText, string imageUrl)
{
Bitmap myBitmap = new Bitmap(imageUrl);
Graphics g = Graphics.FromImage(myBitmap);
g.DrawString(imageText, new Font("Tahoma", 40), Brushes.White, new PointF(0, 0));
return (objBmpImage);
}
Once you have the Bitmap object in memory you can save it to the disk and call it's location from the web.
Bitmap bmp = CreateBitmapImage("my picture", #"C:\myBasePic.bmp");
bmp.Save(#"C:\bla.png", System.Drawing.Imaging.ImageFormat.png);
It would be good if you can specify why such requirement is there. One of such scenario that I had encountered was need of image buttons with different text (round corners with shaded background) - this can easily be achieved using CSS. If you really want to combine an image and text together then you can do that at server side (using say System.Drawing types) and serve the combined image over a handler/web-service.