How to Mirror An Image [duplicate] - c#

This question already has answers here:
How to mirror an image using array
(2 answers)
Closed 7 years ago.
This is my original image,
I want to mirror it and have it appear like this,
I want to mirror my image so that the original and the mirrored image appear side by side. The only thing is that I don't know how to extend the range of my original image in order to add its mirrored image right beside it.
Using my code (below) I have managed to do create the mirrored image, only I can't make both the original and the mirrored appear side by side.
My code,
int Height = TransformedPic.GetLength(0);
int Width = TransformedPic.GetLength(1);
for (int i = 0; i < Height / 2; i++)
{
for (int j = 0; j < Width; j++)
{
var Temporary = TransformedPic[i, j];
TransformedPic[i, j] = TransformedPic[Height - 1 - i, j];
TransformedPic[Height - 1 - i, j] = Temporary;
}
}
TransformedPic is the variable in which the original image is saved under

Step 1 : Mirror an Image.
To do this apply a negative sacaletransform. Like
new ScaleTransform() { ScaleX = -1 };
Then merge two image side by side.
you can see it here, how you can merge Two images.
Here is another way :
//Get Your Image from Picturebox
Bitmap image1 = new Bitmap(pictureBox1.Image);
//Clone it to another bitmap
Bitmap image2 = (Bitmap)image1.Clone();
//Mirroring
image2.RotateFlip(RotateFlipType.RotateNoneFlipX);
//Merge two images in bitmap image,
Bitmap bitmap = new Bitmap(image1.Width + image2.Width, Math.Max(image1.Height, image2.Height));
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(image1, 0, 0);
g.DrawImage(image2, image1.Width, 0);
}
//Show them in a picturebox
pictureBox2.Image = bitmap;

