0

I'm battling with this for a while now and can't seem to get any results. I'm using methods from this SO QA > How to crop an image using C#?

I don't get any errors :/ The code just runs, but the image does not get cropped.

Code:

string fileNameWitPath = "finename.png";
fileNameWitPath = context.Server.MapPath("~/content/branding/" + context.Request.QueryString["userId"] + "/logo" + "/" + fileNameWitPath)

using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Open))
{
    using (BinaryWriter bw = new BinaryWriter(fs))
    {
        //get co-ords
        int x1 = Convert.ToInt32(context.Request.QueryString["x1"].Trim());
        int y1 = Convert.ToInt32(context.Request.QueryString["y1"].Trim());
        int x2 = Convert.ToInt32(context.Request.QueryString["x2"].Trim());
        int y2 = Convert.ToInt32(context.Request.QueryString["y2"].Trim());

        Bitmap b = new Bitmap(fs);
        Bitmap nb = new Bitmap((x2 - x1), (y2 - y1));
        Graphics g = Graphics.FromImage(nb);
        //g.DrawImage(b, x2, y2);
        Rectangle cropRect = new Rectangle(x1, y1, nb.Width, nb.Height);

        g.DrawImage(b, new Rectangle(x1, y1, nb.Width, nb.Height), cropRect, GraphicsUnit.Pixel);

        Byte[] data;

        using (var memoryStream = new MemoryStream())
        {
            nb.Save(memoryStream, ImageFormat.Png);
            data = memoryStream.ToArray();
        }

        bw.Write(data);
        bw.Close();
    }
}
Community
  • 1
  • 1
Orion
  • 452
  • 6
  • 23
  • Well, there's at least one typo in the code: `x2 = x1`. You also should be disposing your `Graphics` object after you're done drawing (with a `using`). And I don't understand the point of using `BinaryWriter` and a `MemoryStream`, when you could just save direct to the `fs` stream. – Peter Duniho May 11 '17 at 03:42
  • what is the size of the new bitmap? – kennyzx May 11 '17 at 03:43
  • @PeterDuniho that is a typo, it's meant to be x2 - x1. I just reverted the code back to original from my testing. result is the same though – Orion May 11 '17 at 03:45
  • @kennyzx size is determined from the co-ordinates. – Orion May 11 '17 at 03:45
  • _"result is the same though"_ -- it can't possibly be _the same_. The output bitmap would have a different width, whatever else there might be wrong with the code. – Peter Duniho May 11 '17 at 03:47
  • I also don't know why you are drawing to the same rect as the source rect. Your dest rect should be {0, 0, nb.Width, nb.Height}. Basically, the code you posted seems full of typos. It seems likely whatever the issue, fixing the typos would fix the problem. Impossible to say for sure, because you didn't provide a good [mcve] that reliably reproduces your problem. – Peter Duniho May 11 '17 at 03:48
  • @Orion you are saying "but the image does not get cropped", so I wonder if it is just because you are passing wrong coordinates so the new image has the same size as the original one. – kennyzx May 11 '17 at 03:48
  • @PeterDuniho, will try change the destination rectangle and see what it gives me. – Orion May 11 '17 at 03:49
  • @kennyzx I don't know. I'm playing with the code to see if I can get it to work out. I can confirm the file is not being saved as I look at the original file date and it's still the old date. – Orion May 11 '17 at 03:51
  • _"I look at the original file date and it's still the old date"_ -- **that has _nothing_ to do with the cropping code**. If the modified date of the file isn't changing, then the file isn't being modified, at all. So, in addition to all the typos in the code you've shown, you've got something else going wrong where no matter what you do in the cropping code, the new data isn't getting saved to your file anyway. – Peter Duniho May 11 '17 at 03:53
  • @PeterDuniho Can you run the above code on your side with test values to check please? – Orion May 11 '17 at 03:55
  • @PeterDuniho I tried changing the source and destination rectangles. Still the same result. – Orion May 11 '17 at 04:01
  • 1
    It's not a [mcve], so...no. I can't run it. Not that I need to, to know it won't work. You are still drawing to the wrong dest rect. And another bug I just noticed: you are trying to write to the same `FileStream` object you have read from. At the very least, this will require resetting the `FileStream.Position` back to 0, and if the original `Bitmap` object is not disposed, it may keep the file locked, preventing the write from succeeding (though an exception should be thrown in that case). – Peter Duniho May 11 '17 at 04:01
  • _"I tried changing the source and destination rectangles. Still the same result."_ -- naturally. Even if you did fix all the bugs in the drawing part, that won't matter until you figure out the _writing_ part. – Peter Duniho May 11 '17 at 04:02
  • @PeterDuniho I hear you. Will try and solve this. I understand what you saying about the same file stream. – Orion May 11 '17 at 04:03

