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