Skip to content

Commit

Permalink
Add support for GPI_RGB with GCI_PaletteIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
yeesian committed Jun 20, 2021
1 parent fa7f005 commit 317272f
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 172 deletions.
42 changes: 42 additions & 0 deletions src/raster/colortable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,45 @@ palette interpretation enumeration value, usually `GPI_RGB`.
"""
paletteinterp(ct::ColorTable)::GDALPaletteInterp =
GDAL.gdalgetpaletteinterpretation(ct.ptr)

"""
getcolorentryasrgb(ct::ColorTable, i::Integer)
Fetch a table entry in RGB format.
In theory this method should support translation of color palettes in non-RGB
color spaces into RGB on the fly, but currently it only works on RGB color
tables.
### Parameters
* `i` entry offset from zero to GetColorEntryCount()-1.
### Returns
`true` on success, or `false` if the conversion isn't supported.
"""
function getcolorentryasrgb(ct::ColorTable, i::Integer)::GDAL.GDALColorEntry
colorentry = Ref{GDAL.GDALColorEntry}(GDAL.GDALColorEntry(0, 0, 0, 0))
result = Bool(GDAL.gdalgetcolorentryasrgb(ct.ptr, i, colorentry))
result || @warn("The conversion to RGB isn't supported.")
return colorentry[]
end

"""
setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry)
Set entry in color table.
Note that the passed in color entry is copied, and no internal reference to it
is maintained. Also, the passed in entry must match the color interpretation of
the table to which it is being assigned.
The table is grown as needed to hold the supplied offset.
### Parameters
* `i` entry offset from `0` to `ncolorentry()-1`.
* `entry` value to assign to table.
"""
function setcolorentry!(ct::ColorTable, i::Integer, entry::GDAL.GDALColorEntry)
GDAL.gdalsetcolorentry(ct.ptr, i, Ref{GDAL.GDALColorEntry}(entry))
return ct
end
269 changes: 101 additions & 168 deletions src/raster/images.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ function imview(colortype::Type{<:ColorTypes.Colorant}, imgvalues...)
)
end

function imview(gci::GDALColorInterp, imgvalues::AbstractMatrix)
function imview(
gci::GDALColorInterp,
imgvalues::AbstractMatrix;
colortable::ColorTable = ColorTable(C_NULL),
)
return if gci == GCI_GrayIndex
imview(ColorTypes.Gray, imgvalues)
elseif gci == GCI_Undefined
Expand All @@ -22,26 +26,59 @@ function imview(gci::GDALColorInterp, imgvalues::AbstractMatrix)
elseif gci == GCI_BlueBand
zerovalues = zeros(eltype(imgvalues), size(imgvalues))
imview(GPI_RGB, zerovalues, zerovalues, imgvalues)
elseif gci == GCI_PaletteIndex
if colortable.ptr == C_NULL
error(
"""
`imview` is only supported for `GCI_PaletteIndex` with non-null
colortables.
""",
)
end
gpi = paletteinterp(colortable)
if gpi == GPI_Gray
imview(GPI_Gray, imgvalues)
elseif gpi == GPI_RGB
colorentries = GDAL.GDALColorEntry[
getcolorentryasrgb(colortable, i - 1) for
i in 1:GDAL.gdalgetcolorentrycount(colortable.ptr)
]
c1 = Matrix{UInt8}(undef, size(imgvalues)...)
c2 = Matrix{UInt8}(undef, size(imgvalues)...)
c3 = Matrix{UInt8}(undef, size(imgvalues)...)
c4 = Matrix{UInt8}(undef, size(imgvalues)...)
for i in eachindex(imgvalues)
c1[i] = UInt8(colorentries[imgvalues[i]+1].c1)
c2[i] = UInt8(colorentries[imgvalues[i]+1].c2)
c3[i] = UInt8(colorentries[imgvalues[i]+1].c3)
c4[i] = UInt8(colorentries[imgvalues[i]+1].c4)
end
imview(GPI_RGB, c1, c2, c3, c4)
else
error("""
Unsupported GPI: $(paletteinterp(colortable)). Please file an
issue at https://github.com/yeesian/ArchGDAL.jl/issues if it
should be supported.
""")
end
else
error(
"""
Unknown GCI: $gci. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported.
""",
)
error("""
Unknown GCI: $gci. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be
supported.
""")
end
end

function imview(gpi::GDALPaletteInterp, imgvalues::AbstractMatrix)
return if gpi == GPI_Gray
imview(ColorTypes.Gray, imgvalues)
else
error(
"""
Unsupported GPI: $gpi. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported.
""",
)
error("""
Unsupported GPI: $gpi. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be
supported.
""")
end
end

Expand All @@ -56,12 +93,11 @@ function imview(
elseif gpi == GPI_RGB
imview(ColorTypes.RGB, c1, c2, c3)
else
error(
"""
Unsupported GPI: $gpi. If it should be supported, please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues with the desired output.
""",
)
error("""
Unsupported GPI: $gpi. If it should be supported, please file an
issue at https://github.com/yeesian/ArchGDAL.jl/issues with the
desired output.
""")
end
end

Expand All @@ -77,182 +113,79 @@ function imview(
elseif gpi == GPI_RGB
imview(ColorTypes.RGBA, c1, c2, c3, c4)
else
error(
"""
Unsupported GPI: $gpi. If it should be supported, please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues with the desired output.
""",
)
error("""
Unsupported GPI: $gpi. If it should be supported, please file an
issue at https://github.com/yeesian/ArchGDAL.jl/issues with the
desired output.
""")
end
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
rb::AbstractRasterBand,
xoffset::Integer,
yoffset::Integer,
xsize::Integer,
ysize::Integer,
)
return imview(colortype, read(rb, xoffset, yoffset, xsize, ysize))
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
dataset::AbstractDataset,
i::Integer,
xoffset::Integer,
yoffset::Integer,
xsize::Integer,
ysize::Integer,
args...,
)
return imread(
colortype,
getband(dataset, i),
xoffset,
yoffset,
xsize,
ysize,
)
return imread(colortype, getband(dataset, i), args...)
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
rb::AbstractRasterBand,
rows::UnitRange{<:Integer},
cols::UnitRange{<:Integer},
)
return imview(colortype, read(rb, rows, cols))
function imread(gpi::GDALPaletteInterp, rb::AbstractRasterBand, args...)
return imview(gpi, read(rb, args...))
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
dataset::AbstractDataset,
i::Integer,
rows::UnitRange{<:Integer},
cols::UnitRange{<:Integer},
)
return imread(colortype, getband(dataset, i), rows, cols)
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
rb::AbstractRasterBand,
)
return imview(colortype, read(rb))
end

function imread(
colortype::Union{GDALPaletteInterp,GDALColorInterp},
dataset::AbstractDataset,
i::Integer,
)
return imread(colortype, getband(dataset, i))
end

function imread(
rb::AbstractRasterBand,
xoffset::Integer,
yoffset::Integer,
xsize::Integer,
ysize::Integer,
)
return imview(getcolorinterp(rb), read(rb, xoffset, yoffset, xsize, ysize))
end

function imread(
dataset::AbstractDataset,
i::Integer,
xoffset::Integer,
yoffset::Integer,
xsize::Integer,
ysize::Integer,
)
return imread(getband(dataset, i), xoffset, yoffset, xsize, ysize)
end

function imread(
rb::AbstractRasterBand,
rows::UnitRange{<:Integer},
cols::UnitRange{<:Integer},
)
return imview(getcolorinterp(rb), read(rb, rows, cols))
end

function imread(
dataset::AbstractDataset,
i::Integer,
rows::UnitRange{<:Integer},
cols::UnitRange{<:Integer},
)
return imread(getband(dataset, i), rows, cols)
function imread(gci::GDALColorInterp, rb::AbstractRasterBand, args...)
return getcolortable(rb) do colortable
return imview(gci, read(rb, args...), colortable = colortable)
end
end

function imread(rb::AbstractRasterBand)
return imview(getcolorinterp(rb), read(rb))
function imread(rb::AbstractRasterBand, args...)
return getcolortable(rb) do colortable
imview(getcolorinterp(rb), read(rb, args...), colortable = colortable)
end
end

function imread(dataset::AbstractDataset, i::Integer)
return imread(getband(dataset, i))
function imread(dataset::AbstractDataset, i::Integer, args...)
return imread(getband(dataset, i), args...)
end

function _paletteindices(dataset::AbstractDataset, indices)
function _colorindices(dataset::AbstractDataset, indices)
gci = unique(
GDALColorInterp[getcolorinterp(getband(dataset, i)) for i in indices],
)
gciorder = sort(gci)
return if gciorder == [GCI_GrayIndex]
GPI_Gray, Tuple(indices[sortperm(gci)])
colortype = if gciorder == [GCI_GrayIndex]
GCI_GrayIndex
elseif gciorder == [GCI_PaletteIndex]
gpi = getcolortable(getband(dataset, indices[1])) do ct
return paletteinterp(ct)
end
gpi, Tuple(indices)
GCI_PaletteIndex
elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand]
GPI_RGB, Tuple(indices[sortperm(gci)])
GPI_RGB
elseif gciorder == [GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand]
GPI_RGB, Tuple(indices[sortperm(gci)])
GPI_RGB
else
error(
"""
Unknown GCI: $gciorder. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be supported.
""",
)
error("""
Unknown GCI: $gciorder. Please file an issue at
https://github.com/yeesian/ArchGDAL.jl/issues if it should be
supported.
""")
end
return colortype, Tuple(indices[sortperm(gci)])
end

function imread(dataset::AbstractDataset, indices, args...)
colortype, idxs = _colorindices(dataset, indices)
return if colortype == GCI_PaletteIndex
getcolortable(getband(dataset, 1)) do colortable
return imview(
colortype,
(read(getband(dataset, i), args...) for i in idxs)...,
colortable = colortable,
)
end
else
imview(colortype, (read(getband(dataset, i), args...) for i in idxs)...)
end
end

function imread(
dataset::AbstractDataset,
indices,
xoffset::Integer,
yoffset::Integer,
xsize::Integer,
ysize::Integer,
)
gpi, idxs = _paletteindices(dataset, indices)
return imview(
gpi,
(
read(getband(dataset, i), xoffset, yoffset, xsize, ysize) for
i in idxs
)...,
)
end

function imread(
dataset::AbstractDataset,
indices,
rows::UnitRange{<:Integer},
cols::UnitRange{<:Integer},
)
gpi, idxs = _paletteindices(dataset, indices)
return imview(gpi, (read(getband(dataset, i), rows, cols) for i in idxs)...)
end

function imread(dataset::AbstractDataset, indices)
gpi, idxs = _paletteindices(dataset, indices)
return imview(gpi, (read(getband(dataset, i)) for i in idxs)...)
end

imread(dataset::AbstractDataset) = imread(dataset, 1:nraster(dataset))
Expand Down
Loading

0 comments on commit 317272f

Please sign in to comment.