1 : /******************************************************************************
2 : * $Id: memdataset.cpp 24378 2012-05-03 21:01:27Z rouault $
3 : *
4 : * Project: Memory Array Translator
5 : * Purpose: Complete implementation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2000, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "memdataset.h"
31 : #include "cpl_string.h"
32 :
33 : CPL_CVSID("$Id: memdataset.cpp 24378 2012-05-03 21:01:27Z rouault $");
34 :
35 : /************************************************************************/
36 : /* MEMCreateRasterBand() */
37 : /************************************************************************/
38 :
39 7 : GDALRasterBandH MEMCreateRasterBand( GDALDataset *poDS, int nBand,
40 : GByte *pabyData, GDALDataType eType,
41 : int nPixelOffset, int nLineOffset,
42 : int bAssumeOwnership )
43 :
44 : {
45 : return (GDALRasterBandH)
46 : new MEMRasterBand( poDS, nBand, pabyData, eType, nPixelOffset,
47 7 : nLineOffset, bAssumeOwnership );
48 : }
49 :
50 : /************************************************************************/
51 : /* MEMRasterBand() */
52 : /************************************************************************/
53 :
54 5519 : MEMRasterBand::MEMRasterBand( GDALDataset *poDS, int nBand,
55 : GByte *pabyDataIn, GDALDataType eTypeIn,
56 : int nPixelOffsetIn, int nLineOffsetIn,
57 5519 : int bAssumeOwnership, const char * pszPixelType)
58 :
59 : {
60 : //CPLDebug( "MEM", "MEMRasterBand(%p)", this );
61 :
62 5519 : this->poDS = poDS;
63 5519 : this->nBand = nBand;
64 :
65 5519 : this->eAccess = poDS->GetAccess();
66 :
67 5519 : eDataType = eTypeIn;
68 :
69 5519 : nBlockXSize = poDS->GetRasterXSize();
70 5519 : nBlockYSize = 1;
71 :
72 5519 : if( nPixelOffsetIn == 0 )
73 5224 : nPixelOffsetIn = GDALGetDataTypeSize(eTypeIn) / 8;
74 :
75 5519 : if( nLineOffsetIn == 0 )
76 5230 : nLineOffsetIn = nPixelOffsetIn * nBlockXSize;
77 :
78 5519 : nPixelOffset = nPixelOffsetIn;
79 5519 : nLineOffset = nLineOffsetIn;
80 5519 : bOwnData = bAssumeOwnership;
81 :
82 5519 : pabyData = pabyDataIn;
83 :
84 5519 : bNoDataSet = FALSE;
85 :
86 5519 : poColorTable = NULL;
87 :
88 5519 : eColorInterp = GCI_Undefined;
89 :
90 5519 : papszCategoryNames = NULL;
91 5519 : dfOffset = 0.0;
92 5519 : dfScale = 1.0;
93 5519 : pszUnitType = NULL;
94 5519 : psSavedHistograms = NULL;
95 :
96 5519 : if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
97 0 : this->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
98 5519 : }
99 :
100 : /************************************************************************/
101 : /* ~MEMRasterBand() */
102 : /************************************************************************/
103 :
104 5519 : MEMRasterBand::~MEMRasterBand()
105 :
106 : {
107 : //CPLDebug( "MEM", "~MEMRasterBand(%p)", this );
108 5519 : if( bOwnData )
109 : {
110 : //CPLDebug( "MEM", "~MEMRasterBand() - free raw data." );
111 5236 : VSIFree( pabyData );
112 : }
113 :
114 5519 : if( poColorTable != NULL )
115 2 : delete poColorTable;
116 :
117 5519 : CPLFree( pszUnitType );
118 5519 : CSLDestroy( papszCategoryNames );
119 :
120 5519 : if (psSavedHistograms != NULL)
121 1 : CPLDestroyXMLNode(psSavedHistograms);
122 5519 : }
123 :
124 :
125 : /************************************************************************/
126 : /* IReadBlock() */
127 : /************************************************************************/
128 :
129 17398 : CPLErr MEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
130 : void * pImage )
131 :
132 : {
133 17398 : int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
134 17398 : CPLAssert( nBlockXOff == 0 );
135 :
136 17398 : if( nPixelOffset == nWordSize )
137 : {
138 : memcpy( pImage,
139 : pabyData + nLineOffset*(size_t)nBlockYOff,
140 17098 : nPixelOffset * nBlockXSize );
141 : }
142 : else
143 : {
144 300 : GByte *pabyCur = pabyData + nLineOffset * (size_t)nBlockYOff;
145 :
146 30300 : for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
147 : {
148 : memcpy( ((GByte *) pImage) + iPixel*nWordSize,
149 : pabyCur + iPixel*nPixelOffset,
150 30000 : nWordSize );
151 : }
152 : }
153 :
154 17398 : return CE_None;
155 : }
156 :
157 : /************************************************************************/
158 : /* IWriteBlock() */
159 : /************************************************************************/
160 :
161 20159 : CPLErr MEMRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
162 : void * pImage )
163 :
164 : {
165 20159 : int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
166 20159 : CPLAssert( nBlockXOff == 0 );
167 :
168 20159 : if( nPixelOffset == nWordSize )
169 : {
170 : memcpy( pabyData+nLineOffset*(size_t)nBlockYOff,
171 : pImage,
172 18859 : nPixelOffset * nBlockXSize );
173 : }
174 : else
175 : {
176 1300 : GByte *pabyCur = pabyData + nLineOffset*(size_t)nBlockYOff;
177 :
178 491300 : for( int iPixel = 0; iPixel < nBlockXSize; iPixel++ )
179 : {
180 : memcpy( pabyCur + iPixel*nPixelOffset,
181 : ((GByte *) pImage) + iPixel*nWordSize,
182 490000 : nWordSize );
183 : }
184 : }
185 :
186 20159 : return CE_None;
187 : }
188 :
189 : /************************************************************************/
190 : /* GetNoDataValue() */
191 : /************************************************************************/
192 280 : double MEMRasterBand::GetNoDataValue( int *pbSuccess )
193 :
194 : {
195 280 : if( pbSuccess )
196 279 : *pbSuccess = bNoDataSet;
197 :
198 280 : if( bNoDataSet )
199 5 : return dfNoData;
200 : else
201 275 : return 0.0;
202 : }
203 :
204 : /************************************************************************/
205 : /* SetNoDataValue() */
206 : /************************************************************************/
207 2 : CPLErr MEMRasterBand::SetNoDataValue( double dfNewValue )
208 : {
209 2 : dfNoData = dfNewValue;
210 2 : bNoDataSet = TRUE;
211 :
212 2 : return CE_None;
213 : }
214 :
215 : /************************************************************************/
216 : /* GetColorInterpretation() */
217 : /************************************************************************/
218 :
219 262 : GDALColorInterp MEMRasterBand::GetColorInterpretation()
220 :
221 : {
222 262 : if( poColorTable != NULL )
223 1 : return GCI_PaletteIndex;
224 : else
225 261 : return eColorInterp;
226 : }
227 :
228 : /************************************************************************/
229 : /* SetColorInterpretation() */
230 : /************************************************************************/
231 :
232 76 : CPLErr MEMRasterBand::SetColorInterpretation( GDALColorInterp eGCI )
233 :
234 : {
235 76 : eColorInterp = eGCI;
236 :
237 76 : return CE_None;
238 : }
239 :
240 : /************************************************************************/
241 : /* GetColorTable() */
242 : /************************************************************************/
243 :
244 191 : GDALColorTable *MEMRasterBand::GetColorTable()
245 :
246 : {
247 191 : return poColorTable;
248 : }
249 :
250 : /************************************************************************/
251 : /* SetColorTable() */
252 : /************************************************************************/
253 :
254 2 : CPLErr MEMRasterBand::SetColorTable( GDALColorTable *poCT )
255 :
256 : {
257 2 : if( poColorTable != NULL )
258 0 : delete poColorTable;
259 :
260 2 : if( poCT == NULL )
261 0 : poColorTable = NULL;
262 : else
263 2 : poColorTable = poCT->Clone();
264 :
265 2 : return CE_None;
266 : }
267 :
268 : /************************************************************************/
269 : /* GetUnitType() */
270 : /************************************************************************/
271 :
272 165 : const char *MEMRasterBand::GetUnitType()
273 :
274 : {
275 165 : if( pszUnitType == NULL )
276 162 : return "";
277 : else
278 3 : return pszUnitType;
279 : }
280 :
281 : /************************************************************************/
282 : /* SetUnitType() */
283 : /************************************************************************/
284 :
285 1 : CPLErr MEMRasterBand::SetUnitType( const char *pszNewValue )
286 :
287 : {
288 1 : CPLFree( pszUnitType );
289 :
290 1 : if( pszNewValue == NULL )
291 0 : pszUnitType = NULL;
292 : else
293 1 : pszUnitType = CPLStrdup(pszNewValue);
294 :
295 1 : return CE_None;
296 : }
297 :
298 : /************************************************************************/
299 : /* GetOffset() */
300 : /************************************************************************/
301 :
302 165 : double MEMRasterBand::GetOffset( int *pbSuccess )
303 :
304 : {
305 165 : if( pbSuccess != NULL )
306 128 : *pbSuccess = TRUE;
307 :
308 165 : return dfOffset;
309 : }
310 :
311 : /************************************************************************/
312 : /* SetOffset() */
313 : /************************************************************************/
314 :
315 1 : CPLErr MEMRasterBand::SetOffset( double dfNewOffset )
316 :
317 : {
318 1 : dfOffset = dfNewOffset;
319 1 : return CE_None;
320 : }
321 :
322 : /************************************************************************/
323 : /* GetScale() */
324 : /************************************************************************/
325 :
326 165 : double MEMRasterBand::GetScale( int *pbSuccess )
327 :
328 : {
329 165 : if( pbSuccess != NULL )
330 128 : *pbSuccess = TRUE;
331 :
332 165 : return dfScale;
333 : }
334 :
335 : /************************************************************************/
336 : /* SetScale() */
337 : /************************************************************************/
338 :
339 1 : CPLErr MEMRasterBand::SetScale( double dfNewScale )
340 :
341 : {
342 1 : dfScale = dfNewScale;
343 1 : return CE_None;
344 : }
345 :
346 : /************************************************************************/
347 : /* GetCategoryNames() */
348 : /************************************************************************/
349 :
350 164 : char **MEMRasterBand::GetCategoryNames()
351 :
352 : {
353 164 : return papszCategoryNames;
354 : }
355 :
356 : /************************************************************************/
357 : /* SetCategoryNames() */
358 : /************************************************************************/
359 :
360 1 : CPLErr MEMRasterBand::SetCategoryNames( char ** papszNewNames )
361 :
362 : {
363 1 : CSLDestroy( papszCategoryNames );
364 1 : papszCategoryNames = CSLDuplicate( papszNewNames );
365 :
366 1 : return CE_None;
367 : }
368 :
369 : /************************************************************************/
370 : /* SetDefaultHistogram() */
371 : /************************************************************************/
372 :
373 3 : CPLErr MEMRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
374 : int nBuckets, int *panHistogram)
375 :
376 : {
377 : CPLXMLNode *psNode;
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Do we have a matching histogram we should replace? */
381 : /* -------------------------------------------------------------------- */
382 : psNode = PamFindMatchingHistogram( psSavedHistograms,
383 : dfMin, dfMax, nBuckets,
384 3 : TRUE, TRUE );
385 3 : if( psNode != NULL )
386 : {
387 : /* blow this one away */
388 1 : CPLRemoveXMLChild( psSavedHistograms, psNode );
389 1 : CPLDestroyXMLNode( psNode );
390 : }
391 :
392 : /* -------------------------------------------------------------------- */
393 : /* Translate into a histogram XML tree. */
394 : /* -------------------------------------------------------------------- */
395 : CPLXMLNode *psHistItem;
396 :
397 : psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
398 3 : panHistogram, TRUE, FALSE );
399 :
400 : /* -------------------------------------------------------------------- */
401 : /* Insert our new default histogram at the front of the */
402 : /* histogram list so that it will be the default histogram. */
403 : /* -------------------------------------------------------------------- */
404 :
405 3 : if( psSavedHistograms == NULL )
406 : psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
407 1 : "Histograms" );
408 :
409 3 : psHistItem->psNext = psSavedHistograms->psChild;
410 3 : psSavedHistograms->psChild = psHistItem;
411 :
412 3 : return CE_None;
413 : }
414 : /************************************************************************/
415 : /* GetDefaultHistogram() */
416 : /************************************************************************/
417 :
418 : CPLErr
419 1 : MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
420 : int *pnBuckets, int **ppanHistogram,
421 : int bForce,
422 : GDALProgressFunc pfnProgress,
423 : void *pProgressData )
424 :
425 : {
426 1 : if( psSavedHistograms != NULL )
427 : {
428 : CPLXMLNode *psXMLHist;
429 :
430 2 : for( psXMLHist = psSavedHistograms->psChild;
431 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
432 : {
433 : int bApprox, bIncludeOutOfRange;
434 :
435 1 : if( psXMLHist->eType != CXT_Element
436 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
437 0 : continue;
438 :
439 1 : if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
440 : ppanHistogram, &bIncludeOutOfRange,
441 : &bApprox ) )
442 1 : return CE_None;
443 : else
444 0 : return CE_Failure;
445 : }
446 : }
447 :
448 : return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
449 : ppanHistogram, bForce,
450 0 : pfnProgress,pProgressData);
451 : }
452 :
453 : /************************************************************************/
454 : /* ==================================================================== */
455 : /* MEMDataset */
456 : /* ==================================================================== */
457 : /************************************************************************/
458 :
459 :
460 : /************************************************************************/
461 : /* MEMDataset() */
462 : /************************************************************************/
463 :
464 5252 : MEMDataset::MEMDataset()
465 :
466 : {
467 5252 : pszProjection = NULL;
468 5252 : bGeoTransformSet = FALSE;
469 5252 : adfGeoTransform[0] = 0.0;
470 5252 : adfGeoTransform[1] = 1.0;
471 5252 : adfGeoTransform[2] = 0.0;
472 5252 : adfGeoTransform[3] = 0.0;
473 5252 : adfGeoTransform[4] = 0.0;
474 5252 : adfGeoTransform[5] = -1.0;
475 :
476 5252 : nGCPCount = 0;
477 5252 : pasGCPs = NULL;
478 5252 : }
479 :
480 : /************************************************************************/
481 : /* ~MEMDataset() */
482 : /************************************************************************/
483 :
484 5252 : MEMDataset::~MEMDataset()
485 :
486 : {
487 5252 : FlushCache();
488 5252 : CPLFree( pszProjection );
489 :
490 5252 : GDALDeinitGCPs( nGCPCount, pasGCPs );
491 5252 : CPLFree( pasGCPs );
492 5252 : }
493 :
494 : /************************************************************************/
495 : /* GetProjectionRef() */
496 : /************************************************************************/
497 :
498 90 : const char *MEMDataset::GetProjectionRef()
499 :
500 : {
501 90 : if( pszProjection == NULL )
502 81 : return "";
503 : else
504 9 : return pszProjection;
505 : }
506 :
507 : /************************************************************************/
508 : /* SetProjection() */
509 : /************************************************************************/
510 :
511 83 : CPLErr MEMDataset::SetProjection( const char *pszProjectionIn )
512 :
513 : {
514 83 : CPLFree( pszProjection );
515 83 : pszProjection = CPLStrdup( pszProjectionIn );
516 :
517 83 : return CE_None;
518 : }
519 :
520 : /************************************************************************/
521 : /* GetGeoTransform() */
522 : /************************************************************************/
523 :
524 164 : CPLErr MEMDataset::GetGeoTransform( double *padfGeoTransform )
525 :
526 : {
527 164 : memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
528 164 : if( bGeoTransformSet )
529 87 : return CE_None;
530 : else
531 77 : return CE_Failure;
532 : }
533 :
534 : /************************************************************************/
535 : /* SetGeoTransform() */
536 : /************************************************************************/
537 :
538 96 : CPLErr MEMDataset::SetGeoTransform( double *padfGeoTransform )
539 :
540 : {
541 96 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
542 96 : bGeoTransformSet = TRUE;
543 :
544 96 : return CE_None;
545 : }
546 :
547 : /************************************************************************/
548 : /* GetInternalHandle() */
549 : /************************************************************************/
550 :
551 0 : void *MEMDataset::GetInternalHandle( const char * pszRequest)
552 :
553 : {
554 : // check for MEMORYnnn string in pszRequest (nnnn can be up to 10
555 : // digits, or even omitted)
556 0 : if( EQUALN(pszRequest,"MEMORY",6))
557 : {
558 0 : if(int BandNumber = CPLScanLong(&pszRequest[6], 10))
559 : {
560 : MEMRasterBand *RequestedRasterBand =
561 0 : (MEMRasterBand *)GetRasterBand(BandNumber);
562 :
563 : // we're within a MEMDataset so the only thing a RasterBand
564 : // could be is a MEMRasterBand
565 :
566 0 : if( RequestedRasterBand != NULL )
567 : {
568 : // return the internal band data pointer
569 0 : return(RequestedRasterBand->GetData());
570 : }
571 : }
572 : }
573 :
574 0 : return NULL;
575 : }
576 : /************************************************************************/
577 : /* GetGCPCount() */
578 : /************************************************************************/
579 :
580 81 : int MEMDataset::GetGCPCount()
581 :
582 : {
583 81 : return nGCPCount;
584 : }
585 :
586 : /************************************************************************/
587 : /* GetGCPProjection() */
588 : /************************************************************************/
589 :
590 1 : const char *MEMDataset::GetGCPProjection()
591 :
592 : {
593 1 : return osGCPProjection;
594 : }
595 :
596 : /************************************************************************/
597 : /* GetGCPs() */
598 : /************************************************************************/
599 :
600 1 : const GDAL_GCP *MEMDataset::GetGCPs()
601 :
602 : {
603 1 : return pasGCPs;
604 : }
605 :
606 : /************************************************************************/
607 : /* SetGCPs() */
608 : /************************************************************************/
609 :
610 5 : CPLErr MEMDataset::SetGCPs( int nNewCount, const GDAL_GCP *pasNewGCPList,
611 : const char *pszGCPProjection )
612 :
613 : {
614 5 : GDALDeinitGCPs( nGCPCount, pasGCPs );
615 5 : CPLFree( pasGCPs );
616 :
617 5 : if( pszGCPProjection == NULL )
618 0 : osGCPProjection = "";
619 : else
620 5 : osGCPProjection = pszGCPProjection;
621 :
622 5 : nGCPCount = nNewCount;
623 5 : pasGCPs = GDALDuplicateGCPs( nGCPCount, pasNewGCPList );
624 :
625 5 : return CE_None;
626 : }
627 :
628 : /************************************************************************/
629 : /* AddBand() */
630 : /* */
631 : /* Add a new band to the dataset, allowing creation options to */
632 : /* specify the existing memory to use, otherwise create new */
633 : /* memory. */
634 : /************************************************************************/
635 :
636 278 : CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
637 :
638 : {
639 278 : int nBandId = GetRasterCount() + 1;
640 : GByte *pData;
641 278 : int nPixelSize = (GDALGetDataTypeSize(eType) / 8);
642 :
643 : /* -------------------------------------------------------------------- */
644 : /* Do we need to allocate the memory ourselves? This is the */
645 : /* simple case. */
646 : /* -------------------------------------------------------------------- */
647 278 : if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL )
648 : {
649 :
650 : pData = (GByte *)
651 8 : VSICalloc(nPixelSize * GetRasterXSize(), GetRasterYSize() );
652 :
653 8 : if( pData == NULL )
654 : {
655 : CPLError( CE_Failure, CPLE_OutOfMemory,
656 0 : "Unable to create band arrays ... out of memory." );
657 0 : return CE_Failure;
658 : }
659 :
660 : SetBand( nBandId,
661 : new MEMRasterBand( this, nBandId, pData, eType, nPixelSize,
662 8 : nPixelSize * GetRasterXSize(), TRUE ) );
663 :
664 8 : return CE_None;
665 : }
666 :
667 : /* -------------------------------------------------------------------- */
668 : /* Get layout of memory and other flags. */
669 : /* -------------------------------------------------------------------- */
670 : const char *pszOption;
671 : int nPixelOffset, nLineOffset;
672 : const char *pszDataPointer;
673 :
674 270 : pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
675 : pData = (GByte *) CPLScanPointer(pszDataPointer,
676 270 : strlen(pszDataPointer));
677 :
678 270 : pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET");
679 270 : if( pszOption == NULL )
680 270 : nPixelOffset = nPixelSize;
681 : else
682 0 : nPixelOffset = atoi(pszOption);
683 :
684 270 : pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET");
685 270 : if( pszOption == NULL )
686 270 : nLineOffset = GetRasterXSize() * nPixelOffset;
687 : else
688 0 : nLineOffset = atoi(pszOption);
689 :
690 : SetBand( nBandId,
691 : new MEMRasterBand( this, nBandId, pData, eType,
692 270 : nPixelOffset, nLineOffset, FALSE ) );
693 :
694 270 : return CE_None;
695 : }
696 :
697 : /************************************************************************/
698 : /* Open() */
699 : /************************************************************************/
700 :
701 3635 : GDALDataset *MEMDataset::Open( GDALOpenInfo * poOpenInfo )
702 :
703 : {
704 : char **papszOptions;
705 :
706 : /* -------------------------------------------------------------------- */
707 : /* Do we have the special filename signature for MEM format */
708 : /* description strings? */
709 : /* -------------------------------------------------------------------- */
710 3635 : if( !EQUALN(poOpenInfo->pszFilename,"MEM:::",6)
711 : || poOpenInfo->fp != NULL )
712 3632 : return NULL;
713 :
714 : papszOptions = CSLTokenizeStringComplex(poOpenInfo->pszFilename+6, ",",
715 3 : TRUE, FALSE );
716 :
717 : /* -------------------------------------------------------------------- */
718 : /* Verify we have all required fields */
719 : /* -------------------------------------------------------------------- */
720 3 : if( CSLFetchNameValue( papszOptions, "PIXELS" ) == NULL
721 : || CSLFetchNameValue( papszOptions, "LINES" ) == NULL
722 : || CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL )
723 : {
724 : CPLError( CE_Failure, CPLE_AppDefined,
725 : "Missing required field (one of PIXELS, LINES or DATAPOINTER)\n"
726 1 : "Unable to access in-memory array." );
727 :
728 1 : CSLDestroy( papszOptions );
729 1 : return NULL;
730 : }
731 :
732 : /* -------------------------------------------------------------------- */
733 : /* Create the new MEMDataset object. */
734 : /* -------------------------------------------------------------------- */
735 : MEMDataset *poDS;
736 :
737 2 : poDS = new MEMDataset();
738 :
739 2 : poDS->nRasterXSize = atoi(CSLFetchNameValue(papszOptions,"PIXELS"));
740 2 : poDS->nRasterYSize = atoi(CSLFetchNameValue(papszOptions,"LINES"));
741 2 : poDS->eAccess = GA_Update;
742 :
743 : /* -------------------------------------------------------------------- */
744 : /* Extract other information. */
745 : /* -------------------------------------------------------------------- */
746 : const char *pszOption;
747 : GDALDataType eType;
748 : int nBands, nPixelOffset, nLineOffset;
749 : size_t nBandOffset;
750 : const char *pszDataPointer;
751 : GByte *pabyData;
752 :
753 2 : pszOption = CSLFetchNameValue(papszOptions,"BANDS");
754 2 : if( pszOption == NULL )
755 1 : nBands = 1;
756 : else
757 : {
758 1 : nBands = atoi(pszOption);
759 : }
760 :
761 2 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
762 : !GDALCheckBandCount(nBands, TRUE))
763 : {
764 0 : CSLDestroy( papszOptions );
765 0 : delete poDS;
766 0 : return NULL;
767 : }
768 :
769 2 : pszOption = CSLFetchNameValue(papszOptions,"DATATYPE");
770 2 : if( pszOption == NULL )
771 0 : eType = GDT_Byte;
772 : else
773 : {
774 2 : if( atoi(pszOption) > 0 && atoi(pszOption) < GDT_TypeCount )
775 0 : eType = (GDALDataType) atoi(pszOption);
776 : else
777 : {
778 : int iType;
779 :
780 2 : eType = GDT_Unknown;
781 14 : for( iType = 0; iType < GDT_TypeCount; iType++ )
782 : {
783 14 : if( EQUAL(GDALGetDataTypeName((GDALDataType) iType),
784 : pszOption) )
785 : {
786 2 : eType = (GDALDataType) iType;
787 2 : break;
788 : }
789 : }
790 :
791 2 : if( eType == GDT_Unknown )
792 : {
793 : CPLError( CE_Failure, CPLE_AppDefined,
794 : "DATATYPE=%s not recognised.",
795 0 : pszOption );
796 0 : CSLDestroy( papszOptions );
797 0 : delete poDS;
798 0 : return NULL;
799 : }
800 : }
801 : }
802 :
803 2 : pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET");
804 2 : if( pszOption == NULL )
805 1 : nPixelOffset = GDALGetDataTypeSize(eType) / 8;
806 : else
807 1 : nPixelOffset = atoi(pszOption);
808 :
809 2 : pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET");
810 2 : if( pszOption == NULL )
811 1 : nLineOffset = poDS->nRasterXSize * nPixelOffset;
812 : else
813 1 : nLineOffset = atoi(pszOption);
814 :
815 2 : pszOption = CSLFetchNameValue(papszOptions,"BANDOFFSET");
816 2 : if( pszOption == NULL )
817 1 : nBandOffset = nLineOffset * (size_t) poDS->nRasterYSize;
818 : else
819 1 : nBandOffset = atoi(pszOption);
820 :
821 2 : pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
822 : pabyData = (GByte *) CPLScanPointer( pszDataPointer,
823 2 : strlen(pszDataPointer) );
824 :
825 : /* -------------------------------------------------------------------- */
826 : /* Create band information objects. */
827 : /* -------------------------------------------------------------------- */
828 8 : for( int iBand = 0; iBand < nBands; iBand++ )
829 : {
830 : poDS->SetBand( iBand+1,
831 : new MEMRasterBand( poDS, iBand+1,
832 : pabyData + iBand * nBandOffset,
833 : eType, nPixelOffset, nLineOffset,
834 2 : FALSE ) );
835 : }
836 :
837 : /* -------------------------------------------------------------------- */
838 : /* Try to return a regular handle on the file. */
839 : /* -------------------------------------------------------------------- */
840 2 : CSLDestroy( papszOptions );
841 2 : return poDS;
842 : }
843 :
844 : /************************************************************************/
845 : /* Create() */
846 : /************************************************************************/
847 :
848 5252 : GDALDataset *MEMDataset::Create( const char * pszFilename,
849 : int nXSize, int nYSize, int nBands,
850 : GDALDataType eType,
851 : char **papszOptions )
852 :
853 : {
854 :
855 : /* -------------------------------------------------------------------- */
856 : /* Do we want a pixel interleaved buffer? I mostly care about */
857 : /* this to test pixel interleaved io in other contexts, but it */
858 : /* could be useful to create a directly accessable buffer for */
859 : /* some apps. */
860 : /* -------------------------------------------------------------------- */
861 5252 : int bPixelInterleaved = FALSE;
862 5252 : const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
863 5252 : if( pszOption && EQUAL(pszOption,"PIXEL") )
864 3 : bPixelInterleaved = TRUE;
865 :
866 : /* -------------------------------------------------------------------- */
867 : /* First allocate band data, verifying that we can get enough */
868 : /* memory. */
869 : /* -------------------------------------------------------------------- */
870 5252 : std::vector<GByte*> apbyBandData;
871 : int iBand;
872 5252 : int nWordSize = GDALGetDataTypeSize(eType) / 8;
873 5252 : int bAllocOK = TRUE;
874 :
875 5252 : if( bPixelInterleaved )
876 : {
877 : apbyBandData.push_back(
878 3 : (GByte *) VSIMalloc3( nWordSize * nBands, nXSize, nYSize ) );
879 :
880 3 : if( apbyBandData[0] == NULL )
881 1 : bAllocOK = FALSE;
882 : else
883 : {
884 2 : memset(apbyBandData[0], 0, ((size_t)nWordSize) * nBands * nXSize * nYSize);
885 6 : for( iBand = 1; iBand < nBands; iBand++ )
886 4 : apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize );
887 : }
888 : }
889 : else
890 : {
891 10473 : for( iBand = 0; iBand < nBands; iBand++ )
892 : {
893 : apbyBandData.push_back(
894 5225 : (GByte *) VSIMalloc3( nWordSize, nXSize, nYSize ) );
895 5225 : if( apbyBandData[iBand] == NULL )
896 : {
897 1 : bAllocOK = FALSE;
898 1 : break;
899 : }
900 5224 : memset(apbyBandData[iBand], 0, ((size_t)nWordSize) * nXSize * nYSize);
901 : }
902 : }
903 :
904 5252 : if( !bAllocOK )
905 : {
906 4 : for( iBand = 0; iBand < (int) apbyBandData.size(); iBand++ )
907 : {
908 2 : if( apbyBandData[iBand] )
909 0 : VSIFree( apbyBandData[iBand] );
910 : }
911 : CPLError( CE_Failure, CPLE_OutOfMemory,
912 2 : "Unable to create band arrays ... out of memory." );
913 2 : return NULL;
914 : }
915 :
916 : /* -------------------------------------------------------------------- */
917 : /* Create the new GTiffDataset object. */
918 : /* -------------------------------------------------------------------- */
919 : MEMDataset *poDS;
920 :
921 5250 : poDS = new MEMDataset();
922 :
923 5250 : poDS->nRasterXSize = nXSize;
924 5250 : poDS->nRasterYSize = nYSize;
925 5250 : poDS->eAccess = GA_Update;
926 :
927 10500 : const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
928 5250 : if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
929 0 : poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
930 :
931 5250 : if( bPixelInterleaved )
932 2 : poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
933 :
934 : /* -------------------------------------------------------------------- */
935 : /* Create band information objects. */
936 : /* -------------------------------------------------------------------- */
937 10480 : for( iBand = 0; iBand < nBands; iBand++ )
938 : {
939 : MEMRasterBand *poNewBand;
940 :
941 5230 : if( bPixelInterleaved )
942 : poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
943 : eType, nWordSize * nBands, 0,
944 6 : iBand == 0 );
945 : else
946 : poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
947 5224 : eType, 0, 0, TRUE );
948 :
949 5230 : poDS->SetBand( iBand+1, poNewBand );
950 : }
951 :
952 : /* -------------------------------------------------------------------- */
953 : /* Try to return a regular handle on the file. */
954 : /* -------------------------------------------------------------------- */
955 5250 : return poDS;
956 : }
957 :
958 : /************************************************************************/
959 : /* MEMDatasetIdentify() */
960 : /************************************************************************/
961 :
962 10205 : static int MEMDatasetIdentify( GDALOpenInfo * poOpenInfo )
963 : {
964 : return (strncmp(poOpenInfo->pszFilename, "MEM:::", 6) == 0 &&
965 10205 : poOpenInfo->fp == NULL);
966 : }
967 :
968 : /************************************************************************/
969 : /* MEMDatasetDelete() */
970 : /************************************************************************/
971 :
972 127 : static CPLErr MEMDatasetDelete(const char* fileName)
973 : {
974 : /* Null implementation, so that people can Delete("MEM:::") */
975 127 : return CE_None;
976 : }
977 :
978 : /************************************************************************/
979 : /* GDALRegister_MEM() */
980 : /************************************************************************/
981 :
982 582 : void GDALRegister_MEM()
983 :
984 : {
985 : GDALDriver *poDriver;
986 :
987 582 : if( GDALGetDriverByName( "MEM" ) == NULL )
988 : {
989 561 : poDriver = new GDALDriver();
990 :
991 561 : poDriver->SetDescription( "MEM" );
992 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
993 561 : "In Memory Raster" );
994 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
995 561 : "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
996 :
997 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
998 : "<CreationOptionList>"
999 : " <Option name='INTERLEAVE' type='string-select' default='BAND'>"
1000 : " <Value>BAND</Value>"
1001 : " <Value>PIXEL</Value>"
1002 : " </Option>"
1003 561 : "</CreationOptionList>" );
1004 :
1005 : /* Define GDAL_NO_OPEN_FOR_MEM_DRIVER macro to undefine Open() method for MEM driver. */
1006 : /* Otherwise, bad user input can trigger easily a GDAL crash as random pointers can be passed as a string. */
1007 : /* All code in GDAL tree using the MEM driver use the Create() method only, so Open() */
1008 : /* is not needed, except for esoteric uses */
1009 : #ifndef GDAL_NO_OPEN_FOR_MEM_DRIVER
1010 561 : poDriver->pfnOpen = MEMDataset::Open;
1011 561 : poDriver->pfnIdentify = MEMDatasetIdentify;
1012 : #endif
1013 561 : poDriver->pfnCreate = MEMDataset::Create;
1014 561 : poDriver->pfnDelete = MEMDatasetDelete;
1015 :
1016 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1017 : }
1018 582 : }
1019 :
|