C#两次传递图像

时间:2018-06-17 00:14:01

标签: c# file file-manipulation

因此,我正在构建一个控制台应用程序来生成在多个图像文件之间分割的2D perlin(ish)噪声。我使用的算法要求我在两次通过中进行生成,一次为噪声创建种子,然后生成噪声。我将生成的噪音保存到生成种子的同一文件中,以便减少磁盘空间,并最终使其清洁。我遇到了一个问题,但是在第二次通过期间,我实际上无法访问该文件,因为它已经被另一个进程使用了​​。这是完整的代码,看看是否有任何我遗漏的内容:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace MapGenerator
{
class Program
{
    public static Random rng = new Random();

    public static void Seed(int px, int py)
    {
        Bitmap seed = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        for (int x = 0; x < seed.Width; x++)
        {
            for (int y = 0; y < seed.Height; y++)
            {
                var val = rng.Next(0, 255);
                seed.SetPixel(x, y, Color.FromArgb(255, val, val, val));
            }
        }

        if (File.Exists("chunk," + (px - 1) + "," + (py) + ".jpeg"))
        {
            Bitmap source = new Bitmap("chunk," + (px - 1) + "," + (py) + ".jpeg");
            for (int y = 0; y < 256; y++)
            {
                seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));
            }
        }
        if (File.Exists("chunk," + (px + 1) + "," + (py) + ".jpeg"))
        {
            Bitmap source = new Bitmap("chunk," + (px + 1) + "," + (py) + ".jpeg");
            for (int y = 0; y < 256; y++)
            {
                seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));
            }
        }
        if (File.Exists("chunk," + (px) + "," + (py - 1) + ".jpeg"))
        {
            Bitmap source = new Bitmap("chunk," + (px) + "," + (py - 1) + ".jpeg");
            for (int x = 0; x < 256; x++)
            {
                seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));
            }
        }
        if (File.Exists("chunk," + (px) + "," + (py + 1) + ".jpeg"))
        {
            Bitmap source = new Bitmap("chunk," + (px) + "," + (py + 1) + ".jpeg");
            for (int x = 0; x < 256; x++)
            {
                seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));
            }
        }
        seed.Save("chunk," + px + "," + py + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
        seed.Dispose();
    }

    public static void Perlin(int px, int py)
    {
        Bitmap seed = new Bitmap("chunk," + px + "," + py + ".jpeg");

        Bitmap output = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format24bppRgb);


        for (int y = 0; y < 256; y++)
        {
            for (int x = 0; x < 256; x++)
            {
                double noise = 0.0;
                double scale = 1.0;
                double acc = 0.0;

                for (int o = 0; o < 8; o++)
                {
                    int pitch = 256 >> o;
                    int sampleX1 = (x / pitch) * pitch;
                    int sampleY1 = (y / pitch) * pitch;


                    int sampleX2 = (sampleX1 + pitch);
                    int sampleY2 = (sampleY1 + pitch);

                    sampleX2 = (sampleX2 == 256) ? 255 : sampleX2;
                    sampleY2 = (sampleY2 == 256) ? 255 : sampleY2;

                    double Xblend = (double)(x - sampleX1) / (double)pitch;
                    double Yblend = (double)(y - sampleY1) / (double)pitch;

                    // interpolate between the two points
                    double Tsample = ((1 - Xblend) * ((double)seed.GetPixel(sampleX1, sampleY1).R / 255.0)) + (Xblend * ((double)seed.GetPixel(sampleX2, sampleY1).R / 255.0));
                    double Bsample = ((1 - Xblend) * ((double)seed.GetPixel(sampleX1, sampleY2).R / 255.0)) + (Xblend * ((double)seed.GetPixel(sampleX2, sampleY2).R / 255.0));

                    noise += (((1 - Yblend) * Tsample) + (Yblend * Bsample)) * scale;
                    acc += scale;
                    scale = scale * 0.6;
                }

                noise = noise / acc;

                noise = noise * 255.0;

                output.SetPixel(x, y, Color.FromArgb(255, (int)(noise), (int)(noise), (int)(noise)));
            }
        }
        seed.Dispose();
        File.Delete("chunk," + px + "," + py + ".jpeg");
        output.Save("chunk," + px + "," + py + ".jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
        output.Dispose();
    }

    static void Main(string[] args)
    {
        int depth = 1;

        for(int x = -depth; x <= depth; x++)
        {
            for(int y = -depth; y <= depth; y++)
            {
                Seed(x, y);
            }
        }

        for (int x = -depth; x <= depth; x++)
        {
            for (int y = -depth; y <= depth; y++)
            {
                Perlin(x, y);
            }
        }
    }
}
}