This is how it's done with a BitMap, you can draw the image from the graphics and redraw the graphics object with the modified one.
public Bitmap MirrorImage(Bitmap source)
{
Bitmap mirrored = new Bitmap(source.Width, source.Height);
for(int i = 0; i < source.Height; i++)
for(int j = 0; j < source.Width; j++)
mirrored.SetPixel(i, j, source.GetPixel(source.Width - j - 1, i);
return mirrored;
}

Related

How to set pixels from original image to a new image?

usage
public UserControlTester()
{
InitializeComponent();
GetSetPixelsRandom();
}
code
private void GetSetPixelsRandom()
{
Bitmap img = new Bitmap(#"d:\\downloaded images\\test.gif");
for (int i = 0; i < img.Width; i++)
{
for (int j = 0; j < img.Height; j++)
{
Color pixel = img.GetPixel(i, j);
pixels.Add(pixel);
}
}
Bitmap img1 = new Bitmap(512,512);
for (int i = 0; i < img1.Width; i++)
{
for (int j = 0; j < img1.Height; j++)
{
for (int c = 0; c < pixels.Count; c++)
{
img1.SetPixel(i, j, pixels[c]);
}
}
}
img1.Save(#"d:\\downloaded images\\test3.gif");
}
Not sure if this is the right way. the inner loop with the variable c take a lot of time because there are more then 290,000 pixels.
Assuming you want to resize the image, this can be done easily. The Bitmap constructor has rescaling build in:
Bitmap img = new Bitmap(#"d:\\downloaded images\\test.gif");
Bitmap img1 = new Bitmap(img, new Size(512, 512));
img1.Save(#"d:\\downloaded images\\test3.gif");
If you do not want to resize but indeed take random pixels take a look at what at MickyD mentioned.
Note that in your provided example every pixel in the new image is effectively set to the last pixel in the pixels list because you loop over every pixel in pixels for every pixel in the new image.

Convert ARGB to PARGB

I've been looking for a fast alternative method of SetPixel() and I have found this link : C# - Faster Alternatives to SetPixel and GetPixel for Bitmaps for Windows Forms App
So my problem is that I've an image and I want to create a copy as a DirectBitmap object but first I need to convert ARGB to PARGB so I used this code:
public static Color PremultiplyAlpha(Color pixel)
{
return Color.FromArgb(
pixel.A,
PremultiplyAlpha_Component(pixel.R, pixel.A),
PremultiplyAlpha_Component(pixel.G, pixel.A),
PremultiplyAlpha_Component(pixel.B, pixel.A));
}
private static byte PremultiplyAlpha_Component(byte source, byte alpha)
{
return (byte)((float)source * (float)alpha / (float)byte.MaxValue + 0.5f);
}
and Here's my copy code:
DirectBitmap DBMP = new DirectBitmap(img.Width, img.Height);
MyImage myImg = new MyImage(img as Bitmap);
for (int i = 0; i < img.Width; i++)
{
for (int j = 0; j < img.Height; j++)
{
Color PARGB = NativeWin32.PremultiplyAlpha(Color.FromArgb(myImg.RGB[i, j].Alpha,
myImg.RGB[i, j].R, myImg.RGB[i, j].G, myImg.RGB[i, j].B));
byte[] bitMapData = new byte[4];
bitMapData[3] = (byte)PARGB.A;
bitMapData[2] = (byte)PARGB.R;
bitMapData[1] = (byte)PARGB.G;
bitMapData[0] = (byte)PARGB.B;
DBMP.Bits[(i * img.Height) + j] = BitConverter.ToInt32(bitMapData, 0);
}
}
MyImage : a class containing a Bitmap object along with an array of struct RGB storing the colors of each pixel
However, this code gives me a messed up image. what am I doing wrong?
Bitmap data is organized horizontal line after horizontal line. Therefore, your last line should be:
DBMP.Bits[j * img.Width + i] = BitConverter.ToInt32(bitMapData, 0);

Strange colors while displaying bitmap with PixelFormat.Format8bppIndexed

I would like to ask for help. I want to create an image from array and show it in PictureBox. But image, that was supposed to be in gray scale, is displayed in strange colors. In the past, I have had such a problem, but the methods used until now have failed. Here is my code:
public static Bitmap BitmapFromArray(int[] pixelValues,int rows, int columns)
{
Bitmap bitmap = new Bitmap(rows, columns);
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, rows, columns), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
byte[] pixelValuesOriginal = new byte[Math.Abs(bmpData.Stride) * bitmap.Height];
//Pobierz wartosc wszystkich punktow obrazu
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixelValuesOriginal, 0, pixelValues.Length);
for (int i = 0; i < pixelValues.Length; i++)
{
pixelValuesOriginal[i] = (byte)pixelValues[i];
}
//Ustaw wartosc wszystkich punktow obrazu
System.Runtime.InteropServices.Marshal.Copy(pixelValuesOriginal, 0, bmpData.Scan0, pixelValuesOriginal.Length);
bitmap.UnlockBits(bmpData);
return bitmap;
}
I tried the method that I found here: Editing 8bpp indexed Bitmaps
ColorPalette pal = bitmap.Palette;
for (int i = 0; i <= 255; i++)
{
pal.Entries[i] = Color.FromArgb(i, i, i);
}
bitmap.Palette = pal;
But this time it did not work because bitmap.Palette.Entries is an array with 0 elements.
I also tried to change the PixelFormat for PixelFormat.Format24bppRgb and use such a trick:
for (int i = 0; i < pixelValues.Length; i++)
{
for (int j = 0; j < 3; j++)
{
pixelValuesOriginal[i + j] = (byte)pixelValues[i];
}
}
But then I have three gray scaled pictures side by side.
I will be grateful for hints on what to do with this problem.

How to quickly batch save Bitmaps?

So I have a source bitmap that is fairly large, so I shrink it down by a scale of %25 to speed things along in image processing and what not. At the end, I have a group of Rectangles (around 2000) that correspond to sections of the scaled image. I am trying to rescale the Rectangles to match the same areas on the source, then saving that area as a cropped image.
This was my initial code that saved cropped images of the scaled image:
for (int i = 0; i < cells.Count; i++)
{
for (int j = 0; j < cells[i].Count; j++)
{
Cell cell = cells[i][j];
if (cell.width < 0 || cell.height < 0)
{
return;
}
Bitmap bitmap = new Bitmap(cell.width, cell.height);
using (Graphics c = Graphics.FromImage(bitmap))
{
c.DrawImage(inputBitmap, new Rectangle(0, 0, cell.width, cell.height), new Rectangle(cell.x1, cell.y1, cell.width, cell.height), GraphicsUnit.Pixel);
}
bitmap.Save(cellDirectory + "\\cell" + i.ToString("D2") + j.ToString("D2") + ".png", ImageFormat.Png);
}
}
This is my code changed to save the cropped image of the original bitmap:
for (int i = 0; i < cells.Count; i++)
{
for (int j = 0; j < cells[i].Count; j++)
{
Cell cell = cells[i][j];
if (cell.width < 0 || cell.height < 0)
{
return;
}
int x = cell.x1 * 4;
int y = cell.y1 * 4;
int width = cell.width * 4;
int height = cell.height * 4;
Bitmap bitmap = new Bitmap(width, height);
using (Graphics c = Graphics.FromImage(bitmap))
{
c.DrawImage(input, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
}
bitmap.Save(cellDirectory + "\\cell" + i.ToString("D2") + j.ToString("D2") + ".png", ImageFormat.Png);
}
}
The program with the first code finishes in about 20 seconds on average, but for some reason the second version takes over 6 minutes. My brain math might be lying to me, but that seems to be a disproportionate time increase.
The debugging that I have done so far has revealed to me that this line:
c.DrawImage(input, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
is taking longer to complete over time. I suspect that some sort of memory leak could be causing this, but I have tried manually calling Dispose on every object I can and nothing helped. Is there some kind of under-the-hood thing that I should be aware of that is causing this?
Your original method saves a file at the original resolution, while the new method increases both width and height by a factor of 4, which is a 16x increase in the image size. The time difference (6 minutes vs 20 seconds) is roughly proportional:
(6 * 60) / 20 = 18 times slower
4 * 4 = 16 times the image size

Image Processing in C# - A smart solution?

I have an image with letters in it, the letters are in two colors black and blue, I want to read the blue colored letters from the image.
Can anyone suggest me a method to do this in C#. Iam studying GDI+,but still didn't get any logic to develop this program..
I tried OCRing it, but the issue with common OCRs is that they dont recognize the color difference.
I only want to read the Blue characters....
Any guidance is highly appreciated.
Try this one ;) But that's unsafe code.
void RedAndBlue()
{
OpenFileDialog ofd;
int imageHeight, imageWidth;
if (ofd.ShowDialog() == DialogResult.OK)
{
Image tmp = Image.FromFile(ofd.FileName);
imageHeight = tmp.Height;
imageWidth = tmp.Width;
}
else
{
// error
}
int[,] bluePixelArray = new int[imageWidth, imageHeight];
int[,] redPixelArray = new int[imageWidth, imageHeight];
Rectangle rect = new Rectangle(0, 0, tmp.Width, tmp.Height);
Bitmap temp = new Bitmap(tmp);
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int j = 0; j < bmpData.Height; j++)
{
for (int i = 0; i < bmpData.Width; i++)
{
bluePixelArray[i, j] = ptr[0];
redPixelArray[i, j] = ptr[2];
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
temp.Dispose();
}
Modify the color of the image to gray scaled then use OCR
public Bitmap MakeGrayscale(Bitmap original)
{
//make an empty bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
for (int i = 0; i < original.Width; i++)
{
for (int j = 0; j < original.Height; j++)
{
//get the pixel from the original image
Color originalColor = original.GetPixel(i, j);
//create the grayscale version of the pixel
int grayScale = (int)((originalColor.R * .3) + (originalColor.G * .59)
+ (originalColor.B * .11));
//create the color object
Color newColor = Color.FromArgb(grayScale, grayScale, grayScale);
//set the new image's pixel to the grayscale version
newBitmap.SetPixel(i, j, newColor);
}
}
return newBitmap;
}
You could probably modify the palette to have only black and white on the image

Categories

Resources