在n x m图像中分割图像 [英] Splitting an image in n x m images

查看:137
本文介绍了在n x m图像中分割图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在程序中使用了一些大的精灵表(最大2048 x 2048像素,png 32位).

现在,我有以下选择:
1.在图像编辑器中分割图像,然后将各个精灵作为资源添加到我的程序中(我不喜欢这种方法)
2.加载图像,将其拆分,保留零件,然后进行处理. (我最喜欢这个,因为这项工作只完成了一次)
3.加载图像,保留它,并在需要时从其中除去精灵.

至于实际的拆分,我想到了两个选择:
1.首先将其拆分为行,然后使用ImageList s将其拆分为单个单元格中的行.

I have some large sprite sheets (up to 2048 x 2048 pixels, png 32 bit) which I use in my programs.

Now, I have the following options:
1. Split the image in an image editor and add the individual sprites to my program as resources (I don''t like this approach)
2. Load the image, split it, keep the parts and then dispose it. (I like this most, as the job is done only once)
3. Load the image, keep it and get the sprites out of it when needed.

As for the actual splitting, I thought of two options:
1. Split it first in rows and then the rows in individual cells using ImageLists.

private static ImageList Split(Bitmap image, int width, int height)
{
    ImageList rows = new ImageList();
    rows.ImageSize = new Size(image.Width, height);
    rows.Images.AddStrip(image);
    ImageList cells = new ImageList();
    cells.ImageSize = new Size(width, height);
    foreach (Image row in Rows.Images)
    {
        cells.Images.AddStrip(row);
    }
    return cells;
}


(粗糙的代码,仅用于示例)


2.使用Graphics在画布上绘制它的一部分.


(rough code, just for purpose of exemplification)


2. Draw portions of it on a canvas using Graphics.

private static ImageList Split(Bitmap image, int width, int height)
{
    ImageList cells = new ImageList();
    cells.ImageSize = new Size(width, height);
    Bitmap bmp = new Bitmap(width, height);
    Graphics g = Graphics.FromImage(bmp);
    for (int i = 0; i < image.Width / width; i++)
    {
        for (int j = 0; i < image.Height / height; j++)
        {
            g.DrawImageUnscaled(image, -i * width, -j * height);
            cells.Images.Add((Bitmap)bmp.Clone());
        }
    }
    return cells;
}


(粗糙的代码,仅用于示例)


但是,这两种方法都相当慢... :(
必须有更好的方法!
有人可以给我一些想法吗?
谢谢.

如果您认为这是一个好问题,请投票.


(rough code, just for purpose of exemplification)


However, both methods are quite slow... :(
There must be a better way!
Can someone give me a few ideas?
Thank you.

If you think this is a good question, please vote it.

推荐答案

利用线程并工作计算机的好机会处理器.

将图像分成几行(应该比较快),然后将它们放入队列中.使用单独的线程在每一行上工作.将所有图像添加到集合中,并在队列中的所有项目都完成后保留该集合.

使用队列的同步版本,这里有文章 [^ ].

编辑说:我确实认为这是线性缓慢的东西的一个很好的例子,但是如果您将其线程化,它会很好地滴答作响.这些是离散的,不相关的任务,需要一些时间才能完成...换句话说,非常适合线程化.

干杯.
Good opportunity to take on threads and work your machine''s processor.

Split the image into rows (which should be relatively quick), then put those into a queue. Work on each row with individual threads. Add each image to a collection and persist the collection when all the items are completed in the queue.

Use the sync''d version of the queue, there''s an article here[^].

Edit to say: I do really think this is a good example of something that is slow linearly, but would tick along quite nicely if you thread it. These are discrete, non-related tasks that take a while to do...in other words, ideal for threading.

Cheers.


好吧,您也可以选择使用lockbits路由.

鲍勃·鲍威尔(Bob Powell)在GDI,图像处理和.NET主题上有很多(系列)文章.锁定位在此处 [
Well, you could alternatively go the lockbits route.

Bob Powell has a great (series of) article(s) on the topic(s of GDI, image processing and .NET). Lockbits is here[^].

This will require a lower level of processing (and understanding of the image) but should be much faster.

Cheers.


我自己找到了另一种方法,使用Bitmap.Clone(Rectangle rect):
I found another way myself, using Bitmap.Clone(Rectangle rect):
private static int Main(string[] args)
{
    if (args.Length < 3)
    {
        Console.WriteLine("Error 1: Not enough arguments. Usage: SplitImage filename cellwidth cellheight");
        return -1;
    }
    string filename = args[0];
    if (!File.Exists(filename))
    {
        Console.WriteLine("Error 2: File not found.");
        return -2;
    }
    ushort width;
    ushort height;
    if (!ushort.TryParse(args[1], out width))
    {
        Console.WriteLine("Error 3: Cannot parse cell width.");
        return -3;
    }
    if (!ushort.TryParse(args[2], out height))
    {
        Console.WriteLine("Error 4: Cannot parse cell height.");
        return -4;
    }
    Bitmap bmp = null;
    try
    {
        bmp = (Bitmap)Image.FromFile(filename);
    }
    catch
    {
        Console.WriteLine("Error 5: Cannot load image from file.");
        return -5;
    }
    if (width == 0)
        width = (ushort)bmp.Width;
    if (height == 0)
        height = (ushort)bmp.Height;
    int columns = bmp.Width / width;
    int rows = bmp.Height / height;
    int cells = columns * rows;
    if (cells == 0)
    {
        Console.WriteLine("Warning: Cannot split image in 0 cells.");
        return 0;
    }
    string dir;
    try
    {
        dir = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename);
        if (!Directory.Exists(dir))
            Directory.CreateDirectory(dir);
    }
    catch
    {
        Console.WriteLine("Error 6: Cannot create directory for cells.");
        return -6;
    }
    Console.WriteLine();
    Console.WriteLine("About to split image in {0} rows x {1} columns = {2} cells...", rows, columns, cells);
    Console.WriteLine();
    int cellpadding = (cells - 1).ToString().Length;
    int rowpadding = (rows - 1).ToString().Length;
    string cellfile;
    string cellpath;
    try
    {
        for (int row = 0; row < rows; row++)
        {
            Console.Write("Row " + row.ToString().PadLeft(rowpadding, ' ') + ":  ");
            for (int column = 0; column < columns; column++)
            {
                cellfile = (row * columns + column).ToString().PadLeft(cellpadding, '0');
                cellpath = dir + Path.DirectorySeparatorChar + cellfile + ".png";
                bmp.Clone(new Rectangle(column * width, row * height, width, height), bmp.PixelFormat).Save(cellpath, ImageFormat.Png);
                Console.Write(cellfile + "  ");
            }
            Console.WriteLine();
        }
        Console.WriteLine();
        Console.WriteLine("{0} files written to disk.", cells);
        Console.WriteLine();
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error 7: " + ex.Message);
        return -7;
    }
    return cells;
}


这篇关于在n x m图像中分割图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