Image manipulation - converting transparent pixels before saving as jpg - c#

I'm saving a an image with a transparent background to jpeg.
Is there a way to convert the transparent pixels to a certain color without iterating on all the pixels?
This is the code I'm using (also - is the first line a common way to do it? are there different encoders?)
public void SaveImage(Bitmap image, string path)
{
var encoder = ImageCodecInfo.GetImageEncoders().FirstOrDefault(c => c.MimeType == "image/jpeg");
var encodeParams = new EncoderParameters(1);
encodeParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)100);
image.Save(path, encoder, encodeParams);
}

image.MakeTransparent(image.GetPixel(0, 0));
But this can saved as png because sadly jpg doesn't support transparency

The usual solution is to make a bitmap image with your desired background color, render your image to it, and save/convert this bitmap as an image.
Check Graphics.FromImage. This will give you a Graphics rendering object for a bitmap.

Related

SkiaSharp text drawn over canvas not saved

I'm drawing an SKBitmap on SKCanvas, then drawing some text over the canvas, then saving the image to disk. The text is not saved to the file on disk, and I only see the original bitmap. What am I missing ?
SKBitmap pngImage = SKBitmap.Decode(msBitmap.ToArray());
mycanvas.DrawBitmap(pngImage, 0, 0);
mycanvas.DrawText("Text", 10, 10, myBrush);
using (var stream = File.OpenWrite(myfileName))
{
SKData d = SKImage.FromBitmap(pngImage).Encode(SKEncodedImageFormat.Png, 100);
d.SaveTo(stream);
}
You are drawing both the bitmap and the text to the canvas (mycanvas) - but when you save, you are saving just the image data (pngImage). You need to get what is drawn on the canvas, and save that.
You might try the Snapshot() method, available on the surface (which owns the SKCanvas object).

Dynamically generated Bitmap image with aligned data in it

I'm developing an Winforms application to be used for Led displays. The Led display is size 64x32. I created a test bitmap image with 4 cells size 64x16, so I can output it it to the LED display.
When the user enters 4 numbers in the input form, those Strings are then converted to Bitmap Image and placed inside the cells. I somehow got it to work with this method; It edits the same bitmap image, inserts the numbers, and saves it into a new bmp (or am I wrong?).
public static Bitmap Convert_Text_to_Image(string txt, string fontname, int fontsize)
{
//creating bitmap image
Bitmap bmp = new Bitmap("cells.bmp");
//FromImage method creates a new Graphics from the specified Image.
Graphics graphics = Graphics.FromImage(bmp);
// Create the Font object for the image text drawing.
Font font = new Font(fontname, fontsize);
// Instantiating object of Bitmap image again with the correct size for the text and font.
SizeF stringSize = graphics.MeasureString(txt, font);
bmp = new Bitmap(bmp, (int)stringSize.Width, (int)stringSize.Height);
graphics = Graphics.FromImage(bmp);
//Draw Specified text with specified format
graphics.DrawString(txt, font, Brushes.Red, 0, 0);
font.Dispose();
graphics.Flush();
graphics.Dispose();
bmp.Save("cells2.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
return bmp; //return Bitmap Image
}
The output in the PictureBox is This
Now I've created myself multiple problems with the alignment, since I just pasted "bmp numbers" directly onto the "bmp cells"... is there a function of "mapping" the numbers correctly inside the cells, depending if its a single-digit or a two-digit number?
I'm pretty certain there's a way easier way to do all of this, maybe with the DataGridView? I only started using C#, any help would be appreciated.
The image "cells.bmp" is just a test image i created in Paint (xd), rather than that, I'm trying to write a function that will create the Bitmap cells through code
if (want_x_number_cells) {
//create bmp with appropriate number of cells
}

Unsupported Pixel Format of source or template image. AForge Imaging

I am getting the following Exception at ProcessImage(bitmap1, bitmap2);
Unsupported Pixel Format of source or template image
and this is my code:
public static double FindComparisonRatioBetweenImages(
System.Drawing.Image one, System.Drawing.Image two)
{
Bitmap bitmap1 = new Bitmap(one);
Bitmap bitmap2 = new Bitmap(two);
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0);
TemplateMatch[] matchings = null;
matchings = tm.ProcessImage(bitmap1, bitmap2); // Exception occurs here!
return matchings[0].Similarity;
}
I have also passed managedImage from the below code into the method, but it still gives error:
UnmanagedImage unmanagedImageA = UnmanagedImage.FromManagedImage(bitmap1);
Bitmap managedImageA = unmanagedImageA.ToManagedImage();
UnmanagedImage unmanagedImageB = UnmanagedImage.FromManagedImage(bitmap2);
Bitmap managedImageB = unmanagedImageB.ToManagedImage();
I have passed Images randomly from my computer, they all give exception.
I have passed Blank Image edited in paint into the method,it still give exception.
Also checked, jpeg, png, bmp formats, nothing work.
Try ExhaustiveTemplateMatching:
The class implements exhaustive template matching algorithm, which performs complete scan of source image, comparing each pixel with corresponding pixel of template.
The class processes only grayscale 8 bpp and color 24 bpp images.
So, those are the image formats you must use.
As requested, to convert to a specific pixel format, you can do this:
public static Bitmap ConvertToFormat(this Image image, PixelFormat format)
{
Bitmap copy = new Bitmap(image.Width, image.Height, format);
using (Graphics gr = Graphics.FromImage(copy))
{
gr.DrawImage(image, new Rectangle(0, 0, copy.Width, copy.Height));
}
return copy;
}
The one you would use is System.Drawing.Imaging.PixelFormat.Format24bppRgb.

