@@ -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