How to mirror an image using array - c#

I need to mirror an image and display it like this:
To display like this:
This is my code so far, I have had no luck:
int Height = TransformedPic.GetLength(0);
int Width = TransformedPic.GetLength(1);
for (int i = 0; i < Height; i++)//loop rows
{
for (int j = 0; j < Width; j++)//loop columns
{
TransformedPic[i, j] = TransformedPic[i, ((2 * Width) - (j + 1))];
}
}

Image.RotateFlip will do the job at lot faster and easier:
Bitmap bmp1 = (Bitmap)pictureBox1.Image;
Bitmap bmp2 = new Bitmap(bmp1.Width * 2, bmp1.Height);
using (Graphics G = Graphics.FromImage(bmp2))
{
G.DrawImage(bmp1, 0, 0);
bmp1.RotateFlip(RotateFlipType.RotateNoneFlipX);
G.DrawImage(bmp1, bmp1.Width, 0);
pictureBox2.Image = bmp2;
}
Instead you could use loops similar to yours and Bitmap.GetPixel and Bitmap.SetPixel but that would be really slow:
TransformedPic.SetPixel(Width - i, j, TransformedPic.GetPixel(i,j));
Going over one half of the width..

Or you could do it like this in one line:
picBox.Image.RotateFlip(RotateFlipType.RotateNoneFlipX)

Related

How to get color from specific area in an Image in C#

I am trying to get color from specific area in an Image.
Assume that , this is image , and I want to get color inside image.(the result should be red of the above image) This color may be different position in image. Because I don't know exact position of color where it starting, so I can't get exact result.
Until now, I cropped image giving manually position of x and y, and then cropped image and I got average color of cropped image. But I know , this is not exact color.
What I tried :
private RgbDto GetRGBvalueCroppedImage(Image croppedImage)
{
var avgRgb = new RgbDto();
var bm = new Bitmap(croppedImage);
BitmapData srcData = bm.LockBits(
new Rectangle(0, 0, bm.Width, bm.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
IntPtr Scan0 = srcData.Scan0;
long[] totals = new long[] { 0, 0, 0 };
int width = bm.Width;
int height = bm.Height;
unsafe
{
byte* p = (byte*)(void*)Scan0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
for (int color = 0; color < 3; color++)
{
int idx = (y * stride) + x * 4 + color;
totals[color] += p[idx];
}
}
}
}
avgRgb.avgB = (int)totals[0] / (width * height);
avgRgb.avgG = (int)totals[1] / (width * height);
avgRgb.avgR = (int)totals[2] / (width * height);
return avgRgb;
}
How can I get exact position to crop? May be I can convert image to byte array, then I can find different color and take position of it and then crop. But I have no clue how do this.
You can use something this extension method to get dominant color in a region of an image in case they are not all the same
public static Color GetDominantColor(this Bitmap bitmap, int startX, int startY, int width, int height) {
var maxWidth = bitmap.Width;
var maxHeight = bitmap.Height;
//TODO: validate the region being requested
//Used for tally
int r = 0;
int g = 0;
int b = 0;
int totalPixels = 0;
for (int x = startX; x < (startX + width); x++) {
for (int y = startY; y < (startY + height); y++) {
Color c = bitmap.GetPixel(x, y);
r += Convert.ToInt32(c.R);
g += Convert.ToInt32(c.G);
b += Convert.ToInt32(c.B);
totalPixels++;
}
}
r /= totalPixels;
g /= totalPixels;
b /= totalPixels;
Color color = Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
return color;
}
You can then use it like
Color pixelColor = myBitmap.GetDominantColor(xPixel, yPixel, 5, 5);
there is room for improvement, like using a Point and Size, or even a Rectangle
public static Color GetDominantColor(this Bitmap bitmap, Rectangle area) {
return bitmap.GetDominantColor(area.X, area.Y, area.Width, area.Height);
}
and following this link:
https://www.c-sharpcorner.com/UploadFile/0f68f2/color-detecting-in-an-image-in-C-Sharp/
If you want to get the image colors, you don't need to do any cropping at all. Just loop on image pixels and find the two different colors. (Assuming that you already know the image will have exactly 2 colors, as you said in comments). I've written a small function that will do that. However, I didn't test it in an IDE, so expect some small mistakes:
private static Color[] GetColors(Image image)
{
var bmp = new Bitmap(image);
var colors = new Color[2];
colors[0] = bmp.GetPixel(0, 0);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color c = bmp.GetPixel(i, j);
if (c == colors[0]) continue;
colors[1] = c;
return colors;
}
}
return colors;
}

