Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

How to create JPEG of specified size

by Limbic~Region (Chancellor)
on Jul 25, 2007 at 14:23 UTC ( [id://628683]=perlquestion: print w/replies, xml ) Need Help??

Limbic~Region has asked for the wisdom of the Perl Monks concerning the following question:

All,
I have a task where I need to be able to replace JPEG images with a fake. The fake need only be roughly the same size as the original. In other words, I do not care if the fake is a single white dot or the blue screen of death. I have never used Image::Magick nor done anything like this so any help is appreciated.

Update: To clarify, my use of size refers to the file size on disk and not necessarily the dimensions of the image. I do not care about the relationship of dimensions of the fake to the original as long as the size on disk is roughly the same. I have /msg'd the authors of responses about this update in case their advice doesn't apply.

Cheers - L~R

Replies are listed 'Best First'.
Re: How to create JPEG of specified size
by halley (Prior) on Jul 25, 2007 at 14:29 UTC
    With ImageMagick installed,
    system("convert xc:white -geometry 200x200 output.jpg");
    or
    my $image = new Image::Magick(geometry => '200x200'); $image->Read('xc:white'); $image->Write('output.jpg');
    See http://www.imagemagick.org/script/perl-magick.php for more details.

    If you want to READ a given file, figure out its size, and use that, then you will also want the following:

    my $original = new Image::Magick(); $original->Read('original.jpg'); $geometry = $original->Get('geometry');
    (The 'xc:____' is a "virtual limitless file" for input, kinda like /dev/urandom, except all pixels are of the named color. You can use #FFFFFF notation here too. Or supply an original image filename without the 'xc:' prefix.)

    --
    [ e d @ h a l l e y . c c ]

      In reference to a private message, Limbic~Region, it sounds like you're more interested in bulking up the file to emulate a large download or a large disk load. There are some thoughts about this.

      If jpg is your target format, bulking it up on disk is easy: write a simple small .jpg file, then append as much random binary garbage that you want after it. This will satisfy your desire to make the file bigger without having to go through some tedious guesstimate loop that makes more PIXELS to satisfy the requirements of more BYTES.

      If your intent is to create a larger download, either for stress testing your system or for poisoning a bandwidth hog, then this is a bit trickier: I don't think any browsers are smart enough to parse the jpg as it reads it (and stops when it reaches the end of valid jpg data), but theoretically one could. If you give a 1x1 pixel image with a megabyte of junk following, the jpg parser could stop after the first hundred bytes and not bother reading or downloading the rest. You'd have to do some tests to ensure you're seeing that the whole thing is getting downloaded.

      If someone's leeching your bandwidth by deeplinking your jpg on your server, and you replace it with a surrogate, I suggest NOT inflating the file to hurt the downloader, since you're ultimately paying the bandwidth on your side too. Make a 1x1 or a highly-compressed "bandwidth hog" image to replace the original.

      With GD or ImageMagick, if you want to make more PIXELS to make a genuine image that happens to require more BYTES (disk or memory), then I suggest you create a small original, then use these APIs to create a "stretched" equivalent of it at larger dimensions. This will ensure the jpg parser must read the whole thing. An image that is all-white or all-red, like the previous examples, will compress VERY well, so you will have a lot of PIXELS that don't take much disk space.

      --
      [ e d @ h a l l e y . c c ]

        halley,
        The fake file has to be a valid JPEG and the purpose for needing this has nothing to do with web servers. If you have any ideas on how to manipulate an dummy image through trial and error to reach an approximate target size I would be most appreciative.

        Cheers - L~R

Re: How to create JPEG of specified size
by jasonk (Parson) on Jul 25, 2007 at 14:34 UTC

    I haven't done much with Image::Magick either, but this is trivial with GD...

    use GD; my $img = GD::Image->new( $width, $height ); # The first color allocated becomes the background color $img->colorAllocate( 255, 0, 0 ); # $img->jpeg will return the image data, you can then # save it to a file, or print it with an image/jpeg # header or whatever you want to do... print $img->jpeg();

    We're not surrounded, we're in a target-rich environment!
Re: How to create JPEG of specified size
by ikegami (Patriarch) on Jul 25, 2007 at 15:04 UTC

    Does the fake have to be a valid JPEG file, or just a file whose name ends with .jpg? The latter would be particularly easy to do.

    If you want to produce a valid JPEG of a certain size, you play with the quality setting. It's trial an error. The amount of colours in the image will have an impact. You could also add JFIFEXIF tags to the image to increase its size.

    Update: JFIF is the .jpg file format. EXIF is what the tags are called.

      ikegami,
      Yes, a valid JPEG that is relatively close in filesize to the original. If you have code that exercises the trial and error or the JFIF EXIF tags I would be most appreciative.

      Cheers - L~R

        Sorry, I don't. In fact, Image::Magick would ignore the quality setting when I tried to use it in the (distant) past.
Re: How to create JPEG of specified size
by BrowserUk (Patriarch) on Jul 25, 2007 at 15:21 UTC

    Just append an approriate amount of junk to the end of a real jpg that it smaller in size. The appended junk will simply be ignored be every tool, including two browsers I have tried.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      BrowserUk,
      Thanks but I do not want the junk to be ignored. In a nutshell, I need to test production like data in a development environment where the actual production data can not be used (no exceptions). Since the testing will include performance as well as functionality, the images need to be roughly the same in terms of size. I apologize but I can't be more specific about how the images are used or why I can't use the production data.

      Cheers - L~R

        I do not want the junk to be ignored.

        What does "ignored" mean? Clearly you're not expecting to do anything with the image. That sounds like a kind of ignoring.

        My suggestion would be to add bulk in the jpeg comment:

        my $jpeg = create_jpeg( height => 1, width => 1 ); save_jpeg_file( $jpeg, $file ); insert_jpeg_comment( $jpeg, ' ' x ($desired_size - (-s $file)) ); # bu +lk up the comment save_jpeg_file( $jpeg, $file ); # adjust again if necessary.

        (note - functions above are pseudo.)

        A word spoken in Mind will reach its own level, in the objective world, by its own weight

        The entire file will be downloaded, or loaded by whatever application you open it with.

        For example, I appended ~45K of 'AAA' to the end of the first image below using

        copy 4344.jpg/b+con junk.jpg and just holding down the A key for a few seconds.

        2005-09-19 09:47 15,996 4344.jpg 2007-07-25 16:25 60,532 junk.jpg

        When I load the first one into ifranview it tells me

        Disk size: 15.62 KB (15,996 Bytes) Memory size: 239.09 KB (244,828 Bytes) Loaded in: 15 milliseconds

        When I view the second it says:

        Disk size: 59.11 KB (60,532 Bytes) Memory size: 239.09 KB (244,828 Bytes) Loaded in: 16 milliseconds

        Also, I took the largest jpg I have (19MB) and copied it to another file twice. When I load these two I get

        18.92 MB (19,838,175 Bytes) 667.42 MB (699,840,040 Bytes) 8891 milliseconds

        37.84 MB (39,676,350 Bytes) 667.42 MB (699,840,040 Bytes) 9734 milliseconds

        So the on-disk size is just one (small) part of 'performance'.

        If this is critical, then you should be more concerned with matching the compression level, whether they are interlaced, the numbers of color table entries, and the final expansion size (essentially X x Y x depth) because these will all have a much greater impact on display time peformance, and memory usage, and the time taken to allocate the memory, than the time taken to load off disk will.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to create JPEG of specified size
by Anonymous Monk on Sep 12, 2007 at 13:50 UTC
    Given an input image, it is possible to create a jpeg image of a given file size - with some small error of course. Have a look at the following software package: http://freshmeat.net/projects/jpegfit/

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://628683]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-25 10:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found