-
Notifications
You must be signed in to change notification settings - Fork 14
/
layout.jl
93 lines (82 loc) · 3.45 KB
/
layout.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
nrows(ifd::IFD) = Int(ifd[IMAGELENGTH].data)::Int
ncols(ifd::IFD) = Int(ifd[IMAGEWIDTH].data)::Int
function nsamples(ifd::IFD)
if SAMPLESPERPIXEL in ifd
Int(ifd[SAMPLESPERPIXEL].data)::Int
else
1
end
end
"""
interpretation(ifd)
For a given IFD, determine the proper colorimetric interpretation of the data.
It returns subtypes of `Colorant` depending on the values of the tiff tags and
whether there are extrasamples it doesn't know how to deal with.
"""
function interpretation(ifd::IFD)
interp = PhotometricInterpretations(ifd[PHOTOMETRIC].data)
extras = EXTRASAMPLE_UNSPECIFIED
if EXTRASAMPLES in ifd
try
extras = ExtraSamples(ifd[EXTRASAMPLES].data)
catch
extras = EXTRASAMPLE_ASSOCALPHA
end
end
interpretation(interp, extras, nsamples(ifd))
end
# dummy color type for palette colored images to dispatch on
struct Palette{T} <: Colorant{T, 1}
i::T
end
Base.reinterpret(::Type{Palette{T}}, arr::A) where {T, N, S, A <: AbstractArray{S, N}} = arr
interpretation(p::PhotometricInterpretations) = interpretation(Val(p))
interpretation(::Val{PHOTOMETRIC_RGB}) = RGB
interpretation(::Val{PHOTOMETRIC_MINISBLACK}) = Gray
interpretation(::Val{PHOTOMETRIC_PALETTE}) = Palette
interpretation(::Val{PHOTOMETRIC_YCBCR}) = YCbCr
interpretation(::Val{PHOTOMETRIC_CIELAB}) = Lab
function interpretation(p::PhotometricInterpretations, extrasamples::ExtraSamples, samplesperpixel::Int)
interp = interpretation(p)::Type{<:Colorant}
len = length(interp)::Int
if len + 1 == samplesperpixel
return interpretation(p, extrasamples, Val(samplesperpixel))
elseif len == samplesperpixel
return interp, false
elseif len < samplesperpixel
return interp, true
else
error("TIFF file says it contains $interp values, but only has $samplesperpixel samples per pixel instead of the minimum required $len")
end
end
_pad(::Type{RGB}) = RGBX
_pad(::Type{T}) where {T} = T
interpretation(p::PhotometricInterpretations, extrasamples::ExtraSamples, nsamples::Val) = interpretation(p, Val(extrasamples), nsamples)
interpretation(p::PhotometricInterpretations, ::Val{EXTRASAMPLE_UNSPECIFIED}, @nospecialize(::Val)) = interpretation(p), true
interpretation(p::PhotometricInterpretations, ::Val{EXTRASAMPLE_UNSPECIFIED}, ::Val{4}) = _pad(interpretation(p)), false
interpretation(p::PhotometricInterpretations, ::Val{EXTRASAMPLE_ASSOCALPHA}, @nospecialize(::Val)) = coloralpha(interpretation(p)), false
interpretation(p::PhotometricInterpretations, ::Val{EXTRASAMPLE_UNASSALPHA}, nsamples::Val) = interpretation(p, Val(EXTRASAMPLE_ASSOCALPHA), nsamples)
_mappedtype(::Type{T}) where {T} = T
_mappedtype(::Type{T}) where {T <: Unsigned} = Normed{T, sizeof(T) * 8}
_mappedtype(::Type{T}) where {T <: Signed} = Fixed{T, sizeof(T) * 8 - 1}
function rawtype(ifd::IFD)
samplesperpixel = nsamples(ifd)
bitsperpixel = ifd[BITSPERSAMPLE].data
sampleformats = fill(UInt16(0x01), samplesperpixel)
if SAMPLEFORMAT in ifd
sampleformats = ifd[SAMPLEFORMAT].data
end
rawtype_mapping[SampleFormats(first(sampleformats)), first(bitsperpixel)]
end
"""
$(SIGNATURES)
Allocate a cache for this IFD with correct type and size.
"""
function getcache(ifd::IFD)
T = rawtype(ifd)
if T === Bool
return BitArray(undef, ncols(ifd), nrows(ifd))
end
colortype, extras = interpretation(ifd)
return Array{colortype{_mappedtype(T)}}(undef, ncols(ifd), nrows(ifd))
end