【问题标题】:Read the file faster and get the pixel color quickly?更快地读取文件并快速获取像素颜色?
【发布时间】:2017-12-23 21:10:41
【问题描述】:

我有以下代码,它可以正常工作,但是,它工作得非常慢,并且读取带有记录的文件并分析每个像素 - 这花费了太长时间。有什么办法可以让它更快地工作吗?

[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);

static void Main(string[] args)
{
    if (isCorrect("test.LOB"))
    {
        Console.WriteLine("Yes");
    }
    else
    {
        Console.WriteLine("Nope...");
    }
    Console.ReadKey();
    //Record("test", 0, 0, 50, 50, 10);
}

public static void Record(string name, int start_x, int start_y, int end_x, int end_y, int max_Difference)
{
    string path = name + ".LOB";
    string result;
    Color pixel_Result;
    for (int x = start_x; x <= end_x; x++)
    {
        for (int y = start_y; y <= end_y; y++)
        {
            pixel_Result = GetPixelColor(x, y);
            result = x + "|" + y + "|" + pixel_Result.R + "|" + pixel_Result.G + "|" + pixel_Result.B + "|" + max_Difference;
            if (!File.Exists(path))
            {
                using (StreamWriter sw = File.CreateText(path))
                {
                    sw.WriteLine(result);
                }
            }
            else
            {
                using (StreamWriter sw = File.AppendText(path))
                {
                    sw.WriteLine(result);
                }
            }
        }
    }
}

public static bool isCorrect(string path)
{
    using (StreamReader sr = File.OpenText(path))
    {
        string result = "";
        string[] correctedResult;
        while ((result = sr.ReadLine()) != null)
        {
            correctedResult = result.Split('|');
            int X = Convert.ToInt32(correctedResult[0]);
            int Y = Convert.ToInt32(correctedResult[1]);
            int R = Convert.ToInt32(correctedResult[2]);
            int G = Convert.ToInt32(correctedResult[3]);
            int B = Convert.ToInt32(correctedResult[4]);
            int maxDifference = Convert.ToInt32(correctedResult[5]);
            Color c;
            c = GetPixelColor(X, Y);
            maxDifference /= 2;
            if (R < c.R - maxDifference || R > c.R + maxDifference)
            {
                return false;
            }
            if (G < c.G - maxDifference || G > c.G + maxDifference)
            {
                return false;
            }
            if (B < c.B - maxDifference || B > c.B + maxDifference)
            {
                return false;
            }
        }
        return true;
    }
}

static public Color GetPixelColor(int x, int y)
{
    IntPtr hdc = GetDC(IntPtr.Zero);
    uint pixel = GetPixel(hdc, x, y);
    ReleaseDC(IntPtr.Zero, hdc);
    Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                 (int)(pixel & 0x0000FF00) >> 8,
                 (int)(pixel & 0x00FF0000) >> 16);
    return color;
}

提前致谢!

【问题讨论】:

  • 好的,不用进入不安全的方法,马上我看到你正在记录每个循环!最重要的是,您每次都在创建一个新的流作家。
  • 你能告诉我们GetDCGetPixelReleaseDC
  • 我尝试将它包含在上面的代码中,但由于某种原因它不断破坏帖子... [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);
  • 该死,让我再试一次。
  • 您需要突出显示文本并单击帖子工具栏上的按钮{ }。您不能将代码放入 cmets。

标签: c# file file-io streamreader streamwriter


【解决方案1】:

有两个主要问题会减慢您的代码速度。首先,您打开和关闭每个像素的流写入器,这将非常慢。将开口移到环外。还有一个 StreamWriter 的构造函数可以让你指定附加模式,这样你就不需要你的 if/else 检查了。

第二个问题是你也在打开和关闭你的 IntPtr 句柄每个像素,这会很慢,打开一次然后在完成后关闭它。

static public Color GetPixelColor(int x, int y, IntPtr hdc)
{
    uint pixel = GetPixel(hdc, x, y);
    Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                 (int)(pixel & 0x0000FF00) >> 8,
                 (int)(pixel & 0x00FF0000) >> 16);
    return color;
}

public static bool isCorrect(string path)
{
    IntPtr hdc = GetDC(IntPtr.Zero);
    try
    {
        using (StreamReader sr = File.OpenText(path))
        {
            string result = "";
            string[] correctedResult;
            while ((result = sr.ReadLine()) != null)
            {
                correctedResult = result.Split('|');
                int X = Convert.ToInt32(correctedResult[0]);
                int Y = Convert.ToInt32(correctedResult[1]);
                int R = Convert.ToInt32(correctedResult[2]);
                int G = Convert.ToInt32(correctedResult[3]);
                int B = Convert.ToInt32(correctedResult[4]);
                int maxDifference = Convert.ToInt32(correctedResult[5]);
                Color c;
                c = GetPixelColor(X, Y, hdc);
                maxDifference /= 2;
                if (R < c.R - maxDifference || R > c.R + maxDifference)
                {
                    return false;
                }
                if (G < c.G - maxDifference || G > c.G + maxDifference)
                {
                    return false;
                }
                if (B < c.B - maxDifference || B > c.B + maxDifference)
                {
                    return false;
                }
            }
            return true;
        }
    }
    finally
    {
        ReleaseDC(IntPtr.Zero, hdc);
    }
}

public static void Record(string name, int start_x, int start_y, int end_x, int end_y, int max_Difference)
{
    string path = name + ".LOB";

    string result;
    Color pixel_Result;

    IntPtr hdc = GetDC(IntPtr.Zero);
    try
    {
        using (StreamWriter sw = new StreamWriter(path, append:true))
        {
            for (int x = start_x; x <= end_x; x++)
            {
                for (int y = start_y; y <= end_y; y++)
                {
                    pixel_Result = GetPixelColor(x, y, hdc);
                    result = x + "|" + y + "|" + pixel_Result.R + "|" + pixel_Result.G + "|" + pixel_Result.B + "|" + max_Difference;
                    sw.WriteLine(result);
                }
            }
        }
    finally
    {
        ReleaseDC(IntPtr.Zero, hdc);
    }
}

如果在解决 GetPixelColor 中的缓慢问题后,代码仍然太慢,我建议在代码上运行分析器以查看缓慢来自哪一部分,您可以使用 TPL DataFlow 等一些工具将工作流水线化所以像素的读取是单线程的,但是您使用多个线程来测试读取值以查看它们是否正确。

【讨论】:

  • 我已经得到了以下代码:gist.github.com/anonymous/fac075a4cfdf5d3532c5708ea34660da 有什么我应该改变的吗? // 我才意识到我犯了一个错误,对不起,不要看那个
  • 我会将发布放在 try/finally 块中,而不是在每次返回之前,然后您只需要编写一次,如果抛出异常,它仍然会被释放。
  • 看起来不错,不运行就无法判断。如果它仍然太慢,请在代码上运行分析器,看看它在哪里花费的时间最多。如果您发现字符串到 int 的转换是缓慢的部分,并且您不需要 .LOB 文件是人类可读的,使用 BinaryWriterBinaryReader 存储值来读取它可能会更快,因为它不需要进行从字符串到 int 的转换。您甚至可以跳过Color.FromArgb 调用,只需将原始uint pixel 值写入和读取到文件中即可。然后在进行测试时转换为 Color 对象。
  • 如果我写原始的 uint 像素,以后仍然需要转换,所以对我来说没关系。你给我的代码运行起来肯定更快,但是,我不太确定如何使用“BinaryWriter”和 Reader 来让它运行得更快。
猜你喜欢
  • 2013-12-05
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 2017-02-15
相关资源
最近更新 更多