dpi question (xresolution, yresolution)

Started by Blaumeise00, March 20, 2023, 06:32:36 AM

Previous topic - Next topic

Blaumeise00

i am trying to get the dpi (horizontal resolution and vertical resolution) from jpeg exif metadata contained in e1 markers. I program using php.

i have read that the 0x1a and 0x1b markers contain addresses to the data. I have found a way to calculate these addresses. i assumed that what i see in most photos is an algorithm to getting the correct dpi number. i usually see four bytes: 00 48 00 00. Great! i can use unpack('n2', $var) to get the number. everything is working using my test photos except for a polaroid photo.

i have been testing code using the following github page with sample photos:
https://github.com/ianare/exif-samples/tree/master/jpg
WWL_(Polaroid)_ION230.jpg

for the problematic polaroid photo, the address in the 0x1a xresolution tag contains the following:
46 48 00 00 01 00 48 00 00 00

my code currently jumps to the address given in the 0x1a field. I usually land on the resolution number and i have to go back 1 byte to get the next four bytes.
if i go back 1 byte in the polaroid photo, then i end up at 46 and not 0:
46 48 00 00 is not 72.

i cannot unpack 2 bytes. i need four to use unpack or php throws an exception.

all other photos have the correct values.
is this polaroid 'out-of-bounds'?
i mean, shouldn't this address contain 4 bytes (00 48 00 00)?

i suppose that the bigger question is am i doing this correctly? i have no idea how it is supposed to be extracted correctly. is there an easier way to get the dpi from the e1 exif data? standard jfif has density at the end of the signature, which is nice and simple.

otherwise, is anyone able to offer a solution? should i just add two 0 bytes to two numbers?
so grab the 48 00 and add 00 48 00 00, then unpack? but this is programmatic cheating (forcing desired results).


Phil Harvey

#1
Look at the file using the exiftool -htmldump output in your browser.

- Phil

Stargeek edit to add example


(thanks for the example StarGeek - PH)
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Blaumeise00

Hello Mr. Harvey,

your exif tool reports 72 dpi, Windows reports 72dpi but neither Microsoft or you are telling me how you are reading this data.

i am learning using information from MIT:
https://www.media.mit.edu/pia/Research/deepview/exif.html#IFDRead
if you read this information, then you see that the example has four bytes: 00 48 00 00

i expect that the address in jpeg photos has four bytes. The polaroid has three with a 46:
46 48 00 00 - 00 01 - 00 00 00 00 48 00 00

i cannot read this address with my current code because it is expecting 00 48 00 00 and not 46 48 00.

how am i supposed to read this address? do you have any suggestions of how to fix my code?

should i only extract the next two bytes? in this example, i would get 48 00
then i would have to add two bytes in order to unpack it but this feels wrong.
i have to have at minimum two bytes to be able to find 2c 01 (300 dpi).

i am not coding an exif reader. i am scanning images for code injection. However, as long as i am reading the file, then i would like to grab some of the data from the image. In this case, i would like to get the resolution from the jpeg.



StarGeek

Quote from: Blaumeise00 on March 20, 2023, 08:24:09 AMyour exif tool reports 72 dpi, Windows reports 72dpi but neither Microsoft or you are telling me how you are reading this data.

Make sure you are using the command in FAQ #3 to list the data.  There are multiple X/YResolution tags that can be embedded in a file.

The most common will be in the JFIF and EXIF groups, but the Photoshop is also common, especially when processed by Lightroom/Photoshop.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Blaumeise00

Hi StarGeek,

Thanks for replying. I appreciate you and Mr. Harvey for taking time to reply.

The problem for me with other places is that IFD0 is reporting info on the main image. Other directories could easily refer to, for example, a thumbnail. There is no rule that the thumbnail must contain the same resolution as the main image. If i read the thumbnail resolution, then i could potentially be reading the wrong resolution data, I base my resolution on the data contained in 0x1a and 0x1b of the main image. It is working except for Polaroid which for some reason adds an F (70) to the horizontal density (FH 00 00 00 CntrlChar 00 00 00 H, when viewed in Notepad++ at position 192).

