Skip to content

Commit f4697b9

Browse files
author
Grok Compression
committed
JP2Grok: support latest Grok 20.3.2 release
This version has a fast 16 bit pathway for decompression, so we need to be more careful about data type of decompressed image. Also, the unit tests tolerances must be adjusted a bit for tests to continue passing, as 16 bit path is a bit more lossy for lossy images.
1 parent 1d00cc0 commit f4697b9

4 files changed

Lines changed: 99 additions & 7 deletions

File tree

.github/workflows/ubuntu_26.04/Dockerfile.ci

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ RUN curl -LO -fsS https://github.com/apache/arrow/archive/refs/heads/main.zip \
230230
&& rm -rf arrow-main
231231

232232
# Build Grok JPEG 2000 library
233-
ARG GROK_VERSION=v20.2.8
233+
ARG GROK_VERSION=v20.3.2
234234

235235
RUN git clone --recursive --depth 1 --branch ${GROK_VERSION} \
236236
https://github.com/GrokImageCompression/grok.git grok-git && \

autotest/gdrivers/jp2grok.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ def test_jp2grok_10():
277277
gdal.Unlink("/vsimem/jp2grok_10.jp2")
278278

279279
# Quite a bit of difference...
280-
assert maxdiff <= 35, "Image too different from reference"
280+
assert maxdiff <= 38, "Image too different from reference"
281281

282282

283283
###############################################################################
@@ -592,7 +592,7 @@ def test_jp2grok_22():
592592
assert fourth_band.GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == "1"
593593
ds = None
594594
ds = gdal.Open("/vsimem/jp2grok_22.jp2")
595-
assert ds.GetRasterBand(4).Checksum() == 22499
595+
assert ds.GetRasterBand(4).Checksum() == 26477
596596
ds = None
597597
gdal.Unlink("/vsimem/jp2grok_22.jp2")
598598

@@ -721,7 +721,7 @@ def test_jp2grok_24():
721721
ds = None
722722
ds = gdal.Open("/vsimem/jp2grok_24.jp2")
723723
assert ds.GetRasterBand(2).GetMetadataItem("NBITS", "IMAGE_STRUCTURE") is None
724-
assert ds.GetRasterBand(2).Checksum() == 22499
724+
assert ds.GetRasterBand(2).Checksum() == 27389
725725
ds = None
726726
gdal.Unlink("/vsimem/jp2grok_24.jp2")
727727

cmake/helpers/CheckDependentLibrariesGrok.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ gdal_check_package(Grok "Enable JPEG2000 support with Grok library"
22
CONFIG
33
CAN_DISABLE
44
TARGETS GROK::grokj2k
5-
VERSION 20.2.8)
5+
VERSION 20.3.2)

frmts/grok/grkdatasetbase.h

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,9 @@ struct GRKCodecWrapper
476476
*/
477477
void allocComponentParams(int nBands)
478478
{
479+
// need to zero-init the component structs
479480
pasBandParams = static_cast<grk_image_comp *>(
480-
CPLMalloc(nBands * sizeof(grk_image_comp)));
481+
CPLCalloc(nBands, sizeof(grk_image_comp)));
481482
}
482483

