280
280
281
281
# ## Write ##########################################################################################
282
282
283
+ _dpi_to_ppm (:: Nothing ) = nothing
284
+ function _dpi_to_ppm (dpi:: Real )
285
+ @assert dpi > 0
286
+ pixels_per_meter = round (UInt32, dpi / 0.0254 )
287
+ return (pixels_per_meter, pixels_per_meter)
288
+ end
289
+ function _dpi_to_ppm (dpi:: Tuple{<:Real,<:Real} )
290
+ @assert dpi[1 ] > 0
291
+ @assert dpi[2 ] > 0
292
+ return round .(UInt32, dpi ./ 0.0254 )
293
+ end
294
+
283
295
const SupportedPaletteColor = Union{
284
296
AbstractRGB{<: Union{N0f8,AbstractFloat} },
285
297
TransparentRGB{T,<: Union{N0f8,AbstractFloat} } where T,
@@ -328,6 +340,9 @@ Write out a julia `Array` as a PNG image.
328
340
- `background`: optional background color to be stored in the `bKGD` chunk. Only meaningful for transparent images.
329
341
Valid values are `nothing` for no background, `UInt8` as a palette index for palleted images,
330
342
`Gray` for grayscale images and `RGB` for true color images.
343
+ - `dpi`: stores the pixel density given in dots per inch into the `pHYs` chunk as pixels per meter.
344
+ The density is given as `dpi` for ease of use as pixels per meter is an uncommon format. If set to `nothing`,
345
+ no pixel density is written. If set to a 2-element tuple, a different density is written for x and y, respectively.
331
346
332
347
# Returns
333
348
- `nothing`
@@ -340,6 +355,7 @@ function save(
340
355
filters:: Integer = Int (PNG_FILTER_PAETH),
341
356
file_gamma:: Union{Nothing,Float64} = nothing ,
342
357
background:: Union{Nothing,UInt8,AbstractGray,AbstractRGB} = nothing ,
358
+ dpi:: Union{Nothing,Real,Tuple{<:Real,<:Real}} = nothing ,
343
359
) where {
344
360
T,
345
361
S<: Union{AbstractMatrix{T},AbstractArray{T,3}}
@@ -363,7 +379,8 @@ function save(
363
379
compression_strategy= compression_strategy,
364
380
filters= filters,
365
381
file_gamma= file_gamma,
366
- background= background
382
+ background= background,
383
+ pixels_per_meter = _dpi_to_ppm (dpi),
367
384
)
368
385
369
386
close_png (fp)
@@ -377,6 +394,7 @@ function save(
377
394
filters:: Integer = Int (PNG_FILTER_PAETH),
378
395
file_gamma:: Union{Nothing,Float64} = nothing ,
379
396
background:: Union{Nothing,UInt8,AbstractGray,AbstractRGB} = nothing ,
397
+ dpi:: Union{Nothing,Real,Tuple{<:Real,<:Real}} = nothing ,
380
398
) where {
381
399
S<: Union{AbstractMatrix,AbstractArray{<:Any,3}}
382
400
}
@@ -399,6 +417,7 @@ function save(
399
417
filters= filters,
400
418
file_gamma= file_gamma,
401
419
background= background,
420
+ pixels_per_meter = _dpi_to_ppm (dpi),
402
421
)
403
422
end
404
423
end
@@ -411,6 +430,7 @@ function _save(png_ptr, info_ptr, image::S;
411
430
filters:: Integer = Int (PNG_FILTER_PAETH),
412
431
file_gamma:: Union{Nothing,Float64} = nothing ,
413
432
background:: Union{Nothing,UInt8,AbstractGray,AbstractRGB} = nothing ,
433
+ pixels_per_meter:: Union{Nothing,Tuple{UInt32,UInt32}} = nothing ,
414
434
) where {
415
435
T,
416
436
S<: Union{AbstractMatrix{T},AbstractArray{T,3}}
@@ -426,6 +446,9 @@ function _save(png_ptr, info_ptr, image::S;
426
446
png_set_compression_level (png_ptr, compression_level)
427
447
png_set_compression_strategy (png_ptr, compression_strategy)
428
448
png_set_compression_window_bits (png_ptr, min (15 , max (8 , _nextpow2exp (approx_bytes))))
449
+ if pixels_per_meter != = nothing
450
+ png_set_pHYs (png_ptr, info_ptr, pixels_per_meter... , PNG_RESOLUTION_METER)
451
+ end
429
452
430
453
if color_type == PNG_COLOR_TYPE_PALETTE
431
454
# TODO : 1, 2, 4 bit-depth indices for palleted
0 commit comments