Cut an Image into 9 pieces C# [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Image splitting into 9 pieces
Though I googled enough but unfortunately failed to find a help. This Code Project Tutorial also failed to serve me what I actually need.
I have an Image and 9 PictureBox(s) in a WinForm.
Image img = Image.FromFile("media\\a.png"); // a.png has 312X312 width and height
// some code help, to get
// img1, img2, img3, img4, img5, img6, img7, img8, img9
// having equal width and height
// then...
pictureBox1.Image = img1;
pictureBox2.Image = img2;
pictureBox3.Image = img3;
pictureBox4.Image = img4;
pictureBox5.Image = img5;
pictureBox6.Image = img6;
pictureBox7.Image = img7;
pictureBox8.Image = img8;
pictureBox9.Image = img9;
Here is an example Image for you:
This is a part of my Picture Puzzle class project. I have done with photoshop images, now want to dynamically cut.
Thanks in advance.
First off, instead of using img1, img2... use an array with a size of 9. Then it's much easier to do this using a couple of loops like this:
var imgarray = new Image[9];
var img = Image.FromFile("media\\a.png");
for( int i = 0; i < 3; i++){
for( int j = 0; j < 3; j++){
var index = i*3+j;
imgarray[index] = new Bitmap(104,104);
var graphics = Graphics.FromImage(imgarray[index]);
graphics.DrawImage( img, new Rectangle(0,0,104,104), new Rectangle(i*104, j*104,104,104), GraphicsUnit.Pixel);
graphics.Dispose();
}
}
Then you can fill your boxes like this:
pictureBox1.Image = imgarray[0];
pictureBox2.Image = imgarray[1];
...
You could try with this code. It basically creates a matrix of images (like you need in your project) and draws on each Bitmap adequate part of the large image. The same concept you could use for the pictureBoxes and put them in the matrix.
Image img = Image.FromFile("media\\a.png"); // a.png has 312X312 width and height
int widthThird = (int)((double)img.Width / 3.0 + 0.5);
int heightThird = (int)((double)img.Height / 3.0 + 0.5);
Bitmap[,] bmps = new Bitmap[3,3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
bmps[i, j] = new Bitmap(widthThird, heightThird);
Graphics g = Graphics.FromImage(bmps[i, j]);
g.DrawImage(img, new Rectangle(0, 0, widthThird, heightThird), new Rectangle(j * widthThird, i * heightThird, widthThird, heightThird), GraphicsUnit.Pixel);
g.Dispose();
}
pictureBox1.Image = bmps[0, 0];
pictureBox2.Image = bmps[0, 1];
pictureBox3.Image = bmps[0, 2];
pictureBox4.Image = bmps[1, 0];
pictureBox5.Image = bmps[1, 1];
pictureBox6.Image = bmps[1, 2];
pictureBox7.Image = bmps[2, 0];
pictureBox8.Image = bmps[2, 1];
pictureBox9.Image = bmps[2, 2];

Layout Advice for C#

