Missing half of first pixel column after a Graphics Transform Scale

故事扮演 提交于 2019-12-19 02:04:10

问题


I have noticed that the half of the first pixel column of the image is not drawn after a Graphics Transform Scale on the OnPaint event.

All the code needed to reproduce it is at the end of the post. Basically I've created a Class derived from PictureBox called PictureBox2 and it overrides the OnPaint method to perform the Scale transformation. It also changes the InterpolationMode to NearestNeighbor to prevent Graphics from changing the pixels look.

The PictureBox control was added to a Form called Form6_GraphicsTest. The control is anchored in all sides. The PictureBox2 back color was changed to blue and the Form back color to dark grey.

As you can see on the image below, only 1/2 of the first pixel column of the image is drawn. Why?? Am I missing something here??

Here is the original 10x10 8bpp image:

EDIT - Solution For some ODD reason PixelOffsetMode.Default eats up 0.5 pixel. Solution: PixelOffsetMode.Half or HighQuality!

Code PictureBox2.cs

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace GraphicsTest
{
    public class PictureBox2 : PictureBox
    {
        public PointF Zoom = new PointF(20, 20);
        private InterpolationMode interpolationMode = InterpolationMode.NearestNeighbor;

        /// <summary>
        /// Paint the image
        /// </summary>
        /// <param name="e">The paint event</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (IsDisposed)
                return;

            if (Image != null)
            {
                if (e.Graphics.InterpolationMode != interpolationMode)
                    e.Graphics.InterpolationMode = interpolationMode;

                using (Matrix transform = e.Graphics.Transform)
                {
                    //e.Graphics.ResetTransform();

                    if (Zoom.X != 1.0 || Zoom.Y != 1.0)
                        transform.Scale(Zoom.X, Zoom.Y, MatrixOrder.Append);

                    //if (ImageDisplayLocation.X != 0 || ImageDisplayLocation.Y != 0) //Convert translation back to display pixel unit.
                    //    transform.Translate(ImageDisplayLocation.X / Zoom.X, ImageDisplayLocation.Y / Zoom.Y);

                    e.Graphics.Transform = transform;
                }
            }

            base.OnPaint(e);

            //If you want to draw something over the control in control coordinate, you must first reset the transformation! :D
            //e.Graphics.ResetTransform();
            //Draw your stuff
        }
    }
}

Code Form6_GraphicsTest.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GraphicsTest
{
    public class Form6_GraphicsTest : Form
    {
        public Form6_GraphicsTest()
        {
        InitializeComponent();
        Bitmap bmp = new Bitmap(@"D:\Test 10x10.8bpp.png");
        this.pictureBox21.Image = bmp;

        this.pictureBox21.Zoom = new PointF(20,20);

        this.ClientSize = new Size(Convert.ToInt32(this.pictureBox21.Zoom.X * bmp.Width) + 30, Convert.ToInt32(this.pictureBox21.Zoom.Y * bmp.Height) + 30);
        }

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.pictureBox21 = new GraphicsTest.PictureBox2();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox21)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox21
            // 
            this.pictureBox21.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.pictureBox21.BackColor = System.Drawing.SystemColors.Highlight;
            this.pictureBox21.Location = new System.Drawing.Point(12, 12);
            this.pictureBox21.Name = "pictureBox21";
            this.pictureBox21.Size = new System.Drawing.Size(260, 238);
            this.pictureBox21.TabIndex = 0;
            this.pictureBox21.TabStop = false;
            // 
            // Form6_GraphicsTest
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.ControlDarkDark;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.pictureBox21);
            this.Name = "Form6_GraphicsTest";
            this.Text = "Form6_GraphicsTest";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox21)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private PictureBox2 pictureBox21;
    }
}

回答1:


Could it be related to PixelOffsetMode? This might be related to this other post. It has do with efficiency of rendering...



来源:https://stackoverflow.com/questions/20776605/missing-half-of-first-pixel-column-after-a-graphics-transform-scale

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!