483484
/**
@@ -2131,6 +2132,91 @@ struct JP2GRKDatasetBase : public JP2DatasetBase
21312132
if (xStart >= xEnd || yStart >= yEnd)
21322133
return CE_None;
21332134

2135+
// can use fast path when there is no sub-sampling, no alpha promotion
2136+
// and output pixels are contiguous
2137+
const int elemSize = GDALGetDataTypeSizeBytes(eBufType);
2138+
bool canFastCopy = (nPromoteAlphaBandIdx < 0 &&
2139+
nPixelSpace == elemSize && elemSize > 0);
2140+
for (int i = 0; i < nBandCount && canFastCopy; ++i)
2141+
{
2142+
const int b = panBandMap[i] - 1;
2143+
if (b < 0 || b >= img->numcomps)
2144+
canFastCopy = false;
2145+
else
2146+
{
2147+
const auto &comp = img->comps[b];
2148+
if (comp.dx != 1 || comp.dy != 1 || !comp.data)
2149+
canFastCopy = false;
2150+
}
2151+
}
2152+
2153+
if (canFastCopy)
2154+
{
2155+
const int copyWidth = xEnd - xStart;
2156+
for (int i = 0; i < nBandCount; ++i)
2157+
{
2158+
const int srcBandIdx = panBandMap[i] - 1;
2159+
const auto &comp = img->comps[srcBandIdx];
2160+
const int srcXStart = xStart - tileXOff;
2161+
2162+
for (int iY = yStart; iY < yEnd; ++iY)
2163+
{
2164+
const int srcRow = iY - tileYOff;
2165+
const int dstRow = iY - nYOff;
2166+
const int dstX = xStart - nXOff;
2167+
auto dst = static_cast<uint8_t *>(pData) +
2168+
dstRow * nLineSpace + dstX * nPixelSpace +
2169+
i * nBandSpace;
2170+
2171+
if (comp.data_type == GRK_INT_16)
2172+
{
2173+
const auto src =
2174+
static_cast<int16_t *>(comp.data) +
2175+
srcRow * static_cast<int>(comp.stride) + srcXStart;
2176+
if (eBufType == GDT_UInt16 || eBufType == GDT_Int16)
2177+
{
2178+
memcpy(dst, src, copyWidth * sizeof(int16_t));
2179+
}
2180+
else if (eBufType == GDT_Byte)
2181+
{
2182+
for (int x = 0; x < copyWidth; ++x)
2183+
dst[x] = static_cast<GByte>(src[x]);
2184+
}
2185+
else if (eBufType == GDT_Int32 ||
2186+
eBufType == GDT_UInt32)
2187+
{
2188+
auto dst32 = reinterpret_cast<int32_t *>(dst);
2189+
for (int x = 0; x < copyWidth; ++x)
2190+
dst32[x] = src[x];
2191+
}
2192+
}
2193+
else
2194+
{
2195+
const auto src =
2196+
static_cast<int32_t *>(comp.data) +
2197+
srcRow * static_cast<int>(comp.stride) + srcXStart;
2198+
if (eBufType == GDT_Int32 || eBufType == GDT_UInt32)
2199+
{
2200+
memcpy(dst, src, copyWidth * sizeof(int32_t));
2201+
}
2202+
else if (eBufType == GDT_UInt16 ||
2203+
eBufType == GDT_Int16)
2204+
{
2205+
auto dst16 = reinterpret_cast<int16_t *>(dst);
2206+
for (int x = 0; x < copyWidth; ++x)
2207+
dst16[x] = static_cast<int16_t>(src[x]);
2208+
}
2209+
else if (eBufType == GDT_Byte)
2210+
{
2211+
for (int x = 0; x < copyWidth; ++x)
2212+
dst[x] = static_cast<GByte>(src[x]);
2213+
}
2214+
}
2215+
}
2216+
}
2217+
return CE_None;
2218+
}
2219+
21342220
// Scalar per-pixel loop that handles dx/dy subsampling, alpha promotion,
21352221
// and all five output types.
21362222
CPLErr eErr = CE_None;
@@ -2165,7 +2251,13 @@ struct JP2GRKDatasetBase : public JP2DatasetBase
21652251
const GPtrDiff_t dstOffset =
21662252
bufX * nPixelSpace + bufY * nLineSpace + i * nBandSpace;
21672253

2168-
int32_t value = static_cast<int32_t *>(comp.data)[tileIdx];
2254+
// Grok v20.3.x can use 16 bit storage for images with
2255+
// precision ≤ 12 bits - we need to cast to correct type
2256+
int32_t value;
2257+
if (comp.data_type == GRK_INT_16)
2258+
value = static_cast<int16_t *>(comp.data)[tileIdx];
2259+
else
2260+
value = static_cast<int32_t *>(comp.data)[tileIdx];
21692261
if (srcBandIdx == nPromoteAlphaBandIdx)
21702262
value *= 255;
21712263
if (eBufType == GDT_Byte)

0 commit comments

Comments
 (0)