I'm having a difficult time on this issue. I've searched on this site and couldn't find a solution anywhere yet. I have to make a grid of blocks to be displayed on a picture. I've searched and found things about drawing the grid and the GridView class. But all that seems impossible since I have to manipulate the size of the blocks to whatever size. So if anyone can provide any advice I would be very grateful thanks.
If you need simple grid, you can do it by simply drawing it to image:
using (var bitmap = Bitmap.FromFile(#"C:\darbai_test\Penguins.jpg"))
{
var graphics = Graphics.FromImage(bitmap);
var xStep = 10;
var yStep = 15;
for (int i = 0; i < bitmap.Width / xStep; i++)
{
var x = i * xStep;
graphics.DrawLine(Pens.Black, x, 0, x, bitmap.Height);
}
for (int j = 0; j < bitmap.Height / yStep; j++)
{
var y = j * yStep;
graphics.DrawLine(Pens.Black, 0, y, bitmap.Width, y);
}
bitmap.Save(#"c:\darbai_test\penguins_withgrid.jpg");
}

unsafe image noise removal in c# (error : Bitmap region is already locked)

public unsafe Bitmap MedianFilter(Bitmap Img)
{
int Size =2;
List<byte> R = new List<byte>();
List<byte> G = new List<byte>();
List<byte> B = new List<byte>();
int ApetureMin = -(Size / 2);
int ApetureMax = (Size / 2);
BitmapData imageData = Img.LockBits(new Rectangle(0, 0, Img.Width, Img.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
byte* start = (byte*)imageData.Scan0.ToPointer ();
for (int x = 0; x < imageData.Width; x++)
{
for (int y = 0; y < imageData.Height; y++)
{
for (int x1 = ApetureMin; x1 < ApetureMax; x1++)
{
int valx = x + x1;
if (valx >= 0 && valx < imageData.Width)
{
for (int y1 = ApetureMin; y1 < ApetureMax; y1++)
{
int valy = y + y1;
if (valy >= 0 && valy < imageData.Height)
{
Color tempColor = Img.GetPixel(valx, valy);// error come from here
R.Add(tempColor.R);
G.Add(tempColor.G);
B.Add(tempColor.B);
}
}
}
}
}
}
R.Sort();
G.Sort();
B.Sort();
Img.UnlockBits(imageData);
return Img;
}
I tried to do this. but i got an error call "Bitmap region is already locked" can anyone help how to solve this. (error position is highlighted)
GetPixel is the slooow way to access the image and doesn't work (as you noticed) anymore if someone else starts messing with the image buffer directly. Why would you want to do that?
Check Using the LockBits method to access image data for some good insight into fast image manipulation.
In this case, use something like this instead:
int pixelSize = 4 /* Check below or the site I linked to and make sure this is correct */
byte* color =(byte *)imageData .Scan0+(y*imageData .Stride) + x * pixelSize;
Note that this gives you the first byte for that pixel. Depending on the color format you are looking at (ARGB? RGB? ..) you need to access the following bytes as well. Seems to suite your usecase anyway, since you just care about byte values, not the Color value.
So, after having some spare minutes, this is what I'd came up with (please take your time to understand and check it, I just made sure it compiles):
public void SomeStuff(Bitmap image)
{
var imageWidth = image.Width;
var imageHeight = image.Height;
var imageData = image.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
var imageByteCount = imageData.Stride*imageData.Height;
var imageBuffer = new byte[imageByteCount];
Marshal.Copy(imageData.Scan0, imageBuffer, 0, imageByteCount);
for (int x = 0; x < imageWidth; x++)
{
for (int y = 0; y < imageHeight; y++)
{
var pixelColor = GetPixel(imageBuffer, imageData.Stride, x, y);
// Do your stuff
}
}
}
private static Color GetPixel(byte[] imageBuffer, int imageStride, int x, int y)
{
int pixelBase = y*imageStride + x*3;
byte blue = imageBuffer[pixelBase];
byte green = imageBuffer[pixelBase + 1];
byte red = imageBuffer[pixelBase + 2];
return Color.FromArgb(red, green, blue);
}
This
Relies on the PixelFormat you used in your sample (regarding both the pixelsize/bytes per pixel and the order of the values). If you change the PixelFormat this will break.
Doesn't need the unsafe keyword. I doubt that it makes a lot of difference, but you are free to use the pointer based access instead, the method would be the same.

C# winforms code to c# wpf code

I have a drawing application developed in winforms C# which uses many System.Drawing.Bitmap object throughout the code.
Now I am writing it into WPF with c#. I have done almost 90% of the conversion.
Coming to the problem... I have the following code which is used to traverse the image pixel by pixel
Bitmap result = new Bitmap(img); // img is of System.Drawing.Image
result.SetResolution(img.HorizontalResolution, img.VerticalResolution);
BitmapData bmpData = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.ReadWrite, img.PixelFormat);
int pixelBytes = System.Drawing.Image.GetPixelFormatSize(img.PixelFormat) / 8;
System.IntPtr ptr = bmpData.Scan0;
int size = bmpData.Stride * result.Height;
byte[] pixels = new byte[size];
int index = 0;
double R = 0;
double G = 0;
double B = 0;
System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, size);
for (int row = 0; row <= result.Height - 1; row++)
{
for (int col = 0; col <= result.Width - 1; col++)
{
index = (row * bmpData.Stride) + (col * pixelBytes);
R = pixels[index + 2];
G = pixels[index + 1];
B = pixels[index + 0];
.
.// logic code
.
}
}
result.UnlockBits(bmpData);
It uses System.Drawing's for the purpose.
Is it possible to achieve this thing in wpf as well keeping it simple as it is?
In addtion to Chris's anwser you might want to look at WriteableBitmap. It's another way to manipulate images pixels.
Example
You can use BitmapImage.CopyPixels to copy the image your pixel buffer.
BitmapImage img= new BitmapImage(...); // This is your image
int bytePerPixel = (img.Format.BitsPerPixel + 7) / 8;
int stride = img.PixelWidth * bytesPerPixel;
int size = img.PixelHeight * stride;
byte[] pixels = new byte[size];
img.CopyPixels(pixels, stride, 0);
// Now you can access 'pixels' to perform your logic
for (int row = 0; row < img.PixelHeight; row++)
{
for (int col = 0; col < img.PixelWidth; col++)
{
index = (row * stride) + (col * bytePerPixel );
...
}
}

Categories