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