2 Answers2

1

You can also do it copying pixels between bitmaps with Marshal.Copy:

    static void Main()
    {
        var srcBitmap = new Bitmap(@"d:\Temp\SAE5\Resources\TestFiles\rose.jpg");
        var destBitmap = CropBitmap(srcBitmap, new Rectangle(10, 20, 50, 25));
        destBitmap.Save(@"d:\Temp\tst.png");
    }

    static Bitmap CropBitmap(Bitmap sourceBitmap, Rectangle rect)
    {
        // Add code to check and adjust rect to be inside sourceBitmap

        var sourceBitmapData = sourceBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

        var destBitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        var destBitmapData = destBitmap.LockBits(new Rectangle(0, 0, rect.Width, rect.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

        var pixels = new int[rect.Width * rect.Height];
        System.Runtime.InteropServices.Marshal.Copy(sourceBitmapData.Scan0, pixels, 0, pixels.Length);
        System.Runtime.InteropServices.Marshal.Copy(pixels, 0, destBitmapData.Scan0, pixels.Length);

        sourceBitmap.UnlockBits(sourceBitmapData);
        destBitmap.UnlockBits(destBitmapData);

        return destBitmap;
    }
Mykola Kovalchuk
  • 496
  • 2
  • 6
  • 16
0

After getting a full understanding of what I was doing incorrectly. I then modified the code. I was writing to the same File Stream, so it was not actually saving the cropped image. Changed the code to write to a new File Stream and the cropped image is now being saved.

Byte[] data;

                using (FileStream fs = new FileStream(fileNameWitPath, fileMode))
                {
                    using (BinaryWriter bw = new BinaryWriter(fs))
                    {
                        //get co-ords
                        int x1 = Convert.ToInt32(context.Request.QueryString["x1"].Trim());
                        int y1 = Convert.ToInt32(context.Request.QueryString["y1"].Trim());
                        int x2 = Convert.ToInt32(context.Request.QueryString["x2"].Trim());
                        int y2 = Convert.ToInt32(context.Request.QueryString["y2"].Trim());

                        Bitmap b = new Bitmap(fs);
                        Bitmap nb = new Bitmap((x2 - x1), (y2 - y1));
                        Graphics g = Graphics.FromImage(nb);
                        //g.DrawImage(b, x2, y2);
                        Rectangle cropRect = new Rectangle(x1, y1, nb.Width, nb.Height);

                        g.DrawImage(b, new Rectangle(0, 0, nb.Width, nb.Height), cropRect, GraphicsUnit.Pixel);

                        using (var memoryStream = new MemoryStream())
                        {
                            nb.Save(memoryStream, ImageFormat.Png);
                            data = memoryStream.ToArray();
                        }

                        bw.Close();
                    }
                }

                using (FileStream fs = new FileStream(fileNameWitPath, fileMode))
                {
                    using (BinaryWriter bw = new BinaryWriter(fs))
                    {
                        bw.Write(data);
                        bw.Close();
                    }
                }
Orion
  • 452
  • 6
  • 23