Skip to content

Commit ef9b05e

Browse files
committed
MEM: improve RasterIO() performance in some cases
1 parent fa69f60 commit ef9b05e

File tree

1 file changed

+80
-51
lines changed

1 file changed

+80
-51
lines changed

frmts/mem/memdataset.cpp

Lines changed: 80 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -224,28 +224,40 @@ CPLErr MEMRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
224224
{
225225
for (int iLine = 0; iLine < nYSize; iLine++)
226226
{
227-
GDALCopyWords(pabyData +
228-
nLineOffset *
229-
static_cast<GPtrDiff_t>(iLine + nYOff) +
230-
nXOff * nPixelOffset,
231-
eDataType, static_cast<int>(nPixelOffset),
232-
static_cast<GByte *>(pData) +
233-
nLineSpaceBuf * static_cast<GPtrDiff_t>(iLine),
234-
eBufType, static_cast<int>(nPixelSpaceBuf), nXSize);
227+
GDALCopyWords64(pabyData +
228+
nLineOffset *
229+
static_cast<GPtrDiff_t>(iLine + nYOff) +
230+
nXOff * nPixelOffset,
231+
eDataType, static_cast<int>(nPixelOffset),
232+
static_cast<GByte *>(pData) +
233+
nLineSpaceBuf * static_cast<GPtrDiff_t>(iLine),
234+
eBufType, static_cast<int>(nPixelSpaceBuf), nXSize);
235235
}
236236
}
237237
else
238238
{
239-
for (int iLine = 0; iLine < nYSize; iLine++)
239+
if (nXSize == nRasterXSize && nPixelSpaceBuf == nPixelOffset &&
240+
nLineSpaceBuf == nLineOffset)
241+
{
242+
GDALCopyWords64(pData, eBufType, static_cast<int>(nPixelSpaceBuf),
243+
pabyData +
244+
nLineOffset * static_cast<GPtrDiff_t>(nYOff),
245+
eDataType, static_cast<int>(nPixelOffset),
246+
static_cast<GPtrDiff_t>(nXSize) * nYSize);
247+
}
248+
else
240249
{
241-
GDALCopyWords(static_cast<GByte *>(pData) +
242-
nLineSpaceBuf * static_cast<GPtrDiff_t>(iLine),
243-
eBufType, static_cast<int>(nPixelSpaceBuf),
244-
pabyData +
245-
nLineOffset *
246-
static_cast<GPtrDiff_t>(iLine + nYOff) +
247-
nXOff * nPixelOffset,
248-
eDataType, static_cast<int>(nPixelOffset), nXSize);
250+
for (int iLine = 0; iLine < nYSize; iLine++)
251+
{
252+
GDALCopyWords64(
253+
static_cast<GByte *>(pData) +
254+
nLineSpaceBuf * static_cast<GPtrDiff_t>(iLine),
255+
eBufType, static_cast<int>(nPixelSpaceBuf),
256+
pabyData +
257+
nLineOffset * static_cast<GPtrDiff_t>(iLine + nYOff) +
258+
nXOff * nPixelOffset,
259+
eDataType, static_cast<int>(nPixelOffset), nXSize);
260+
}
249261
}
250262
}
251263
return CE_None;
@@ -265,46 +277,46 @@ CPLErr MEMDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
265277
{
266278
const int eBufTypeSize = GDALGetDataTypeSizeBytes(eBufType);
267279

268-
// Detect if we have a pixel-interleaved buffer
269-
if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount == nBands &&
270-
nBands > 1 && nBandSpaceBuf == eBufTypeSize &&
271-
nPixelSpaceBuf == nBandSpaceBuf * nBands)
280+
const auto IsPixelInterleaveDataset = [this, nBandCount, panBandMap]()
272281
{
273-
const auto IsPixelInterleaveDataset = [this, nBandCount, panBandMap]()
282+
GDALDataType eDT = GDT_Unknown;
283+
GByte *pabyData = nullptr;
284+
GSpacing nPixelOffset = 0;
285+
GSpacing nLineOffset = 0;
286+
int eDTSize = 0;
287+
for (int iBandIndex = 0; iBandIndex < nBandCount; iBandIndex++)
274288
{
275-
GDALDataType eDT = GDT_Unknown;
276-
GByte *pabyData = nullptr;
277-
GSpacing nPixelOffset = 0;
278-
GSpacing nLineOffset = 0;
279-
int eDTSize = 0;
280-
for (int iBandIndex = 0; iBandIndex < nBandCount; iBandIndex++)
281-
{
282-
if (panBandMap[iBandIndex] != iBandIndex + 1)
283-
return false;
289+
if (panBandMap[iBandIndex] != iBandIndex + 1)
290+
return false;
284291

285-
MEMRasterBand *poBand = cpl::down_cast<MEMRasterBand *>(
286-
GetRasterBand(iBandIndex + 1));
287-
if (iBandIndex == 0)
288-
{
289-
eDT = poBand->GetRasterDataType();
290-
pabyData = poBand->pabyData;
291-
nPixelOffset = poBand->nPixelOffset;
292-
nLineOffset = poBand->nLineOffset;
293-
eDTSize = GDALGetDataTypeSizeBytes(eDT);
294-
if (nPixelOffset != static_cast<GSpacing>(nBands) * eDTSize)
295-
return false;
296-
}
297-
else if (poBand->GetRasterDataType() != eDT ||
298-
nPixelOffset != poBand->nPixelOffset ||
299-
nLineOffset != poBand->nLineOffset ||
300-
poBand->pabyData != pabyData + iBandIndex * eDTSize)
301-
{
292+
MEMRasterBand *poBand =
293+
cpl::down_cast<MEMRasterBand *>(GetRasterBand(iBandIndex + 1));
294+
if (iBandIndex == 0)
295+
{
296+
eDT = poBand->GetRasterDataType();
297+
pabyData = poBand->pabyData;
298+
nPixelOffset = poBand->nPixelOffset;
299+
nLineOffset = poBand->nLineOffset;
300+
eDTSize = GDALGetDataTypeSizeBytes(eDT);
301+
if (nPixelOffset != static_cast<GSpacing>(nBands) * eDTSize)
302302
return false;
303-
}
304303
}
305-
return true;
306-
};
304+
else if (poBand->GetRasterDataType() != eDT ||
305+
nPixelOffset != poBand->nPixelOffset ||
306+
nLineOffset != poBand->nLineOffset ||
307+
poBand->pabyData != pabyData + iBandIndex * eDTSize)
308+
{
309+
return false;
310+
}
311+
}
312+
return true;
313+
};
307314

