代码之家  ›  专栏  ›  技术社区  ›  user366312

图像绘制位置不正确

  •  1
  • user366312  · 技术社区  · 6 年前
    bitmap image=readbitmap(“image.png”);
    
    bitmap imagecopy=新位图(图像);
    
    位图画布=新位图(imagecopy.width+100,imagecopy.height);
    
    //从该位图可以获得图形,因为它具有正确的PixelFormat
    使用(graphics g=graphics.fromimage(canvas))
    {
    //将原始位图绘制到新位图的图形上
    g.DrawImage(图像,0,0);
    }
    
    //像使用originalBMP一样使用tempbitmap
    inputPictureBox.image=图像;
    outputPictureBox.image=画布;
    

    我还不明白这个C代码的输出。

    原始图像未放置在正确的位置。它应该已经打开了(0,0)。

    另外,我需要一个黑色背景。

    那么,发生了什么事,如何纠正呢?

    enter image description here

    我还不理解这个C代码的输出。

    原始图像未放置在正确的位置。它应该是打开的(0,0)。

    另外,我需要一个黑色的背景。

    那么,发生了什么事,如何纠正呢?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Jimi    6 年前

    您正在加载图像,然后使用以下命令创建此源的副本:
    bitmap bitmap=new bitmap();

    以这种方式创建图像副本时,会牺牲/更改一些详细信息:
    dpi resolution. :如果未另行指定,则将分辨率设置为用户界面分辨率。96 dpi,作为标准配置;不同的屏幕分辨率和缩放比例可能会有所不同。使用中的系统也会影响此值(Windows 7和Windows 10可能会/可能提供不同的值)
    pixelformat :if not directly copied from the image source or explici在指定的情况下, pixelformat 设置为 pixelformat.format32bppargb

    根据你所说的,你可能想要这样的东西:

    using(bitmap imagesource=(bitmap)image.fromfile(@“[someImageOfLena]”)
    使用(bitmap imagecopy=新位图(imagesource.width+100,imagesource.height,imagesource.pixelformat))
    {
    imagecopy.setresolution(imagesource.HorizontalResolution,imagesource.VerticalResolution);
    使用(graphics g=graphics.fromimage(imagecopy))
    {
    g.透明(颜色:黑色);
    g.compositingMode=合成模式.sourceCopy;
    G.插值模式=插值模式。高质量双三次曲线;
    g.drawimage(imagesource,(imagecopy.width-imagesource.width)/2,0);
    pictureBox1.image=(image)imagesource.clone();
    pictureBox2.image=(image)imagecopy.clone();
    }
    }
    
    
    

    结果如下:
    (上/下框黑色实际上是pictureboxbackground color)

    .

    当原始图像dpi分辨率与使用new bitmap()创建图像副本时使用的基本dpi分辨率不同时,您的结果可能与预期不同。

    在同一场景中,150、96和72 dpi的源图像会发生这种情况:

    <

    另一个重要的细节是IDisposableNature of the Image Object.
    当您创建一个时,您必须dispose()of it;explicit,calling thedisposemethod,or implicitly,encloding the image contructor in ausing statement

    另外,可能的话,不要分配直接从filestream加载的imageobject。 gdi+将锁定文件,您将无法复制、移动或删除该文件。
    使用该文件,绑定到图像的所有资源也将被锁定。

    使用new bitmap()制作副本(如果您不关心上述详细信息),或使用image.clone().,which will preserve th the imagedpi resolutionandpixelformat

    通过这种方式复制图像,您可以牺牲/更改一些细节:
    Dpi Resolution:如果未另行指定,则将分辨率设置为UI分辨率。96 dpi,作为标准配置;不同的屏幕分辨率和缩放比例可能会有所不同。使用中的系统也会影响此值(Windows 7和Windows 10可能会/可能提供不同的值)
    PixelFormat:如果不是直接从图像源复制或明确指定,则PixelFormat设置为PixelFormat.Format32bppArgb.

    根据你所说的,你可能想要这样的东西:

    using (Bitmap imageSource = (Bitmap)Image.FromFile(@"[SomeImageOfLena]"))
    using (Bitmap imageCopy = new Bitmap(imageSource.Width + 100, imageSource.Height, imageSource.PixelFormat))
    {
        imageCopy.SetResolution(imageSource.HorizontalResolution, imageSource.VerticalResolution);
        using (Graphics g = Graphics.FromImage(imageCopy))
        {
            g.Clear(Color.Black);
            g.CompositingMode = CompositingMode.SourceCopy;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(imageSource, (imageCopy.Width - imageSource.Width) / 2, 0);
            pictureBox1.Image = (Image)imageSource.Clone();
            pictureBox2.Image = (Image)imageCopy.Clone();
        }
    }
    

    结果是:
    (上/下框黑色实际上是Picturebox背景色)

    enter image description here

    当原始图像的dpi分辨率与创建图像副本时使用的基本dpi分辨率不同时,new Bitmap(),您的结果可能与预期不同。

    这是相同场景中150、96和72 dpi的源图像所发生的情况:

    enter image description here

    另一个重要细节是IDisposable图像对象的性质。
    当你创建一个,你必须Dispose()明确地称之为Dispose方法,或隐式地将图像构造封闭在Using statement.

    还有,可能,不要指定Image直接从中加载的对象FileStream.
    gdi+将锁定该文件,您将无法复制、移动或删除该文件。
    使用该文件,绑定到图像的所有资源也将被锁定。

    复制时使用新位图()(如果您不关心上述细节),或Image.Clone()将保留图像Dpi Resolution像素格式.

        2
  •  0
  •   Wayne VanWeerthuizen    6 年前

    我不完全清楚你到底需要做什么。但无论如何,这里有一个WPF友好的示例,说明如何在另一个图像中的特定位置绘制图像。

    注意:如果您只想以不同的大小显示图像和/或在图像周围加上黑色边框,有很多简单的方法可以做到,而不必创建第二个图像,例如只需将图像放在已经具有所需边框样式的面板中即可。

    请注意,我正在使用System.Windows.Media命名空间中的类,因为这是WPF所使用的。这些类不容易与System.Drawing命名空间中的旧类混合(一些类名冲突,而且Microsoft的.NET框架缺少在这些类型之间转换对象的内置方法),因此通常需要简单地决定是使用一组还是其他一组绘图工具。我想你一直在尝试使用System.Drawing。每个人都有自己的优缺点,在这里解释起来需要很长时间。

    // using System.Windows.Media;
    // using System.Windows.Media.Imaging;
    private void DrawTwoImages()
    {
        // For InputPictureBox
        var file = new Uri("C:\\image.png");
        var inputImage = new BitmapImage(file);
            // If your image is stored in a Resource Dictionary, instead use:
            //     var inputImage = (BitmapImage) Resources["image.png"];
        InputPicture.Source = inputImage;
    
        // imageCopy isn't actually needed for this example.
        // But since you had it in yours, here is how it's done, anyway.
        var imageCopy = inputImage.Clone();
    
        // Parameters for setting up our output picture
        int leftMargin   = 50;
        int topMargin    = 5;
        int rightMargin  = 50;
        int bottomMargin = 5;
        int width  = inputImage.PixelWidth  + leftMargin + rightMargin;
        int height = inputImage.PixelHeight + topMargin  + bottomMargin;
        var backgroundColor = Brushes.Black;
        var borderColor = (Pen) null; 
    
        // Use a DrawingVisual and DrawingContext for drawing
        DrawingVisual dv = new DrawingVisual();
        using (DrawingContext dc = dv.RenderOpen())
        {
            // Draw the black background
            dc.DrawRectangle(backgroundColor, borderColor, new Rect(0, 0, width, height));
    
            // Copy input image onto output image at desired position
            dc.DrawImage(inputImage, new Rect(leftMargin, topMargin,
                         inputImage.PixelWidth, inputImage.PixelHeight));
        }
    
        // For displaying output image
        var rtb = new RenderTargetBitmap( width, height, 96, 96, PixelFormats.Pbgra32 );
        rtb.Render(dv);
        OutputPicture.Source = rtb;
    }