themcp has asked for the wisdom of the Perl Monks concerning the following question:

Okay, have finally given up on this and need some help. I've searched the web and have seen folks reply about this topic but the answers given were either a work-around for the person who originally needed help and the answer didn't fulfill the requirements for what I need or the web topic simply doesn't fit.

I'm basically trying to automate print-quality images using the GD module using a 300dpi source image. This source image is a backdrop to a final image that has text / charts / photos applied on top of it using GD. On every variation that I know about for opening and writing a new image file with GD, it will not create anything other than a final output image at 72dpi. I need to automate this because our group has to be able to output up to a dozen print-quality statistical report marketing pieces every month and it is very tedious doing it by hand.

This is being done on Windows 10. GD is at version 2.5 (latest). For my perl config, I have specified just these two load lines:
use GD;

I've created test input files at 300dpi (both jpg and png). Just to keep this simple, I've tried every combination of the following:

$source_image = GD::Image->newFromPng("300dpi_test.png",1);
#$source_image = GD::Image->newFromJpeg("300dpi_test.jpg",1);

#$blank_rgb_image = GD::Image->new(2550, 3300, 1 );
#my $blank_rgb_image = GD::Image->newTrueColor(2550, 3300);
binmode F;
print F $source_image->jpeg(90);
#print F $blank_rgb_image->jpeg(90);
#print F $blank_rgb_image->png;

I've tried to tell GD to open the source image with true color support and just dump the source image to a new file. No luck. I've tried opening the source at true color and then creating a new object image using true color (both with the "1" flag AND using the "newTrueColor" method) then copying+pasting the source image to the new image object... neither method works.

Yes, I could inflate the source size of the 300dpi Photoshop file backdrop image and then try to do everything in 72dpi then resample using Photoshop again after the changes are made but these files wind up being huge, the manipulated imaging pixels would be 4x the normal size and it would then require a 3rd party imaging editor to do the conversion back to 300dpi. There has to be a better solution so that everything can be done in the background... just not sure if GD can really do it.

Any help would be appreciated!