315+
// Detect if we have a pixel-interleaved buffer
316+
if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount == nBands &&
317+
nBands > 1 && nBandSpaceBuf == eBufTypeSize &&
318+
nPixelSpaceBuf == nBandSpaceBuf * nBands)
319+
{
308320
const auto IsBandSeparatedDataset = [this, nBandCount, panBandMap]()
309321
{
310322
GDALDataType eDT = GDT_Unknown;
@@ -425,6 +437,23 @@ CPLErr MEMDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
425437
return CE_None;
426438
}
427439
}
440+
// From a band-interleaved buffer to a pixel-interleave dataset
441+
else if (eRWFlag == GF_Write && nXSize == nBufXSize &&
442+
nYSize == nBufYSize && nXSize == nRasterXSize &&
443+
nBandCount == nBands && nBands > 1 &&
444+
nPixelSpaceBuf == eBufTypeSize &&
445+
nLineSpaceBuf == nPixelSpaceBuf * nBufXSize &&
446+
nBandSpaceBuf == nLineSpaceBuf * nBufYSize &&
447+
IsPixelInterleaveDataset())
448+
{
449+
FlushCache(false);
450+
451+
auto poDstBand = cpl::down_cast<MEMRasterBand *>(papoBands[0]);
452+
GDALTranspose2D(pData, eBufType, poDstBand->pabyData,
453+
poDstBand->GetRasterDataType(),
454+
static_cast<size_t>(nXSize) * nYSize, nBands);
455+
return CE_None;
456+
}
428457

429458
if (nBufXSize != nXSize || nBufYSize != nYSize)
430459
return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,

0 commit comments

Comments
 (0)