Не можете изменить размер измененного изображения?C # WinForms - PullRequest
1 голос
/ 23 января 2012

Если я изменил цвет изображения, а затем попытался изменить его размер, он только изменит исходное изображение.Почему это происходит и как я могу это исправить?

Вот мой код:

private PrintDocument printDoc = new PrintDocument();
private PageSettings pgSettings = new PageSettings();
private PrinterSettings prtSettings = new PrinterSettings();

Bitmap myBitmapImage;      // image (bitmap) for some background mountains
Boolean isInvert = false;
Boolean isLOaded = false;
Boolean isGrayscale = false;
Boolean isThreshold = false;
Boolean isResize = false;

OpenFileDialog ofd;
Bitmap bmBack; 

public EditImage()
{
    printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); 

    InitializeComponent();
    this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
}

private void EditImage_Load(object sender, EventArgs e)
{

}

private void EditImage_Paint(object sender, PaintEventArgs e)
{
    if (isLOaded == true)
    {
        Graphics gWindow;   // reference to the graphic surface of this window
        Graphics gBack;     // reference to in-memory surface

        bmBack = new Bitmap(Width, Height);     // bitmap for window surface copy

        gWindow = e.Graphics;   // get our current window's surface
        gBack = Graphics.FromImage(bmBack);     // create surfaces from the bitmaps

        gBack.DrawImage(myBitmapImage, 0, 0, Width, Height);

        if (isInvert == true)
        {
            InvertBitmap(bmBack);
        }
        else if (isGrayscale == true)
        {
            GrayscaleBitmap(bmBack);
        }
        else if (isThreshold == true)
        {
            ThresholdBitmap(bmBack);
        }
        else if (isResize == true)
        {
            bmBack = resizeImage(bmBack, 10, 100);
        }

        gWindow.DrawImage(bmBack, 0, 0);
    }
}
private void toolStripMenuItemLoadImage_Click(object sender, EventArgs e)
{
    using (ofd = new OpenFileDialog())
    {
        ofd.Title = "Load Image";

        if (ofd.ShowDialog() == DialogResult.OK)
        {
            myBitmapImage = new Bitmap(ofd.FileName);
            this.Invalidate(); 
        }
    }
    isLOaded = true;
}


private void GrayscaleBitmap(Bitmap bmp)
{
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
        System.Drawing.Imaging.PixelFormat.Format32bppRgb);

    IntPtr ptr = bmpData.Scan0;

    int numPixels = bmpData.Width * bmp.Height;
    int numBytes = numPixels * 4;
    byte[] rgbValues = new byte[numBytes];

    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, numBytes);

    for (int i = 0; i < rgbValues.Length; i += 4)
    {
        byte gray = (byte)(.3 * rgbValues[i + 0]); //blue
        gray += (byte)(.59 * rgbValues[i + 1]); //green
        gray += (byte)(.11 * rgbValues[i + 2]); //red

        rgbValues[i + 0] = gray; //blue
        rgbValues[i + 1] = gray; //green
        rgbValues[i + 2] = gray; //red
    }

    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, numBytes);

    bmp.UnlockBits(bmpData);
}

private  Bitmap resizeImage(Bitmap sourceBMP, int width, int height)
{
    Bitmap result = new Bitmap(width, height);
    using(Graphics g = Graphics.FromImage(result))
    g.DrawImage(sourceBMP, 0, 0, width, height);

    return result;
}

У меня также есть методы, которые имеют дело с тем, когда пользователь нажимает кнопку и устанавливает в bools значениесоответствующие значения, чтобы он вызывал правильный метод.Изображения действительно меняют цвет - как предполагалось ... но когда я нажимаю на изменение размера, я хочу, чтобы он изменил размер версии изображения, которая изменила цвет - не оригинальное изображение ...

1 Ответ

4 голосов
/ 23 января 2012

Здесь много чего не так:

resizeImage ()

  • Вам следует избавиться от созданного здесь графического объекта (обернуть его воператор using ())
  • Отсюда не вызывайте invalidate, эта функция просто изменяет размер изображения, делает его недействительным после изменения изображения, а метод Paint рисует изображение, которое теперь изменилось.
  • Вам также следует подумать об утилизации sourceBMP непосредственно перед возвратом функции, если она больше не используется.

GrayscaleBitmap ()

  • Это выглядит правильно, но, опять же, здесь нет причин для недействительности.Вы должны сделать недействительным после вызова этого метода в вызывающей функции.Это имеет больше смысла.

EditImage_Paint

  • Вы не должны вызывать эти функции из своего события Paint.И вам не следует создавать новый Bitmap и новый класс Graphics в каждом Paint.Это намного больше работы, чем необходимо.Эти функции должны выполняться только тогда, когда необходимо изменить данные в зависимости от пользовательского ввода (пользователь нажимает кнопку, чтобы применить эффект оттенков серого).

Для того, что вы хотите сделать, вам нужно только 2 растровых изображенияпеременные самое большее.Один для сохранения исходного неизмененного растрового изображения на случай, если вы захотите позволить пользователю «Сбросить» его или отменить какие-либо эффекты (большинство эффектов вызывают постоянную потерю данных, вы не можете снова сделать цвет изображения в градациях серого).И другой, чтобы сохранить растровое изображение, которое окрашивается.Каждый раз, когда пользователь применяет эффект, он изменяет 2-е растровое изображение, а затем вызывает аннулирование.

Все, что ваша функция рисования должна сделать, это нарисовать 2-е растровое изображение:

Bitmap originalBitmap; // load from file, do not modify
Bitmap currentBitmap; // when user clicks an effect, modify this bitmap and then Invalidate afterward

private void EditImage_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

    // Draw the currentBitmap centered on the window
    SizeF clientSize = this.ClientSize;

    double zoomRatio = Math.Min(
        clientSize.Width / currentBitmap.Width,
        clientSize.Height / currentBitmap.Height
    );

    SizeF zoomedSize = new SizeF(
        (float)(currentBitmap.Width * zoomRatio),
        (float)(currentBitmap.Height * zoomRatio)
    );

    PointF imageOffset = new PointF(
        (clientSize.Width - zoomedSize.Width) / 2,
        (clientSize.Height - zoomedSize.Height) / 2
    );

    e.Graphics.Clear(Color.White);
    e.Graphics.DrawImage(currentBitmap, imageOffset.X, imageOffset.Y, zoomedSize.Width, zoomedSize.Height);
}

Это эмулирует простоеэффект масштабирования, который центрирует изображение на элементе управления и рисует его по размеру окна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...