Replies are listed 'Best First'.
Re: GD @ 300dpi output
by BrowserUk (Patriarch) on Mar 27, 2016 at 05:49 UTC

    You are confused. An image contains pixels. Those pixels only become dpi when you print them. GD, has nothing whatsoever to do with printing.

    The exact, bit for bit, binary identical, same image can be printed at 72 dpi or 300 dpi or 1 dot per metre if you want it really big.

    A 2550 x 3300 printed at 72 dpi will be 35.416" x 45.833". The same image printed at 300dpi will be 8.5" x 10". The content of the image file doesn't change at all.

    What is telling you that the images produced using GD are "72dpi"?

    Looking again, I see you are outputting to jpg format. That is the wrong thing to do if you want to retain quality.

    For more information about the confusion that Photoshop creates, read: (You'll just have to forgive the photographer the hideous layout:) the information is good.)

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: GD @ 300dpi output
by Anonymous Monk on Mar 27, 2016 at 09:41 UTC
    BrowserUk has already said it, but for a computer, the specification "300dpi" by itself is useless, because it only tells us what density you want to print at. For it to be useful for the computer, you need to say something like "3000x2000 pixels printed at 300dpi" (which will result in a print of roughly 25.4x16.9cm), or "10x20cm at 300dpi", which is an image of 1181x2362 pixels. That same 1181x2362 pixel image can also be printed at 600dpi, in which case it will be 5x10cm, or at 150dpi, in which case it will be 20x40cm.

    Anyway, maybe what you are asking about is the DPI information stored as part of the image headers. I have had success in changing it using Image::ExifTool, at least this changes the image's DPI reported by The Gimp.

    use Image::ExifTool; my $DPI = 300; my $exif = Image::ExifTool->new; $exif->SetNewValue("XResolution",$DPI); $exif->SetNewValue("YResolution",$DPI); $exif->SetNewValue("ResolutionUnit","inches"); $exif->WriteInfo($FILE) or warn "Failed to update EXIF in $FILE";
    Or on the command line:
    exiftool -XResolution=300 -YResolution=300 -ResolutionUnit=inches file +.jpg
    For the computer, this DPI information is relatively useless, because the computer only cares about how many pixels the image has. You can change this header all you want and the pixel data will not change, the image will not be resized to a different number of pixels. The DPI information will only become useful to a printer. But most printers that I know will always let you specify the DPI you want to print with as a separate setting. The only scenario I can imagine where the above will be useful to you is if you have some program or printer that does care about the DPI information stored in the image header.
      Yes! ... holy cow, finally a way to set the dpi value. Image::ExifTool is exactly what I needed - worked perfectly. Thank you for the recommendation and sample code.

      I had always assumed that GD would retain the source dpi value if you use a particular setting but simply couldn't find a way to have it set a desired value in the output file.

      The problem I was having is that when the batch job goes to send the image file to the printer, the dpi reduction changed the image to 35 inches wide instead of 8.5 and I'd have to go in and reset the dpi value in Photoshop every time. As BrowserUK said, I'm not completely in tune with how the conversions work so I appreciate the link to the explanation web page... will try to better understand the mechanics of dpi versus pixel counts going forward.

      And yep, jpg compression probably isn't the best format to use but it is just an office printer doing the work... didn't have to be photo quality. At 95% output it is pretty clear in the final print. May look into using png - I think that is lossless but it's been awhile since I've read up on it.

      Thanks again for the assistance and solution!
        Glad it helped :-)

        will try to better understand the mechanics of dpi versus pixel counts going forward.

        Here's a try: In the world of bitmaps, only the pixel counts matter. A bitmap has a width in pixels, and a height in pixels. "DPI", or "Dots Per Inch", is as the name says a measure of how dense the pixels are in the physical world, how many of them per inch are input/output. By itself, a bitmap does not have "DPI". Only your monitor, printer and scanner have a measure of DPI. The DPI information in the bitmap header is only a hint for output!

        So by itself, DPI is a measure of print quality only. It does not tell you anything about the size of the bitmap. Only in combination with a size in pixels or a size in inches or centimeters is it a measure of bitmap size. It's kind of like miles and mph, or kilometers and km/h - kilometers (DPI) are related to km/h (DPI+size), but they're measuring/expressing different things!

        When you're talking to a graphics designer or a printer, they're much more used to thinking in DPI. That's why you'll need to translate between the language of "X by Y pixels" and "Z DPI at X by Y cm"/"Z DPI at X by Y pixels" - try typing "10 inches at 300 dpi" or "3000 dots / 300 dpi" into Wolfram Alpha ("dots"="pixels"). The confusion starts happening when people forget to specify a size - a designer might tell you "I need the image at 300 DPI" and forget to tell you the dimensions of the image, or "I need the image to be A5" without telling you the DPI! In my experience this happens regularly, and you'll have to get used to asking for the missing information.

        Some bitmap processing tools try to be helpful to people who live in the world of DPI by specifying sizes with DPI and in/cm everywhere. They try to take into account the DPI measures of your monitor and printer, font sizes, etc. in order to try to present a world that can always be measured in inches or centimeters (and DPI). And when loading bitmaps into such software, it may take into account the DPI information stored in the bitmaps' headers. However, this world often clashes with the world of bitmaps, and people who only think in pixels - for example web designers, who are much more used to pixels.

        It can be confusing, kind of like the German tourists who are regularly questioned by US Customs as to whether they want to poison their relatives!

        Personally, I always just do everything in pixels, and convert to and from the language of "X by Y cm at Z DPI" only when talking to people who think in those terms.

        Graphics Department: "We need the image at 600 DPI."
        You: "Okay, what's the largest you want to print that at?"
        Graphics Department: "We're thinking 5 by 8 cm right now but we may make it as big as 10 by 16 cm."
        At this point you know you need to make the bitmap 2362 by 3780 pixels large, and that you may need to scale down the number of pixels later. Scaling down a photo is of course no problem at all, but if it contains small fonts or fine lines that won't survive the scaling down, you might need to make a second version of the bitmap.

        When handing off a bitmap back to the graphics department, you just set the "print size", i.e. the DPI information in the bitmap headers, using for example the "Print Size" menu item in Gimp's "Image" menu, or the method in the above post. This does not affect the pixels at all, only the "hint" in the bitmap's header as to what DPI it was intended to be printed at (and whoever or whatever is now handling the image can choose to use any other DPI value they want).

        If the graphics department comes to you later and says something like "the printer has asked for the image to be at 1200 DPI", then in my experience this issue can often be settled by simply scaling up the size of the bitmap to twice its size in pixels - even though because you've simply interpolated the image to a larger number of pixels, the quality of the image will be the same as a 600 DPI image, some printers just want a specific number of pixels per inch because that's what they're printing at (maybe the graphics department has specified that the texts on the page should be printed at 1200 DPI, and the image next to the text can't be printed at a different number of dots per inch). Only if the graphics department later complains about the quality of the image, do you have to tell them "sorry, you asked for 600 DPI and that's what you got, if you now really want 1200 DPI I'll have to redo the whole image".

        That's my brain dump on the topic, HTH!

Re: GD @ 300dpi output
by nysus (Parson) on Mar 27, 2016 at 15:48 UTC