Skip to content

Instantly share code, notes, and snippets.

@jkrumbiegel
Created November 21, 2023 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkrumbiegel/2b1bf65bacd7185d36c11b9ecf9d00e2 to your computer and use it in GitHub Desktop.
Save jkrumbiegel/2b1bf65bacd7185d36c11b9ecf9d00e2 to your computer and use it in GitHub Desktop.
Julia detect png dpi
function detect_png_dpi(io::IO)
# PNG header signature
png_signature = UInt8['\u89', 'P', 'N', 'G', '\r', '\n', '\u1a', '\n']
# Reset the IO position to the beginning
seekstart(io)
# Check if the PNG signature is present
if [read(io, UInt8) for _ in 1:length(png_signature)] != png_signature
error("Not a png file")
end
# Function to read a 4-byte chunk length
function read_chunk_length()
return ntoh(read(io, UInt32))
end
# Function to read a 4-byte chunk type
function read_chunk_type()
return [read(io, UInt8) for _ in 1:4]
end
while true
# Read the chunk length
chunk_length = read_chunk_length()
# Read the chunk type
chunk_type = read_chunk_type()
s = String(chunk_type)
if s == "pHYs"
# Read the horizontal and vertical DPI values
x_px_per_unit = Int(ntoh(read(io, UInt32)))
y_px_per_unit = Int(ntoh(read(io, UInt32)))
in_meters = read(io, Bool)
x_dpi = in_meters ? x_px_per_unit / 100 * 2.54 : x_px_per_unit
y_dpi = in_meters ? y_px_per_unit / 100 * 2.54 : y_px_per_unit
aspect_ratio_only = !in_meters
return (x_dpi, y_dpi, aspect_ratio_only)
elseif s == "IDAT"
return nothing # pHYs always comes before IDAT if it exists
end
# Skip the chunk data and CRC
skip(io, chunk_length)
skip(io, 4)
end
return nothing # No pHYs chunk found
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment