I'm working on water marking an image with another image and I can't seem to get it quite right. I'm using the Graphics library to overlay the watermark image over the photo. The photo Stream object is later uploaded as a jpg image to Amazon S3. When I go to look at the image, the photo is there but no water mark is present.
I've tried using both the DrawImage() function and DrawText() to add text as a test but no luck. Are there any issues with this part of the code? Thanks for the help.
public Stream WatermarkImage(Stream img, Stream mark, ImageType type)
{
// watermark the image
using (Image result = Image.FromStream(img))
{
Image markImage = Image.FromStream(mark);
using (Graphics g = Graphics.FromImage(result))
{
// draw mark and get result
g.DrawImage(markImage, new Point(20, 20));
Stream markedResult = new MemoryStream();
result.Save(markedResult, ImageFormat.Jpeg);
// return image
return markedResult;
}
}
}
EDIT: I actually found that this part of the code does work. Instead of saving to S3, I saved it to a file:
result.Save(#"C:\Users\Dan\Documents\Jobs\ZenPhotos\Test\test_watermark" + DateTime.Now.ToString("MM_dd_yyyy_HH_mm") + ".jpg");
The saved file shows the watermarked image. So the problem is in my upload to S3 and is unrelated.
Have a look at Automatically add watermark to an image
Instead of saving it to disk as the example demonstrates, you can return a stream instead if that's what you are after.
Hope it helps.
Cloudinary allows you to manipulate your images on-the-fly using all kind of cool transformations capabilities including overlays & watermarks. See: http://cloudinary.com/blog/adding_watermarks_credits_badges_and_text_overlays_to_images
and: http://cloudinary.com/blog/transform_your_image_overlays_with_on_the_fly_manipulation
Related
image color is becoming inverted when bitmap is converted to byte array and then to memory stream and saved. This code was part of the dynamic image creation at my site ommrudraksha.com
using (var bmp = new System.Drawing.Bitmap(width + 10, height + 10))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Flush();
bmp.Save("ss.jpg");
}
}
Above code saves properly the image.
But when the bmp is converted to memorystream and saved, the background becomes black.
Below code generates black image.
var memStream = new MemoryStream();
bmp.Save(memStream, ImageFormat.Jpeg);
var bytes = memStream.ToArray();
var ms2 = new MemoryStream(bytes);
Bitmap.FromStream(ms).Save("ss1.jpg");
Let's examine your drawing code first:
bmp.Save("ss.jpg");
In your case, this operation is actually saving as the "PNG" file format, regardless of the file name. I found this out using a hex editor. Windows is smart enough to check the file header, though, so most likely you can still preview or otherwise open it even with a wrong extension name. You can also explicitly specify an output format with a second argument.
By default, a new PNG will also be transparent. Some image formats may default to black, even though they support alpha channel (e.g. BMP and GIF). This means that if you really want to save as a BMP, you'll have to do some additional processing.
That brings me to why your output image is black. Jpeg does not support transparency at all, so when the transparent PNG was converted, the Jpeg defaulted to black. See this post.
If you need transparency, you'll have to use an image format that supports it. You may also have to clear the entire rectangle first, depending on the format.
Our users needed the ability to change images (rotate\insert scan between pages etc) so I wrote an app that allows them to load a Tiff image and edit as needed.
The problem I have is that when the image is saved it is saved as black and white and not in color. The loaded image displays in color no problem so it seems that it is the saving that is causing the issue.
This is the code I am using to save the Tiff image from an array of BitmapSource:
//create encoder
TiffBitmapEncoder tiffEncoder = new TiffBitmapEncoder();
tiffEncoder.Compression = TiffCompressOption.Ccitt4;
//loop through images and create frames
foreach (BitmapSource src in bitmapList)
{
BitmapFrame bmFrame = BitmapFrame.Create(src);
tiffEncoder.Frames.Add(bmFrame);
}
//create stream to write file
FileStream fStream = null;
try
{
fStream = new FileStream(path, FileMode.Create);
//Save Tiff image to disc
tiffEncoder.Save(fStream);
}
finally
{
if (fStream != null)
{
fStream.Close();
}
}
When I look at the properties of the original file it has a bit depth of 24 but the newly saved image has a bit depth of 1 (black and white?), is this the problem?
I am new to working with Tiffs so any guidance would be greatly appreciated.
Please let me know if you need any other info.
Tx
The images are probably converted to black/white, because of the TiffCompressOption.Ccitt4 compression in use. The CCITT compressions are intended for fax documents, and only supports black/white images.
Instead, use a more general purpose compression, like LZW or Deflate. This will let the image data pass unchanged as 24 or 32 bit color data.
I've seen articles demonstrating that the ink can be saved with the background image so that the ink is overlayed onto the image and then saved as a single image file. But, unfortunately the articles I've seen don't go into any detail about how it is done.
I can save the background image easy enough with the following statement:
axInkPicture1.Picture.Save(#"\path\to\file.gif");
...but there is no ink overlayed onto the background image
I don't know of any direct method to save the ink, but this is how I am currently doing it:
string tempPath = Path.GetTempPath();
string tempFile = tempPath + #"\file.gif";
// save to a temp file
if (axInkPicture1.Ink.Strokes.Count > 0)
{
byte[] bytes = (byte[])axInkPicture1.Ink.Save(InkPersistenceFormat.IPF_GIF, InkPersistenceCompressionMode.IPCM_Default);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (Bitmap gif = new Bitmap(ms))
{
gif.Save(tempFile);
}
}
}
This saves the ink, but there is no background image.
How do I save both the ink and image into a single file?
Any help or direction pointing is appreciated...
### EDIT
Here is what else I have tried so far
InkRectangle inkBox = axInkPicture1.Ink.GetBoundingBox();
byte[] gifbits = (byte[])axInkPicture1.Ink.Save(InkPersistenceFormat.IPF_GIF, InkPersistenceCompressionMode.IPCM_Default);
using (System.IO.MemoryStream buffer = new System.IO.MemoryStream(gifbits))
using (var inkImage = new Bitmap(buffer))
using (var picture = new Bitmap(axInkPicture1.Picture))
using (var g = Graphics.FromImage(picture))
{
g.DrawImage(inkImage, new Rectangle(inkBox.Left, inkBox.Right, axInkPicture1.Picture.Width, axInkPicture1.Height));
picture.Save(tempFile, System.Drawing.Imaging.ImageFormat.Gif);
}
...but I'm still not having any luck. This saves only the background picture and not the ink. Any ideas what I'm doing wrong?
Thanks in advance
Soooo.... after much head banging and gnashing of teeth, I finally came up with a solution to my problem, although maybe not the solution I had expected and maybe not the best solution, but it works. I'm new to the world of c# and .net so please feel free to correct me me if I state anything stupid here.
What I found was that the code in my edit above was actually working, I just couldn't see the ink because it was outside the bounds of the rectangle. Apparently rectangles acquired using the GetBoundingBox() method gives you inkSpace coordinates which are vastly different than pixel coordinates.
With that in mind, my next goal became to convert the inkSpace coordinates to pixel coordinates using the inkSpaceToPixels method. I struggled with this for awhile and could never figure out how to do this using the activex version of inkPicure or axInkPicture. It required some handle to hdcDisplay which I couldn't quite wrap my head around.
In the end, I used the .net version (Microsoft.Ink) from Microsoft.Ink.dll. The only reason I was using the activeX version to begin with was because I couldn't get the Windows Tablet PC SDK to install on my development machine for some reason. It kept complaining that I needed the WinXP Tablet PC OS to install it. I figured out that I was able to install it on another (Win7) PC and then just copy the .dlls over from that PC.
So, here is the final version that is now working... whew!
//set the temporary file paths
string tempPath = Path.GetTempPath();
string tempFile = tempPath + #"tmpFile.png";
//get the bounding box and reference point for the ink strokes (in inkspace coordinates!)
Rectangle inkBox = inkPicture1.Ink.GetBoundingBox();
Point point = new Point(inkBox.Left, inkBox.Top);
MessageBox.Show(point.X.ToString() + ", " + point.Y.ToString());//"before" coordinates
// Convert inkspace coordinates to pixel coordinates using Renderer
Graphics tempGraphics = CreateGraphics();
Microsoft.Ink.Renderer inkRenderer = new Renderer();
inkRenderer.InkSpaceToPixel(tempGraphics, ref point);;
MessageBox.Show(point.X.ToString() + ", " + point.Y.ToString());//"after" coordinates
// Clean up
tempGraphics.Dispose();
// save the ink and background image to a temp file
if (inkPicture1.Ink.Strokes.Count > 0)
{
byte[] bytes = inkPicture1.Ink.Save(PersistenceFormat.Gif, CompressionMode.NoCompression);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (Bitmap gif = new Bitmap(ms))
using (var bmp = new Bitmap(inkPicture1.BackgroundImage))
using (var g = Graphics.FromImage(bmp))
{
g.DrawImage(gif, new Rectangle(point.X, point.Y, gif.Width, gif.Height));
bmp.Save(tempFile, System.Drawing.Imaging.ImageFormat.Png);
}
}
}
Sorry for the long winded explanation, but I felt that simply posting the solution without adequate explanation would leave too many open questions...
I guess I don't have enough 50 reputation to comment, so I will answer with this comment for others that might land here after a google search like I did:
This was very helpful. I translated to VB and it worked.
After some flailing around I found the DLL at:
C:\Program Files (x86)\Common Files\Microsoft Shared\Ink\Microsoft.Ink.dll
Apparently I am not the only one to have a problem locating the DLL as there are many google entries on how to get it -- many are wrong and most are not this simple.
If you are just starting out with signature capture, remember to add a background image to your control or it will fail on this line:
Using bmp = New Bitmap(InkPicture1.BackgroundImage)
I am having trouble importing an icon into my application. I have a main form and I am trying to import to it a new icon via the Icon field in Properties.
The image is already in .ico format: this is the link to the icon I'm trying to use.
Does anyone know why Microsoft Visual Studio would be displaying this error?
Any help would be great.
I had this error recently. Some recommendations:
make sure the icon is square (16x16, 32x32)
try saving it to a PNG and using this free service for conversion : http://www.convertico.com/
We have an application that works fine on 99% of our computers, but in one laptop it pops out this error.
It looks like our issue is that the laptop user set the screen text/image size to 150%. This could cause otherwise working images no longer working. We will see whether this works.
UPDATE
A commenter seems to have the same problem. And yes, we resolved this problem by setting the screen text size to less than 150%.
After a second restart and then opening and re-saving the .ico myself in Gimp, then I was able to import it without any errors. Not too sure what caused this problem but it was just a freak error.
Credits to Xiaohuan ZHOU for the answer in this question. This function losslessly converts PNG (including transparency) to .ICO file format.
public void ConvertToIco(Image img, string file, int size)
{
Icon icon;
using (var msImg = new MemoryStream())
using (var msIco = new MemoryStream())
{
img.Save(msImg, ImageFormat.Png);
using (var bw = new BinaryWriter(msIco))
{
bw.Write((short)0); //0-1 reserved
bw.Write((short)1); //2-3 image type, 1 = icon, 2 = cursor
bw.Write((short)1); //4-5 number of images
bw.Write((byte)size); //6 image width
bw.Write((byte)size); //7 image height
bw.Write((byte)0); //8 number of colors
bw.Write((byte)0); //9 reserved
bw.Write((short)0); //10-11 color planes
bw.Write((short)32); //12-13 bits per pixel
bw.Write((int)msImg.Length); //14-17 size of image data
bw.Write(22); //18-21 offset of image data
bw.Write(msImg.ToArray()); // write image data
bw.Flush();
bw.Seek(0, SeekOrigin.Begin);
icon = new Icon(msIco);
}
}
using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
{
icon.Save(fs);
}
}
In my situation the error was because I used a stream and didn't ensure that the stream pointer is at the beginning.
Adding the following line before new Icon(stream) solved the problem:
stream.Seek(0, SeekOrigin.Begin);
I am learning C# as I write a program which interfaces with a spectrometer. I have figured out how to get a spectrum from the spectrometer and plot it on an MS chart.
How do I copy the image of the chart into the clipboard so that it can be pasted into other programs?
I'm using Visual Studio C# 2010.
I have found the chart.SaveImage method, but I would really rather copy the image to the clipboard rather than having to save it to disk. I have not found a chart.CopyPicture method.
I also figured out how to copy the raw data to clipboard as a string, which can then be pasted into an Excel worksheet and plotted, but I would rather just copy the image itself.
Additonal data:
I am able to copy the image to the clipboard using the following code:
spectrumChart2.SaveImage("Image.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Image img = Image.FromFile("Image.jpg");
System.Windows.Forms.Clipboard.SetImage(img);
Surely there is way to get the image directly Clipboard without saving and retrieving it from a disk file first. Please, please let me know how this is done (before one of my coworkers finds this kludge)!
To get image from chart control, save it to memory stream, create bitmap and then send it to clipboard:
using (MemoryStream ms = new MemoryStream())
{
chart1.SaveImage(ms, ChartImageFormat.Bmp);
Bitmap bm = new Bitmap(ms);
Clipboard.SetImage(bm);
}
Use the static method...
Clipboard.SetImage(....);
I am saving the chart images as a metafile (EMF) through a memory stream. I want to preserve the original image resolution and preserve the option to ungroup the vector images and edit them in PowerPoint. Recently, I upgraded to a very high-resolution laptop and I found that the chart image was being framed with a lot of empty space. If I paste the image into PowerPoint or Word, the pasted image will be very small. Cropping and resizing manually is not satisfactory, and I don't want to have to downgrade my screen resolution to get the images to paste larger. Here is the solution I found (below).
I am using VB.Net 2008, so the Chart.Clone method was not available. I had to implement a separate function to clone the chart, but if you have a more recent version of Visual Studio, you can uncomment the line below and delete the CloneMSChart function and the line referencing it. Here are references to the relevant websites I used to find the solution:
How to clone a chart
Exporting a high-resolution image
and here is the composite solution:
'-------------------------------------------------------------
Public Sub CopyChartImageToClipBoard(ByVal ChartToSave As Chart)
Dim originalSize As Size = ChartToSave.Size
Dim screenWidth As Integer = Screen.PrimaryScreen.Bounds.Width
Dim screenHeight As Integer = Screen.PrimaryScreen.Bounds.Height
Dim cloneChart As New Chart
Using ms As New IO.MemoryStream()
Try
'cloneChart = CType(ChartToSave.Clone, Chart)
cloneChart = CloneMSChart(ChartToSave)
cloneChart.Size = New Size(screenWidth, screenHeight) ' copy a high resolution image
cloneChart.SaveImage(ms, System.Drawing.Imaging.ImageFormat.Png)
ms.Seek(0, SeekOrigin.Begin)
Using mf As New Bitmap(ms)
Clipboard.SetImage(mf)
End Using
Finally
ms.Close()
cloneChart.Dispose()
End Try
End Using
End Sub
'------------------------------------------------------------
Public Function CloneMSChart(ByVal chart1 As Chart) As Chart
Dim myStream As New System.IO.MemoryStream
Dim chart2 As Chart = New Chart
chart1.Serializer.Save(myStream)
chart2.Serializer.Load(myStream)
Return chart2
End Function
'-------------------------------------------------------