6

I'm using the following code right now, and it works for ~300 images, but I have to merge more than one thousand.

private static void CombineThumbStripImages(string[] imageFiles)
{
    int index = 0;
    using (var result = new Bitmap(192 * imageFiles.Length, 112))
    {
        using (var graphics = Graphics.FromImage(result))
        {
            graphics.Clear(Color.White);
            int leftPosition = 0;
            for (index = 0; index < imageFiles.Length; index++)
            {
                string file = imageFiles[index];
                using (var image = new Bitmap(file))
                {
                    var rect = new Rectangle(leftPosition, 0, 192, 112);
                    graphics.DrawImage(image, rect);
                    leftPosition += 192;
                }
            }
        }
        result.Save("result.jpg", ImageFormat.Jpeg);
    }
}

It throws the following exception:

An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll

Additional information: A generic error occurred in GDI+.

Can somebody help?

csharpwinphonexaml
  • 3,659
  • 10
  • 32
  • 63
Tamás Varga
  • 635
  • 5
  • 17
  • I can't but I do remember getting that error because the source image was in a format that windows/GDI didn't like and I couldn't do anything about it. I was able to open it in MS paint and save it which then worked, but IDK how that can be used on the command line. I tried using imagemagick convert to fix it but no matter what I did it didnt solve the problem and I posted a question which went unanswered. –  Apr 17 '14 at 21:10
  • 2
    Good chance you are running up against limits in GDI+. Try looking at open source image processing packages like aforge.net (www.aforgenet.com/framework/‎). If you're just trying to create a mosaic and don't need to code it yourself, I have had success with http://www.andreaplanet.com/andreamosaic/download/ (free for personal use). – Eric J. Apr 17 '14 at 21:11
  • However if you don't need to load the image in .NET then you can possibly get away with using imagicmagick or a thumbnail command line tool. I can't think of any offhand but I do know I irfanview can merge many images into a single image and it might be able to do it on the command line –  Apr 17 '14 at 21:12
  • Could you include the full error message and stack please? – Adam Zuckerman Apr 17 '14 at 21:12
  • @AdamZuckerman: No, its an internal error. That won't help at all. I seen that exception before and its a lousy error message –  Apr 17 '14 at 21:12
  • 2
    _When_ does it throw the exception? Right at the beginning or after a few iterations (I'm assuming the latter considering what you said)? It might be that you're loading unsupported formats, or running out of memory in your graphics object. I don't really know how GDI handles this, but a few breakpoints may help identifying the problem. – KappaG3 Apr 17 '14 at 21:18
  • ImageMagick will walk that - it's free and scalable and very capable. – Mark Setchell Apr 17 '14 at 21:22
  • It should be done from .Net Code! – Tamás Varga Apr 17 '14 at 21:27
  • @TamásVarga - Side note: "It should be done from .Net Code" is not very detailed respond to comment "about when exception happens". If you don't want/can't provide more information your question is unlikely to be answered. – Alexei Levenkov Apr 17 '14 at 21:57
  • Sorry. I was in hurry. The exception is thrown at the result.Save() method. I'm interested in every solution, even in a 3rd party service. What other information should i provide? – Tamás Varga Apr 17 '14 at 22:01
  • Sombody on [CodeGuru](http://forums.codeguru.com/showthread.php?407837-GDI-Bitmap-size-limitation) may have hit the same limit: "It seems that bitmaps of the GDI+ Bitmap class are limited to a size of 32767 pixels in either direction (width, height)." Can you add rows instead of creating such a huge strip? – TaW Apr 17 '14 at 22:11
  • It's a very good idea, thanks. Requires a lot of code modification, but at least it works. Is there any way to combine them without GDI? – Tamás Varga Apr 17 '14 at 22:41
  • I would create a byte array of the total desired size (max image height x total width). Then stuff this thing with all the raw pixel data from the images (just loop through them and append to the array, while keeping track of the x-offset for each image). Then store it as a raw image, or convert it in code. – Dänu Apr 20 '14 at 10:17
  • I'd be looking at utilising the work done in Seadragon/Photosynth/Deepszoom... http://jonas.follesoe.no/2008/05/31/generating-deepzoom-images-programmatically/ http://blogs.msdn.com/b/jaimer/archive/2008/03/31/a-deepzoom-primer-explained-and-coded.aspx – Mick May 04 '14 at 23:53
  • 2
    The Exception throws when you're appending 342 (192 px) files, but not 341.The width of the resulting Bitmap image for 342 images 65,664. The width of the Bitmap for 341 images is 65,472. GDI+ probably uses an unsigned short int for width and height, whose max value is 65,536. – astallaslions May 19 '14 at 16:38
  • @StephenM Regardless of what the GDI+ is using, .jpeg files are limited to 65,536 x 65,536. – Loren Pechtel Jul 01 '14 at 19:26

2 Answers2

1

Why not use something like xna or opengl to do this?

I know you can with texture2d ... and as i am currently learning opengl id like to think you can with that but do not know how.

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.texture2d_members.aspx (SaveAsJPEG on public)

I have done something similar to make sprite sheets, you basically create a huge texture2d using whatever tesselation or organizing algorithm to optimize space usage. There are lots of ways to do this though.

such as http://xbox.create.msdn.com/en-US/education/catalog/sample/sprite_sheet

would probably only take a couple of hours to do. XNA v easy especially if you are just leaning on the externals. Doing it this was should work pretty well.

John Nicholas
  • 4,778
  • 4
  • 31
  • 50
0

The problems lies in this line of code.

result.Save("result.jpg", ImageFormat.Jpeg);

Looks like it throws an error saving the jpeg/png format. I've loaded a copy of your code into VS2008 + Windows 7.

If you want to use the same code, changed your image format to bmp or tiff

result.Save("result.bmp", ImageFormat.Bmp); // this works, but the file size is huge

or

result.Save("result.tiff", ImageFormat.Tiff); // this also works, files is not as big
Chubosaurus Software
  • 8,133
  • 2
  • 20
  • 26