Accurate BoundingBox on Microsoft ISF?

I have a set of Microsoft ISF (Ink Serialized Format) images, which I am attempting to convert to PNGs to include in a web page. I have successfully used the C# package Microsoft.Ink to draw the ink to a Bitmap and save as PNG:
byte[] data; // data has the raw bytes of the ISF file
Ink ink = new Ink();
Renderer renderer = new Renderer();
Stream outStream; // a Stream to hold the PNG data
ink.Load(data);
using (Strokes strokes = ink.Strokes) {
// get bounds of ISF
rect = strokes.GetBoundingBox(BoundingBoxMode.PointsOnly);
// create bitmap matching bounds
bm = new Bitmap(rect.Width, rect.Height);
// draw the ISF onto the Bitmap
using (Graphics g = Graphics.FromImage(bm)) {
g.Clear(Color.Transparent);
renderer.Draw(g, strokes);
}
}
// save the Bitmap to PNG format
bm.Save(outStream, System.Drawing.Imaging.ImageFormat.Png);
... however, the image dimensions seem to be abnormally large. Changing the BoundingBoxMode enum passed in to the GetBoundingBox method does not appear to change anything, and I'm getting images that are 465px × 660px and contain only a handwritten letter 'a' taking up maybe 25px × 30px in actual space.
Any suggestions on how to get a more accurate bounding box?
The bounding box rectangle is in "Inkspace" coordinates - create throwaway bitmap and graphics objects, then convert the rectangle using renderer.InkSpacetoPixel.
Add these lines between the GetBoundingBox call and the creation of the Bitmap bm, and the Bitmap should be sized correctly:
Bitmap bmTrash = new Bitmap(10, 10);
Graphics gTrash = Graphics.FromImage(bmTrash);
renderer.InkSpaceToPixel(gTrash, rect.Location);
renderer.InkSpaceToPixel(gTrash, rect.Size);

Edit multipage TIFF image using System.Drawing

I'm tring to edit multipage tiff by creating Graphics from the image, but i encountered the error message: “A Graphics object cannot be created from an image that has an indexed pixel format.”
How can i edit multipage tiff?
I wrote something to extract single pages from a multipage tiff file.
// Load as Bitmap
using (Bitmap bmp = new Bitmap(file))
{
// Get pages in bitmap
int frames = bmp.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
bmp.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, tiffpage);
if (bmp.PixelFormat != PixelFormat.Format1bppIndexed)
{
using (Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height))
{
bmp2.Palette = bmp.Palette;
bmp2.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
// create graphics object for new bitmap
using (Graphics g = Graphics.FromImage(bmp2))
{
// copy current page into new bitmap
g.DrawImageUnscaled(bmp, 0, 0);
// do whatever you migth to do
...
}
}
}
}
The snippet loads the tif file and extracts the one page (number in variable tiffpage) into a new bitmap. This is not indexed and an graphics object can be created.
The error : A Graphics object cannot be created from an image that has an indexed pixel format.
...has nothing to do with it being a multipage TIFF. An indexed image format means it has a palette of colours, e.g. it's a 256-colour image. A 1-bit image (B&W) would also count as having a palette of 2 colours.
You can't perform Graphics operations on images that use a palette, they'd need to be converted to 15-bit or more colour depth first.
Here is a link to a CodeProject sample that includes code for converting a TIFF file to a normal Bitmap, which you can then work with like any other Bitmap:
http://www.codeproject.com/KB/GDI-plus/BitonalImageConverter.aspx
I once wrote little utility to create encrypted pdfs from tiff images. Here is a piece of code to get pages from tiff image:
var bm= new System.Drawing.Bitmap('tif path');
var total = bm.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
for(var x=0;x<total;x++)
{
bm.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page,x);
var img=Image.GetInstance(bm,null,false);
//do what ever you want with img object
}

Categories

Resources