diff --git a/src/GeoTIFF.jl b/src/GeoTIFF.jl index d4b85bb..b045c75 100644 --- a/src/GeoTIFF.jl +++ b/src/GeoTIFF.jl @@ -4,7 +4,7 @@ module GeoTIFF -using TiffImages: AbstractTIFF, DenseTaggedImage, WidePixel +using TiffImages: AbstractTIFF, DenseTaggedImage, StridedTaggedImage, IFD, WidePixel using ColorTypes: Colorant, Gray using MappedArrays: mappedarray using StaticArrays: SVector, SMatrix, SA diff --git a/src/image.jl b/src/image.jl index 28a32e9..943e3a1 100644 --- a/src/image.jl +++ b/src/image.jl @@ -15,7 +15,7 @@ to get the metadata and the image with corrected axes, respectively. * The [`GeoTIFF.image`](@ref) function is necessary because the GeoTIFF format swaps the order of the image axes; """ -struct GeoTIFFImage{T,N,I<:AbstractTIFF{T,N}} <: AbstractArray{T,N} +struct GeoTIFFImage{T,I<:AbstractMatrix{T}} <: AbstractMatrix{T} tiff::I metadata::Metadata end @@ -59,4 +59,36 @@ channel(geotiff::GeoTIFFImage, i) = mappedarray(c -> channel(c, i), image(geotif Base.size(geotiff::GeoTIFFImage) = size(geotiff.tiff) Base.getindex(geotiff::GeoTIFFImage, i...) = getindex(geotiff.tiff, i...) Base.setindex!(geotiff::GeoTIFFImage, v, i...) = setindex!(geotiff.tiff, v, i...) -Base.IndexStyle(::Type{GeoTIFFImage{T,N,I}}) where {T,N,I} = IndexStyle(I) +Base.IndexStyle(::Type{GeoTIFFImage{T,I}}) where {T,I} = IndexStyle(I) + +abstract type MultiGeoTIFF end + +function getgeotiff end + +function ngeotiffs end + +# Iterator interface +Base.length(geotiff::MultiGeoTIFF) = ngeotiffs(geotiff) +Base.iterate(geotiff::MultiGeoTIFF, state=1) = + state > length(geotiff) ? nothing : (getgeotiff(geotiff, state), state + 1) + +# Indexing interface +Base.getindex(geotiff::MultiGeoTIFF, i) = getgeotiff(geotiff, i) +Base.firstindex(geotiff::MultiGeoTIFF) = 1 +Base.lastindex(geotiff::MultiGeoTIFF) = ngeotiffs(geotiff) + +struct StridedGeoTIFF{I<:StridedTaggedImage} <: MultiGeoTIFF + tiff::I + metadata::Vector{Metadata} +end + +ngeotiffs(geotiff::StridedGeoTIFF) = length(geotiff.tiff) +getgeotiff(geotiff::StridedGeoTIFF, i) = GeoTIFFImage(geotiff.tiff[i], geotiff.metadata[i]) + +struct SlicedGeoTIFF{T,I<:AbstractTIFF{T,3}} <: MultiGeoTIFF + tiff::I + metadata::Vector{Metadata} +end + +ngeotiffs(geotiff::SlicedGeoTIFF) = size(geotiff.tiff, 3) +getgeotiff(geotiff::SlicedGeoTIFF, i) = GeoTIFFImage(@view(geotiff.tiff[:, :, i]), geotiff.metadata[i]) diff --git a/src/load.jl b/src/load.jl index 713fe53..0c26e3e 100644 --- a/src/load.jl +++ b/src/load.jl @@ -16,16 +16,22 @@ The keyword arguments are forward to the `TiffImages.load` function. """ function load(fname; kwargs...) tiff = TiffImages.load(fname; kwargs...) - metadata = _getmetadata(tiff) - GeoTIFFImage(tiff, metadata) + ifds = TiffImages.ifds(tiff) + metadata = ifds isa IFD ? _getmetadata(ifds) : _getmetadata.(ifds) + if tiff isa StridedTaggedImage + StridedGeoTIFF(tiff, metadata) + elseif ndims(tiff) == 3 + SlicedGeoTIFF(tiff, metadata) + else + GeoTIFFImage(tiff, metadata) + end end # ----------------- # HELPER FUNCTIONS # ----------------- -function _getmetadata(tiff) - ifd = TiffImages.ifds(tiff) +function _getmetadata(ifd) geokeydirectory = _gettag(ifd, GeoKeyDirectoryTag, GeoKeyDirectory) geodoubleparams = _gettag(ifd, GeoDoubleParamsTag, GeoDoubleParams) geoasciiparams = _gettag(ifd, GeoAsciiParamsTag, GeoAsciiParams)