I decided to jump to the address in 0x1b and use that instead, since it does not contain the 46 in any image and the horizontal and vertical res is always the same anyway. I could easily fread backward to be certain that the numbers match. I suppose that since i cannot find an answer to the FH 46 48 polaroid value, i will have to accept my current method of using the value from 0x1b.

I am happy that i am only trying to extract certain data from exif and not writing an exif reader. I have no idea how Mr. Harvey could battle these concepts and keep his sanity. Programming can be very frustrating.

Blaumeise00

By the way, i forgot to mention that i did find a resolution to the problem using unpack and it works but only with this polaroid 46 48 00 value.

$testDataField = unpack('c2/h', "\x46\x48\x00");

I arrive at 72 which is nice but then i would have to use an if block to test the firstread for a 46 special case.
I find it easier to jump to the vertical resolution entry instead.

Phil Harvey

You should be taking into account the resolution units when interpreting the resolution values.  They may be inches or cm (or "none", whatever that means).

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Blaumeise00

Quote from: Phil Harvey on March 20, 2023, 01:31:16 PMYou should be taking into account the resolution units when interpreting the resolution values.  They may be inches or cm (or "none", whatever that means).

- Phil

why? i do not need to calculate with this number. The resolution is stored as a hex number: e.g. 60 (6*16 +0 = 96). Php is programmed to unpack these numbers correctly. I have no use for this value when extracting the resolution value stored in the image.

Can you explain how you are using this value to calculate the resolution? i'm curious because the hex value will yield the correct decimal. In the case of 44 (2c), the value needs to be unpacked correctly using 2c 01 to yield 300. All of my images match the data that i have extracted. I see no errors. I have tested hundreds of different files in different formats. The resolution is printing correctly.

On the other hand, your windows executable exif tool is showing an incorrect date when i drag and drop the polaroid photo. I see 2026 instead of 2023. sometimes in both places, sometimes in one place.

Phil Harvey

A value of 96 may be either 96 pixels per inch, or 96 pixels per centimetre.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Blaumeise00

Hi Mr. Harvey,

i see what you mean about the unit. I need to read the entire address and not four bytes. I already have the unit extracted. I did that earlier today. I will have to adjust my code to detect the unit then collect the correct information. I made a new jpeg in Photoshop elements with 300dpi setting then i changed the unit to cm. I now see about 8bytes of numbers. I will have to figure out what to do with these numbers. I also noticed that Windows shows 300dpi and unit 3 for my photo which is silly. dpi with a cm unit? your exif tool shows the correct format 1/2.54 x 300. Very nice work, Mr. Harvey.

I am a bit frustrated with how much coding is required just to extract a few bits of info from a photo. You must remember that php is a server side scripting language, so i have to read a jpeg very quickly. I have o time to read and process exif data. I am only targeting certain info: exif header, byte order, exif version, resolution, resolution unit, image width and height, bit depth, date modified, thumbnail count, comments. I scan the image for stenography and code injection, so why not grab this data while i am reading the image (rhetorical question.)

I am an amateur coder so it is quite difficult for me to know how to locate and extract the data. I so far have exif header, byte order, orientation, resolution unit and i am working on resolution. I found the date marker and i can find the address but i have to learn how to extract and display the date. I also need to handle this cm units resolution. what a project! i am a bit tired from reading exif data and i struggle to find useful info online. Thank you for this forum. I appreciate all of the help and tips.

Meantime, your tool is quite nice. i have used it a few times already. I see the cm data in an htmldump of the image.

i will read more about this subject tommorrow.

Blaumeise00

Dear Mr. Harvey,

the htmldump of your exif tool helped me locate an error in my code! i was counting the offset from 1 and not zero, which placed the jump to the wrong line position. I have adjusted my code and i am now properly reading both horizontal and vertical resolutions. Thank you for the tip and the great tool!

i have also added the date and formatted the date. I've grabbed the exif version also today.

I really appreciate this forum and its members. Thank you for all of the help and tips :-)