views:

177

answers:

4

For a network experiment I am conducting, I require image files of arbitrary size.

I am lost on how to create such files. I require 5MB, 10MB and 20MB files in JPEG, PNG and PDF format.

In my first attempt at generating these files it became clear that due to the compression schemes of these formats, it's not possible (or at least I don't know how) to generate files of arbitrary size by just specifying resolution of blank files.

Is there a quick (programmatic?) method by which I could generate these files?

Edit: I am investigating creating arbitrarily sized dummy files, but if there is a way to create actual JPEG, PNGs or PDFs that have the correct internal format, that would be ideal.

+2  A: 

Do the files need to be JPEG format internally, or just arbitrary binary files named JPEG? If the latter, see this Stack Overflow answer:

http://stackoverflow.com/questions/1881050/creating-a-huge-dummy-file-in-a-matter-of-seconds-in-c/1881098#1881098

David M
+1 This was my first thought too. Just create binary files of the exact size you need and name them as .jpg
J.Hendrix
Unfortunately, for the purposes of our experiment, we are trying to determine how they will travel over email, we expect that certain formats may be automatically re-encoded and others may not, so we'd like them to be valid internal formats.
Benjamin Borden
+1  A: 

I would start with a 'huge' file in all of these formats (over max. filesize) and then iteratively resize them using imagemagick convert until you found the specifics for your wanted filesize.

May take some trial and error (can easily be scripted though) but should do for a one-time experiment.

ChristopheD
+2  A: 

This is just a suggestion. No idea if it will work.

Perhaps you could generate bitmaps at the correct size and convert them?

If you make the bitmaps very hard to compress(1)? You should then be able to convert them to jpg and png very close to the target size.

(1) My suggestion is that this might be achieved by making each pixel in the bitmap a different colour (as far as possible)

Edit:
This simple solution probably does not work for jpg's, but at least png's seems to work.

I hacked together a small testapp in c# to try it out. Here is the meat of it:

private void make_bitmap(int width, int height)
{
    Random random = new Random();
    Bitmap B = new Bitmap(width, height);
    int redvalue = 0;
    int greenvalue = 0;
    int bluevalue = 0;

    bool pick_random_color = true;
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < width; y++)
        {
            Color col;
            if (pick_random_color)
            {
               col = Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
            }
            else  // iterate over all colours repeatedly
            {   
                if (redvalue == 255) { redvalue = 0; greenvalue++; } else { redvalue++; }
                if (greenvalue == 256) { greenvalue = 0; bluevalue++; }
                if (bluevalue == 256) { redvalue = 0; greenvalue = 0; bluevalue = 0; }
                col = Color.FromArgb(redvalue, greenvalue, bluevalue);
            }
            B.SetPixel(x, y, col);
        }
    }
    B.Save("image.bmp");
    B.Save("image.jpg", ImageFormat.Jpeg);
    B.Save("image.png", ImageFormat.Png);
    B.Dispose();
}
Nifle
I like this answer. However it's more easily said than done. I was hoping someone around here would have an idea how to implement your suggestion. I did try mocking up a suitably sized gradient (used 32-bit worth of colors in the process) but not knowing the internals of the JPEG or PNG compression schemes, I don't know if I did a good enough job. They managed to compress it down quite a bit.
Benjamin Borden
I quickly tried this . It seems to work for png's but not jpgs. The png was almost the same size as the bitmap but the jpg was always a lot smaller
Nifle
I wish I could pick two answers. I went with the other answer by Lou Franco since he explained some of the issues with JPEG compression. But I will likely use this code as a starting point to implement since it doesn't rely on an external SDK.
Benjamin Borden
+1  A: 

The resolution doesn't change the number of pixels, just the display size of a pixel -- increasing resolution makes the display larger, but doesn't make the file larger.

If you make a JPEG that repeats the same information over and over again it will get bigger -- the compression is on a 8x8 cell basis -- if you have more cells, you'll have more data. To make them bigger, encode with quality set to 100. Another thing, JPEG strips out luminance on a cell basis, so variation in hue compresses worse than variation in luminance.

I used my company's product, DotImage, to create a 10mb jpg with this code. You could download an eval and try it out, or do the same with your image SDK.

using System;
using System.Drawing;
using Atalasoft.Imaging;
using Atalasoft.Imaging.Codec;
using Atalasoft.Imaging.Drawing;

namespace MakeLargeImage
{
    class Program
    {
        static void Main(string[] args)
        {
            AtalaImage img = new AtalaImage(1000, 8000, PixelFormat.Pixel24bppBgr);
            Canvas c = new Canvas(img);

            for (int block = 0; block < img.Height; block += 1000)
            {
                for (int line = 0; line < 1000; line += 4)
                {
                    int y = block + line;
                    c.DrawLine(new Point(0, y), new Point(img.Width, block), new AtalaPen(Color.Yellow));
                    c.DrawLine(new Point(0, y + 1), new Point(img.Width, y + 1), new AtalaPen(Color.Red));
                    c.DrawLine(new Point(0, y + 2), new Point(img.Width, y + 2), new AtalaPen(Color.Green));
                    c.DrawLine(new Point(0, block), new Point(img.Width, y + 3), new AtalaPen(Color.Blue));
                }
            }
            JpegEncoder jpeg = new JpegEncoder(100);
            img.Save("10mb.jpg", jpeg, null);
        }
    }
}

If you make the image pixel size larger, the JPEG file will get larger. You could also add in meta-data, but it's hard to get a big file with just meta-data as there are some size limitations.

PDF is the easiest -- just make a big page with uncompressed image and keep adding pages -- it will get big fast -- there's no compression unless you turn it on. You can do this easily in DotImage with the PdfEncoder -- just give it a list of jpgs in a FileSystemImageSource -- code not shown as to not bore everyone, but I'd be happy to provide it to anyone that wants it -- just call Atalasoft and ask for me (or open a support case and reference this question.

Lou Franco
I wish I could pick two answers. I went with this answer because you shed light on some of the underlying processes that would make this a challenge. Although, I will likely use Nifle's code as a starting point with this information in hand.
Benjamin Borden