正如你所看到的,我已经尝试了很多处理变量,但无济于事。我有什么想法,我做错了什么?奇怪的是,当它只运行一个函数时,我可以自由地覆盖基本图像文件,但是现在我将它分成两个不同的函数,它都是下坡的,它不会失败。让我操纵文件。

2 个答案:

答案 0 :(得分:1)

您需要处理位图,如下所示

此外,我会使用Lockbits代替GetPixelSetPixel,您将获得更好的效果

public static void Seed(int px, int py)
{
    using (var seed = new Bitmap(256, 256, PixelFormat.Format24bppRgb))
    {
        for (var x = 0; x < seed.Width; x++)
            for (var y = 0; y < seed.Height; y++)
            {
                var val = rng.Next(0, 255);
                seed.SetPixel(x, y, Color.FromArgb(255, val, val, val));
            }       

        if (File.Exists("chunk," + (px - 1) + "," + py + ".jpeg"))
            using (var source = new Bitmap("chunk," + (px - 1) + "," + py + ".jpeg"))
                for (var y = 0; y < 256; y++)
                    seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));           

        if (File.Exists("chunk," + (px + 1) + "," + py + ".jpeg"))
            using (var source = new Bitmap("chunk," + (px + 1) + "," + py + ".jpeg"))
                for (var y = 0; y < 256; y++)
                    seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));      

        if (File.Exists("chunk," + px + "," + (py - 1) + ".jpeg"))
            using (var source = new Bitmap("chunk," + px + "," + (py - 1) + ".jpeg"))
                for (var x = 0; x < 256; x++)
                    seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));

        if (File.Exists("chunk," + px + "," + (py + 1) + ".jpeg"))
            using (var source = new Bitmap("chunk," + px + "," + (py + 1) + ".jpeg"))
                for (var x = 0; x < 256; x++)
                    seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));

        seed.Save("chunk," + px + "," + py + ".jpeg", ImageFormat.Jpeg);
    }
}

使用LockBits关键字如何使用unsafe和指针的示例。基本上你是通过直接访问内存中32位ARBG值的指针通过固定数组中的扫描线访问你的图片

using (var seed = new Bitmap(256, 256, PixelFormat.Format24bppRgb))
{
   // lock the array for direct access
   var bitmapData = seed.LockBits(new Rectangle(0,0,seed.Width,seed.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
   // get the pointer
   var scan0Ptr = (int*)bitmapData.Scan0;
   // get the stride
   var stride = bitmapData.Stride / 4;

   for (var x = 0; x < seed.Width; x++)
      for (var y = 0; y < seed.Height; y++)
      {
         var val = rng.Next(0, 255);
         *(scan0Ptr + x + y * stride) = Color.FromArgb(255, val, val, val).ToArgb();
      }

   seed.UnlockBits(bitmapData);
   ...

答案 1 :(得分:0)

if (File.Exists("chunk," + (px - 1) + "," + (py) + ".jpeg"))
    {
        Bitmap source = new Bitmap("chunk," + (px - 1) + "," + (py) + ".jpeg");
        for (int y = 0; y < 256; y++)
        {
            seed.SetPixel(0, y, Color.FromArgb(255, source.GetPixel(255, y).R, source.GetPixel(255, y).G, source.GetPixel(255, y).B));
        }
        source.Dispose();
    }
    if (File.Exists("chunk," + (px + 1) + "," + (py) + ".jpeg"))
    {
        Bitmap source = new Bitmap("chunk," + (px + 1) + "," + (py) + ".jpeg");
        for (int y = 0; y < 256; y++)
        {
            seed.SetPixel(255, y, Color.FromArgb(255, source.GetPixel(0, y).R, source.GetPixel(0, y).G, source.GetPixel(0, y).B));
        }
        source.Dispose();
    }
    if (File.Exists("chunk," + (px) + "," + (py - 1) + ".jpeg"))
    {
        Bitmap source = new Bitmap("chunk," + (px) + "," + (py - 1) + ".jpeg");
        for (int x = 0; x < 256; x++)
        {
            seed.SetPixel(x, 0, Color.FromArgb(255, source.GetPixel(x, 255).R, source.GetPixel(x, 255).G, source.GetPixel(x, 255).B));
        }
        source.Dispose();
    }
    if (File.Exists("chunk," + (px) + "," + (py + 1) + ".jpeg"))
    {
        Bitmap source = new Bitmap("chunk," + (px) + "," + (py + 1) + ".jpeg");
        for (int x = 0; x < 256; x++)
        {
            seed.SetPixel(x, 255, Color.FromArgb(255, source.GetPixel(x, 0).R, source.GetPixel(x, 0).G, source.GetPixel(x, 0).B));
        }
        source.Dispose();
    }

是的,我忘记了处理源变量。此外,在我写这个答案时似乎有人回答了。