<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta name="robots" content="noindex"> <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>gdal_drivertut.dox Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body bgcolor="#ffffff"> <!-- Generated by Doxygen 1.2.3-20001105 on Thu Mar 28 09:47:28 2002 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> </center> <hr><h1>gdal_drivertut.dox</h1><div class="fragment"><pre>00001 00073 <font class="comment">/* Before trying JDEMOpen() we first verify that there is at */</font> 00074 <font class="comment">/* least one "\n#keyword" type signature in the first chunk of */</font> 00075 <font class="comment">/* the file. */</font> 00076 <font class="comment">/* -------------------------------------------------------------------- */</font> 00077 <font class="keywordflow">if</font>( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 ) 00078 <font class="keywordflow">return</font> NULL; 00079 00080 <font class="comment">/* check if century values seem reasonable */</font> 00081 <font class="keywordflow">if</font>( (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+11,<font class="stringliteral">"19"</font>,2) 00082 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+11,<font class="stringliteral">"20"</font>,2)) 00083 || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+15,<font class="stringliteral">"19"</font>,2) 00084 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+15,<font class="stringliteral">"20"</font>,2)) 00085 || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+19,<font class="stringliteral">"19"</font>,2) 00086 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+19,<font class="stringliteral">"20"</font>,2)) ) 00087 { 00088 <font class="keywordflow">return</font> NULL; 00089 } 00090 00091 <font class="comment">/* -------------------------------------------------------------------- */</font> 00092 <font class="comment">/* Create a corresponding GDALDataset. */</font> 00093 <font class="comment">/* -------------------------------------------------------------------- */</font> 00094 JDEMDataset *poDS; 00095 00096 poDS = <font class="keyword">new</font> JDEMDataset(); 00097 00098 poDS->poDriver = poJDEMDriver; 00099 poDS->fp = poOpenInfo->fp; 00100 poOpenInfo->fp = NULL; 00101 00102 <font class="comment">/* -------------------------------------------------------------------- */</font> 00103 <font class="comment">/* Read the header. */</font> 00104 <font class="comment">/* -------------------------------------------------------------------- */</font> 00105 VSIFSeek( poDS->fp, 0, SEEK_SET ); 00106 VSIFRead( poDS->abyHeader, 1, 1012, poDS->fp ); 00107 00108 poDS->nRasterXSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS->abyHeader + 23, 3 ); 00109 poDS->nRasterYSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS->abyHeader + 26, 3 ); 00110 00111 <font class="comment">/* -------------------------------------------------------------------- */</font> 00112 <font class="comment">/* Create band information objects. */</font> 00113 <font class="comment">/* -------------------------------------------------------------------- */</font> 00114 poDS->nBands = 1; 00115 poDS->SetBand( 1, <font class="keyword">new</font> JDEMRasterBand( poDS, 1 )); 00116 00117 <font class="keywordflow">return</font>( poDS ); 00118 } 00119 \endverbatim 00120 00121 The first step in any database Open function is to verify that the file 00122 being passed is in fact of the type <font class="keyword">this</font> driver is <font class="keywordflow">for</font>. It is important 00123 to realize that each driver's Open function is called in turn till one 00124 succeeds. Drivers must quitly <font class="keywordflow">return</font> NULL <font class="keywordflow">if</font> the passed file is not of 00125 their format. They should only produce an error <font class="keywordflow">if</font> the file does appear to 00126 be of their supported format, but is <font class="keywordflow">for</font> some reason unsupported or corrupt. 00127 00128 The information on the file to be opened is passed in contained in a 00129 GDALOpenInfo object. The GDALOpenInfo includes the following <font class="keyword">public</font> 00130 data members: 00131 00132 \code 00133 <font class="keywordtype">char</font> *pszFilename; 00134 00135 GDALAccess eAccess; <font class="comment">/* GA_ReadOnly or GA_Update */</font> 00136 00137 GBool bStatOK; 00138 VSIStatBuf sStat; 00139 00140 FILE *fp; 00141 00142 <font class="keywordtype">int</font> nHeaderBytes; 00143 GByte *pabyHeader; 00144 \endcode 00145 00146 The driver can inspect these to establish <font class="keywordflow">if</font> the file is supported. If the 00147 pszFilename refers to an object in the file system, the <b>bStatOK</b> flag 00148 will be set, and the <b>sStat</b> structure will contain normal stat() 00149 information about the object (be it directory, file, device). If the object 00150 is a regular readable file, the <b>fp</b> will be non-NULL, and can be used 00151 <font class="keywordflow">for</font> reads on the file (please use the VSI stdio functions from 00152 cpl_vsi.h). As well, <font class="keywordflow">if</font> the file was successfully opened, the first kilobyte 00153 or so is read in, and put in <b>pabyHeader</b>, with the exact size in 00154 <b>nHeaderBytes</b>. 00155 00156 In <font class="keyword">this</font> typical testing example it is verified that the file was successfully 00157 opened, that we have at least enough header information to perform our test, 00158 and that various parts of the header are as expected <font class="keywordflow">for</font> <font class="keyword">this</font> format. In 00159 <font class="keyword">this</font> <font class="keywordflow">case</font>, there are no <i>magic</i> numbers <font class="keywordflow">for</font> JDEM format so we check 00160 various date fields to ensure they have reasonable century values. If the 00161 test fails, we quietly <font class="keywordflow">return</font> NULL indicating <font class="keyword">this</font> file isn't of our supported 00162 format. 00163 00164 \code 00165 <font class="keywordflow">if</font>( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 ) 00166 <font class="keywordflow">return</font> NULL; 00167 00168 <font class="comment">/* check if century values seem reasonable */</font> 00169 <font class="keywordflow">if</font>( (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+11,<font class="stringliteral">"19"</font>,2) 00170 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+11,<font class="stringliteral">"20"</font>,2)) 00171 || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+15,<font class="stringliteral">"19"</font>,2) 00172 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+15,<font class="stringliteral">"20"</font>,2)) 00173 || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+19,<font class="stringliteral">"19"</font>,2) 00174 && !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo->pabyHeader+19,<font class="stringliteral">"20"</font>,2)) ) 00175 { 00176 <font class="keywordflow">return</font> NULL; 00177 } 00178 \endcode 00179 00180 It is important to make the <i>is <font class="keyword">this</font> my format</i> test as stringent as 00181 possible. In <font class="keyword">this</font> particular <font class="keywordflow">case</font> the test is weak, and a file that happened 00182 to have 19s or 20s at a few locations could be erroneously recognised as 00183 JDEM format, causing it to not be handled properly. 00184 00185 Once we are satisfied that the file is of our format, we need to create 00186 an instance of the database <font class="keyword">class </font>in which we will set various information 00187 of interest. 00188 00189 \code 00190 JDEMDataset *poDS; 00191 00192 poDS = <font class="keyword">new</font> JDEMDataset(); 00193 00194 poDS->poDriver = poJDEMDriver; 00195 poDS->fp = poOpenInfo->fp; 00196 poOpenInfo->fp = NULL; 00197 \endcode 00198 00199 The setting of poDriver is required. We will see poJDEMDriver later when 00200 we discuss the driver instance object. 00201 00202 Generally at <font class="keyword">this</font> point we would open the file, to acquire a file handle 00203 <font class="keywordflow">for</font> the dataset; however, <font class="keywordflow">if</font> read-only access is sufficient it is permitted 00204 to <b>assume ownership</b> of the FILE * from the GDALOpenInfo object. 00205 Just ensure that it is set to NULL in the GDALOpenInfo to avoid having it 00206 get closed twice. It is also important to note that the state of the 00207 FILE * adopted is indeterminate. Ensure that the current location is reset 00208 with VSIFSeek() before assuming you can read from it. This is accomplished 00209 in the following statements which reset the file and read the header. 00210 00211 \code 00212 VSIFSeek( poDS->fp, 0, SEEK_SET ); 00213 VSIFRead( poDS->abyHeader, 1, 1012, poDS->fp ); 00214 \endcode 00215 00216 Next the X and Y size are extracted from the header. The nRasterXSize and 00217 nRasterYSize are data fields inherited from the <a class="code" href="class_GDALDataset.html">GDALDataset</a> base <font class="keyword">class</font>, and 00218 must be set by the Open() method. 00219 00220 \code 00221 poDS->nRasterXSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS->abyHeader + 23, 3 ); 00222 poDS->nRasterYSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS->abyHeader + 26, 3 ); 00223 \endcode 00224 00225 Finally, all the bands related to <font class="keyword">this</font> dataset must be attached <font class="keyword">using</font> 00226 the SetBand() method. We will explore the JDEMRasterBand() <font class="keyword">class </font>shortly. 00227 00228 \code 00229 poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 )); 00230 00231 <font class="keywordflow">return</font>( poDS ); 00232 \endcode 00233 00234 <h2><a name=<font class="stringliteral">"rasterband"</font>>Implementing the RasterBand</a></h2> 00235 00236 Similar to the customized JDEMDataset <font class="keyword">class </font>subclassed from <a class="code" href="class_GDALDataset.html">GDALDataset</a>, 00237 we also need to declare and implement a customized JDEMRasterBand derived 00238 from <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a> for access to the band(s) of the JDEM file. For 00239 JDEMRasterBand the declaration looks like this: 00240 00241 \code 00242 class JDEMRasterBand : <font class="keyword">public</font> <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a> 00243 { 00244 <font class="keyword">public</font>: 00245 JDEMRasterBand( JDEMDataset *, <font class="keywordtype">int</font> ); 00246 <font class="keyword">virtual</font> CPLErr IReadBlock( <font class="keywordtype">int</font>, <font class="keywordtype">int</font>, <font class="keywordtype">void</font> * ); 00247 }; 00248 \endcode 00249 00250 The constructor may have any signature, and is only called from the Open() 00251 method. Other <font class="keyword">virtual</font> methods, such as IReadBlock() must be exactly 00252 matched to the method signature in gdal_priv.h. 00253 00254 The constructor implementation looks like <font class="keyword">this</font>: 00255 00256 \code 00257 JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, <font class="keywordtype">int</font> nBand )<font class="keyword"></font> 00258 <font class="keyword"></font> 00259 <font class="keyword"></font>{ 00260 this->poDS = poDS; 00261 this->nBand = nBand; 00262 00263 eDataType = GDT_Float32; 00264 00265 nBlockXSize = poDS->GetRasterXSize(); 00266 nBlockYSize = 1; 00267 } 00268 \endcode 00269 00270 The following data members are inherited from <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a>, and should 00271 generally be set in the band constructor. 00272 00273 <ul> 00274 <li> <b>poDS</b>: Pointer to the parent <a class="code" href="class_GDALDataset.html">GDALDataset</a>. 00275 <li> <b>nBand</b>: The band number within the dataset. 00276 <li> <b>eDataType</b>: The data type of pixels in <font class="keyword">this</font> band. 00277 <li> <b>nBlockXSize</b>: The width of one block in <font class="keyword">this</font> band. 00278 <li> <b>nBlockYSize</b>: The height of one block in <font class="keyword">this</font> band. 00279 </ul> 00280 00281 The full set of possible GDALDataType values are declared in gdal.h, and 00282 include GDT_Byte, GDT_UInt16, GDT_Int16, and GDT_Float32. The block size is 00283 used to establish a <i>natural</i> or efficient block size to access the data 00284 with. For tiled datasets <font class="keyword">this</font> will be the size of a tile, <font class="keywordflow">while</font> <font class="keywordflow">for</font> most 00285 other datasets it will be one scanline, as in <font class="keyword">this</font> <font class="keywordflow">case</font>. 00286 00287 Next we see the implementation of the code that actually reads the image 00288 data, IReadBlock(). 00289 00290 \code 00291 CPLErr JDEMRasterBand::IReadBlock( <font class="keywordtype">int</font> nBlockXOff, <font class="keywordtype">int</font> nBlockYOff, 00292 <font class="keywordtype">void</font> * pImage )<font class="keyword"></font> 00293 <font class="keyword"></font> 00294 <font class="keyword"></font>{ 00295 JDEMDataset *poGDS = (JDEMDataset *) poDS; 00296 <font class="keywordtype">char</font> *pszRecord; 00297 <font class="keywordtype">int</font> nRecordSize = nBlockXSize*5 + 9 + 2; 00298 <font class="keywordtype">int</font> i; 00299 00300 VSIFSeek( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET ); 00301 00302 pszRecord = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(nRecordSize); 00303 VSIFRead( pszRecord, 1, nRecordSize, poGDS->fp ); 00304 00305 <font class="keywordflow">if</font>( !EQUALN((<font class="keywordtype">char</font> *) poGDS->abyHeader,pszRecord,6) ) 00306 { 00307 CPLFree( pszRecord ); 00308 00309 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00310 <font class="stringliteral">"JDEM Scanline corrupt. Perhaps file was not transferred\n"</font> 00311 <font class="stringliteral">"in binary mode?"</font> ); 00312 <font class="keywordflow">return</font> CE_Failure; 00313 } 00314 00315 <font class="keywordflow">if</font>( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 ) 00316 { 00317 CPLFree( pszRecord ); 00318 00319 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00320 <font class="stringliteral">"JDEM scanline out of order, JDEM driver does not\n"</font> 00321 <font class="stringliteral">"currently support partial datasets."</font> ); 00322 <font class="keywordflow">return</font> CE_Failure; 00323 } 00324 00325 <font class="keywordflow">for</font>( i = 0; i < nBlockXSize; i++ ) 00326 ((<font class="keywordtype">float</font> *) pImage)[i] = JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1; 00327 00328 <font class="keywordflow">return</font> CE_None; 00329 } 00330 \endcode 00331 00332 Key items to note are: 00333 00334 <ul> 00335 <li> It is typical to cast the GDALRasterBand::poDS member to the derived 00336 type of the owning dataset. If your RasterBand <font class="keyword">class </font>will need priveledged 00337 access to the owning dataset object, ensure it is declared as a friend (omitted 00338 above for brevity). 00339 00340 <li> If an error occurs, report it with CPLError(), and return CE_Failure. 00341 Otherwise return CE_None. 00342 00343 <li> The pImage buffer should be filled with one block of data. The block 00344 is the size declared in nBlockXSize and nBlockYSize for the raster band. The 00345 type of the data within pImage should match the type declared in 00346 eDataType in the raster band object. 00347 00348 <li> The nBlockXOff and nBlockYOff are block offsets, so with 128x128 tiled 00349 datasets values of 1 and 1 would indicate the block going from (128,128) to 00350 (255,255) should be loaded. 00351 00352 </ul> 00353 00354 <h2><a name="driver">The Driver</a></h2> 00355 00356 While the JDEMDataset and JDEMRasterBand are now ready to use to read image 00357 data, it still isn't clear how the GDAL system knows about the new driver. 00358 This is accomplished via the <a class="code" href="class_GDALDriverManager.html">GDALDriverManager</a>. To register our format we 00359 implement a registration function: 00360 00361 \code 00362 static <a class="code" href="class_GDALDriver.html">GDALDriver</a> *poJDEMDriver = NULL; 00363 00364 CPL_C_START 00365 void GDALRegister_JDEM(void); 00366 CPL_C_END 00367 00368 ... 00369 00370 void GDALRegister_JDEM() 00371 00372 { 00373 <a class="code" href="class_GDALDriver.html">GDALDriver</a> *poDriver; 00374 00375 <font class="keywordflow">if</font>( poJDEMDriver == NULL ) 00376 { 00377 poJDEMDriver = poDriver = <font class="keyword">new</font> GDALDriver(); 00378 00379 poDriver->pszShortName = <font class="stringliteral">"JDEM"</font>; 00380 poDriver->pszLongName = <font class="stringliteral">"Japanese DEM (.mem)"</font>; 00381 poDriver->pszHelpTopic = <font class="stringliteral">"frmt_various.html#JDEM"</font>; 00382 00383 poDriver->pfnOpen = JDEMDataset::Open; 00384 00385 GetGDALDriverManager()->RegisterDriver( poDriver ); 00386 } 00387 } 00388 \endcode 00389 00390 The registration function will create an instance of a <a class="code" href="class_GDALDriver.html">GDALDriver</a> object 00391 when first called, and keep track of it in the local poJDEMDriver <font class="keyword">static</font> 00392 pointer. The following fields in the <a class="code" href="class_GDALDriver.html">GDALDriver</a> can be set before 00393 registering it with the GDALDriverManager(). 00394 00395 <ul> 00396 <li> pszShortName: A <font class="keywordtype">short</font> unique name <font class="keywordflow">for</font> <font class="keyword">this</font> format, often used to identity 00397 the driver in scripts and commandline programs. Normally 3-5 characters 00398 in length, and matching the prefix of the format classes. (manditory) 00399 00400 <li> pszLongName: A longer descriptive name <font class="keywordflow">for</font> the file format, often 00401 indicating the typical extension <font class="keywordflow">for</font> the format. (manditory) 00402 00403 <li> pszHelpTopic: The name of a help topic to display <font class="keywordflow">for</font> <font class="keyword">this</font> driver, <font class="keywordflow">if</font> 00404 any. In <font class="keyword">this</font> <font class="keywordflow">case</font> JDEM format is contained within the various format 00405 web page held in gdal/html. (optional) 00406 00407 <li> pfnOpen: The function to call to <font class="keywordflow">try</font> opening files of <font class="keyword">this</font> format. 00408 (optional) 00409 00410 <li> pfnCreate: The function to call to create <font class="keyword">new</font> updatable datasets of <font class="keyword">this</font> 00411 format. (optional) 00412 00413 <li> pfnCreateCopy: The function to call to create a <font class="keyword">new</font> dataset of <font class="keyword">this</font> format 00414 copied from another source, but not necessary updatable. (optional) 00415 00416 <li> pfnDelete: The function to call to <font class="keyword">delete</font> a dataset of <font class="keyword">this</font> format. 00417 (optional) 00418 00419 </ul> 00420 00421 <h2><a name=<font class="stringliteral">"addingdriver"</font>>Adding Driver to GDAL Tree</a></h2> 00422 00423 Note that the GDALRegister_JDEM() method must be called by the higher 00424 level program in order to have access to the JDEM driver. Normal practice 00425 when writing <font class="keyword">new</font> drivers is to: 00426 00427 <ol> 00428 <li> Add a driver directory under gdal/frmts, with the directory name the same 00429 as the pszShortName value. 00430 00431 <li> Add a GNUmakefile and makefile.vc in that directory modelled on those 00432 from other similar directories (ie. the jdem directory). 00433 00434 <li> Add the module with the dataset, and rasterband implementation. 00435 Generally <font class="keyword">this</font> is called <short_name>dataset.cpp, with all the GDAL specifc 00436 code in one file, though that is not required. 00437 00438 <li> Add the registration entry point declaration (ie. GDALRegister_JDEM()) to 00439 gdal/core/gdal_frmts.h. 00440 00441 <li> Add a call to the registration function to frmts/gdalallregister.c, 00442 <font class="keyword">protected</font> by an appropriate #ifdef. 00443 00444 <li> Add the format <font class="keywordtype">short</font> name to the GDAL_FORMATS macro in 00445 GDALmake.opt.in (and to GDALmake.opt). 00446 00447 <li> Add a format specific item to the EXTRAFLAGS macro in frmts/makefile.vc. 00448 </ol> 00449 00450 Once <font class="keyword">this</font> is all done, it should be possible to rebuild GDAL, and have 00451 the <font class="keyword">new</font> format available in all the utilities. The gdalinfo utility can be 00452 used to test that opening and reporting on the format is working, and the 00453 gdal_translate utility can be used to test image reading. 00454 00455 <h2><a name=<font class="stringliteral">"georef"</font>>Adding Georeferencing</a></h2> 00456 00457 Now we will take the example a step forward, adding georeferencing support. 00458 We add the following two <font class="keyword">virtual</font> method overrides to JDEMDataset, taking 00459 care to exactly match the signature of the method on the GDALRasterDataset 00460 base <font class="keyword">class</font>. 00461 00462 \code 00463 CPLErr GetGeoTransform( <font class="keywordtype">double</font> * padfTransform ); 00464 <font class="keyword">const</font> <font class="keywordtype">char</font> *GetProjectionRef(); 00465 \endcode 00466 00467 The implementation of GetGeoTransform() just copies the usual geotransform 00468 matrix into the supplied buffer. Note that GetGeoTransform() may be called 00469 alot, so it isn't generally wise to <font class="keywordflow">do</font> alot of computation in it. In many 00470 cases the Open() will collect the geotransform, and <font class="keyword">this</font> method will just 00471 copy it over. Also note that the geotransform <font class="keywordflow">return</font> is based on an 00472 anchor point at the top left corner of the top left pixel, not the center 00473 of pixel approach used in some packages. 00474 00475 \code 00476 CPLErr JDEMDataset::GetGeoTransform( <font class="keywordtype">double</font> * padfTransform )<font class="keyword"></font> 00477 <font class="keyword"></font> 00478 <font class="keyword"></font>{ 00479 <font class="keywordtype">double</font> dfLLLat, dfLLLong, dfURLat, dfURLong; 00480 00481 dfLLLat = JDEMGetAngle( (<font class="keywordtype">char</font> *) abyHeader + 29 ); 00482 dfLLLong = JDEMGetAngle( (<font class="keywordtype">char</font> *) abyHeader + 36 ); 00483 dfURLat = JDEMGetAngle( (<font class="keywordtype">char</font> *) abyHeader + 43 ); 00484 dfURLong = JDEMGetAngle( (<font class="keywordtype">char</font> *) abyHeader + 50 ); 00485 00486 padfTransform[0] = dfLLLong; 00487 padfTransform[3] = dfURLat; 00488 padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize(); 00489 padfTransform[2] = 0.0; 00490 00491 padfTransform[4] = 0.0; 00492 padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize(); 00493 00494 00495 <font class="keywordflow">return</font> CE_None; 00496 } 00497 \endcode 00498 00499 The GetProjectionRef() method returns a pointer to an internal string 00500 containing a coordinate system definition in OGC WKT format. In <font class="keyword">this</font> <font class="keywordflow">case</font> 00501 the coordinate system is fixed <font class="keywordflow">for</font> all files of <font class="keyword">this</font> format, but in more 00502 complex cases a definition may need to be composed on the fly, in which <font class="keywordflow">case</font> 00503 it may be helpful to use the OGRSpatialReference <font class="keyword">class </font>to help build the 00504 definition. 00505 00506 \code 00507 const char *JDEMDataset::GetProjectionRef() 00508 00509 { 00510 <font class="keywordflow">return</font>( <font class="stringliteral">"GEOGCS[\"Tokyo\",DATUM[\"Tokyo\",SPHEROID[\"Bessel 1841\","</font> 00511 <font class="stringliteral">"6377397.155,299.1528128,AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,"</font> 00512 <font class="stringliteral">"507,685,0,0,0,0],AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\","</font> 00513 <font class="stringliteral">"0,AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,"</font> 00514 <font class="stringliteral">"AUTHORITY[\"EPSG\",9108]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],"</font> 00515 <font class="stringliteral">"AUTHORITY[\"EPSG\",4301]]"</font> ); 00516 } 00517 \endcode 00518 00519 This completes explanation of the features of the JDEM driver. The full 00520 source <font class="keywordflow">for</font> <a href=<font class="stringliteral">"jdemdataset.cpp.html"</font>>jdemdataset.cpp</a> can be reviewed 00521 as needed. 00522 00523 <h2><a name=<font class="stringliteral">"overviews"</font>>Overviews</a></h2> 00524 00525 GDAL allows file formats to make pre-built overviews available to applications 00526 via the <a class="code" href="class_GDALRasterBand.html#a29">GDALRasterBand::GetOverview</a>() and related methods. However, 00527 implementing <font class="keyword">this</font> is pretty involved, and goes beyond the scope of <font class="keyword">this</font> 00528 document <font class="keywordflow">for</font> now. The GeoTIFF driver (gdal/frmts/gtiff/geotiff.cpp) and 00529 related source can be reviewed <font class="keywordflow">for</font> an example of a file format implementing 00530 overview reporting and creation support. 00531 00532 Formats can also report that they have arbitrary overviews, by overriding 00533 the HasArbitraryOverviews() method on the <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a>, returning TRUE. 00534 In <font class="keyword">this</font> <font class="keywordflow">case</font> the raster band object is expected to override the RasterIO() 00535 method itself, to implement efficient access to imagery with resampling. 00536 This is also involved, and there are alot of requirements <font class="keywordflow">for</font> correct 00537 implementation of the RasterIO() method. An example of <font class="keyword">this</font> can be found 00538 in the ogdi and ecw formats. 00539 00540 However, by far the most common approach to implementing overviews is to 00541 use the <font class="keywordflow">default</font> support in GDAL <font class="keywordflow">for</font> external overviews stored in TIFF files 00542 with the same name as the dataset, but the extension .ovr appended. In 00543 order to enable reading and creation of <font class="keyword">this</font> style of overviews it is necessary 00544 <font class="keywordflow">for</font> the <a class="code" href="class_GDALDataset.html">GDALDataset</a> to initialize the oOvManager object within itself. This 00545 is typically accomplished with a call like the following near the end of the 00546 Open() method. 00547 00548 \code 00549 poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); 00550 \endcode 00551 00552 This will enable <font class="keywordflow">default</font> implementations <font class="keywordflow">for</font> reading and creating overviews <font class="keywordflow">for</font> 00553 the format. It is advised that <font class="keyword">this</font> be enabled <font class="keywordflow">for</font> all simple file system 00554 based formats unless there is a custom overview mechanism to be tied into. 00555 00556 <h2><a name=<font class="stringliteral">"creation"</font>>File Creation</a></h2> 00557 00558 There are two approaches to file creation. The first method is called the 00559 CreateCopy() method, and involves implementing a function that can write a 00560 file in the output format, pulling all imagery and other information needed 00561 from a source <a class="code" href="class_GDALDataset.html">GDALDataset</a>. The second method, the dynamic creation method, 00562 involves implementing a Create method to create the shell of the file, and 00563 then the application writes various information by calls to set methods. 00564 00565 The benefits of the first method are that that all the information is available 00566 at the point the output file is being created. This can be especially 00567 important when implementing file formats <font class="keyword">using</font> external libraries which 00568 require information like colormaps, and georeferencing information at the 00569 point the file is created. The other advantage of <font class="keyword">this</font> method is that the 00570 CreateCopy() method can read some kinds of information, such as min/max, 00571 scaling, description and GCPs <font class="keywordflow">for</font> which there are no equivelent set methods. 00572 00573 The benefits of the second method are that applications can create an 00574 empty <font class="keyword">new</font> file, and write results to it as they become available. A complete 00575 image of the desired data does not have to be available in advance. 00576 00577 For very important formats both methods may be implemented, otherwise <font class="keywordflow">do</font> 00578 whichever is simpler, or provides the required capabilities. 00579 00580 <h3>CreateCopy</h3> 00581 00582 The <a class="code" href="class_GDALDriver.html#a4">GDALDriver::CreateCopy</a>() method call is passed through directly, so 00583 that method should be consulted <font class="keywordflow">for</font> details of arguments. However, some 00584 things to keep in mind are: 00585 00586 <ul> 00587 <li> If the bStrict flag is FALSE the driver should <font class="keywordflow">try</font> to <font class="keywordflow">do</font> something 00588 reasonable when it cannot exactly represent the source dataset, transforming 00589 data types on the fly, droping georeferencing and so forth. 00590 00591 <li> Implementing progress reporting correctly is somewhat involved. The 00592 <font class="keywordflow">return</font> result of the progress function needs always to be checked <font class="keywordflow">for</font> 00593 cancellation, and progress should be reported at reasonable intervals. The 00594 JPEGCreateCopy() method demonstrates good handling of the progress function. 00595 00596 <li> Special creation options should be documented in the online help. 00597 If the options take the format <font class="stringliteral">"NAME=VALUE"</font> the papszOptions list can be 00598 manipulated with CPLFetchNameValue() as demonstrated in the handling of 00599 the QUALITY and PROGRESSIVE flags <font class="keywordflow">for</font> JPEGCreateCopy(). 00600 00601 <li> The returned <a class="code" href="class_GDALDataset.html">GDALDataset</a> handle can be in ReadOnly or Update mode. 00602 Return it in Update mode <font class="keywordflow">if</font> practical, otherwise in ReadOnly mode is fine. 00603 00604 </ul> 00605 00606 The full implementation of the CreateCopy function <font class="keywordflow">for</font> JPEG (which is 00607 assigned to pfnCreateCopy in the <a class="code" href="class_GDALDriver.html">GDALDriver</a> object) is here. 00608 00609 \verbatim 00610 <font class="keyword">static</font> <a class="code" href="class_GDALDataset.html">GDALDataset</a> * 00611 JPEGCreateCopy( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, <a class="code" href="class_GDALDataset.html">GDALDataset</a> *poSrcDS, 00612 <font class="keywordtype">int</font> bStrict, <font class="keywordtype">char</font> ** papszOptions, 00613 GDALProgressFunc pfnProgress, <font class="keywordtype">void</font> * pProgressData )<font class="keyword"></font> 00614 <font class="keyword"></font> 00615 <font class="keyword"></font>{ 00616 <font class="keywordtype">int</font> nBands = poSrcDS-><a class="code" href="class_GDALDataset.html#a3">GetRasterCount</a>(); 00617 <font class="keywordtype">int</font> nXSize = poSrcDS-><a class="code" href="class_GDALDataset.html#a1">GetRasterXSize</a>(); 00618 <font class="keywordtype">int</font> nYSize = poSrcDS-><a class="code" href="class_GDALDataset.html#a2">GetRasterYSize</a>(); 00619 <font class="keywordtype">int</font> nQuality = 75; 00620 <font class="keywordtype">int</font> bProgressive = FALSE; 00621 00622 <font class="comment">/* -------------------------------------------------------------------- */</font> 00623 <font class="comment">/* Some some rudimentary checks */</font> 00624 <font class="comment">/* -------------------------------------------------------------------- */</font> 00625 <font class="keywordflow">if</font>( nBands != 1 && nBands != 3 ) 00626 { 00627 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_NotSupported, 00628 <font class="stringliteral">"JPEG driver doesn't support %d bands. Must be 1 (grey) "</font> 00629 <font class="stringliteral">"or 3 (RGB) bands.\n"</font>, nBands ); 00630 00631 <font class="keywordflow">return</font> NULL; 00632 } 00633 00634 <font class="keywordflow">if</font>( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict ) 00635 { 00636 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_NotSupported, 00637 <font class="stringliteral">"JPEG driver doesn't support data type %s. "</font> 00638 <font class="stringliteral">"Only eight bit byte bands supported.\n"</font>, 00639 GDALGetDataTypeName( 00640 poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); 00641 00642 <font class="keywordflow">return</font> NULL; 00643 } 00644 00645 <font class="comment">/* -------------------------------------------------------------------- */</font> 00646 <font class="comment">/* What options has the user selected? */</font> 00647 <font class="comment">/* -------------------------------------------------------------------- */</font> 00648 <font class="keywordflow">if</font>( CSLFetchNameValue(papszOptions,<font class="stringliteral">"QUALITY"</font>) != NULL ) 00649 { 00650 nQuality = atoi(CSLFetchNameValue(papszOptions,<font class="stringliteral">"QUALITY"</font>)); 00651 <font class="keywordflow">if</font>( nQuality < 10 || nQuality > 100 ) 00652 { 00653 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_IllegalArg, 00654 <font class="stringliteral">"QUALITY=%s is not a legal value in the range 10-100."</font>, 00655 CSLFetchNameValue(papszOptions,<font class="stringliteral">"QUALITY"</font>) ); 00656 <font class="keywordflow">return</font> NULL; 00657 } 00658 } 00659 00660 <font class="keywordflow">if</font>( CSLFetchNameValue(papszOptions,<font class="stringliteral">"PROGRESSIVE"</font>) != NULL ) 00661 { 00662 bProgressive = TRUE; 00663 } 00664 00665 <font class="comment">/* -------------------------------------------------------------------- */</font> 00666 <font class="comment">/* Create the dataset. */</font> 00667 <font class="comment">/* -------------------------------------------------------------------- */</font> 00668 FILE *fpImage; 00669 00670 fpImage = VSIFOpen( pszFilename, <font class="stringliteral">"wb"</font> ); 00671 <font class="keywordflow">if</font>( fpImage == NULL ) 00672 { 00673 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_OpenFailed, 00674 <font class="stringliteral">"Unable to create jpeg file %s.\n"</font>, 00675 pszFilename ); 00676 <font class="keywordflow">return</font> NULL; 00677 } 00678 00679 <font class="comment">/* -------------------------------------------------------------------- */</font> 00680 <font class="comment">/* Initialize JPG access to the file. */</font> 00681 <font class="comment">/* -------------------------------------------------------------------- */</font> 00682 <font class="keyword">struct </font>jpeg_compress_struct sCInfo; 00683 <font class="keyword">struct </font>jpeg_error_mgr sJErr; 00684 00685 sCInfo.err = jpeg_std_error( &sJErr ); 00686 jpeg_create_compress( &sCInfo ); 00687 00688 jpeg_stdio_dest( &sCInfo, fpImage ); 00689 00690 sCInfo.image_width = nXSize; 00691 sCInfo.image_height = nYSize; 00692 sCInfo.input_components = nBands; 00693 00694 <font class="keywordflow">if</font>( nBands == 1 ) 00695 { 00696 sCInfo.in_color_space = JCS_GRAYSCALE; 00697 } 00698 <font class="keywordflow">else</font> 00699 { 00700 sCInfo.in_color_space = JCS_RGB; 00701 } 00702 00703 jpeg_set_defaults( &sCInfo ); 00704 00705 jpeg_set_quality( &sCInfo, nQuality, TRUE ); 00706 00707 <font class="keywordflow">if</font>( bProgressive ) 00708 jpeg_simple_progression( &sCInfo ); 00709 00710 jpeg_start_compress( &sCInfo, TRUE ); 00711 00712 <font class="comment">/* -------------------------------------------------------------------- */</font> 00713 <font class="comment">/* Loop over image, copying image data. */</font> 00714 <font class="comment">/* -------------------------------------------------------------------- */</font> 00715 GByte *pabyScanline; 00716 CPLErr eErr; 00717 00718 pabyScanline = (GByte *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>( nBands * nXSize ); 00719 00720 <font class="keywordflow">for</font>( <font class="keywordtype">int</font> iLine = 0; iLine < nYSize; iLine++ ) 00721 { 00722 JSAMPLE *ppSamples; 00723 00724 <font class="keywordflow">for</font>( <font class="keywordtype">int</font> iBand = 0; iBand < nBands; iBand++ ) 00725 { 00726 <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a> * poBand = poSrcDS->GetRasterBand( iBand+1 ); 00727 eErr = poBand-><a class="code" href="class_GDALRasterBand.html#a8">RasterIO</a>( GF_Read, 0, iLine, nXSize, 1, 00728 pabyScanline + iBand, nXSize, 1, GDT_Byte, 00729 nBands, nBands * nXSize ); 00730 } 00731 00732 ppSamples = pabyScanline; 00733 jpeg_write_scanlines( &sCInfo, &ppSamples, 1 ); 00734 } 00735 00736 CPLFree( pabyScanline ); 00737 00738 jpeg_finish_compress( &sCInfo ); 00739 jpeg_destroy_compress( &sCInfo ); 00740 00741 VSIFClose( fpImage ); 00742 00743 <font class="keywordflow">return</font> (<a class="code" href="class_GDALDataset.html">GDALDataset</a> *) <a class="code" href="gdal_h.html#a60">GDALOpen</a>( pszFilename, GA_ReadOnly ); 00744 } 00745 \endverbatim 00746 00747 <h3>Dynamic Creation</h3> 00748 00749 In the <font class="keywordflow">case</font> of dynamic creation, there is no source dataset. Instead the 00750 size, number of bands, and pixel data type of the desired file is provided 00751 but other information (such as georeferencing, and imagery data) would be 00752 supplied later via other method calls on the resulting <a class="code" href="class_GDALDataset.html">GDALDataset</a>. 00753 00754 The following sample implement PCI .aux labelled raw raster creation. It 00755 follows a common approach of creating a blank, but valid file <font class="keyword">using</font> non-GDAL 00756 calls, and then calling <a class="code" href="gdal_h.html#a60">GDALOpen</a>(,GA_Update) at the end to <font class="keywordflow">return</font> a writable 00757 file handle. This avoids having to duplicate the various setup actions in 00758 the Open() function. 00759 00760 \verbatim 00761 <a class="code" href="class_GDALDataset.html">GDALDataset</a> *PAuxDataset::Create( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, 00762 <font class="keywordtype">int</font> nXSize, <font class="keywordtype">int</font> nYSize, <font class="keywordtype">int</font> nBands, 00763 GDALDataType eType, 00764 <font class="keywordtype">char</font> ** <font class="comment">/* papszParmList */</font> )<font class="keyword"></font> 00765 <font class="keyword"></font> 00766 <font class="keyword"></font>{ 00767 <font class="keywordtype">char</font> *pszAuxFilename; 00768 00769 <font class="comment">/* -------------------------------------------------------------------- */</font> 00770 <font class="comment">/* Verify input options. */</font> 00771 <font class="comment">/* -------------------------------------------------------------------- */</font> 00772 <font class="keywordflow">if</font>( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 00773 && eType != GDT_Int16 ) 00774 { 00775 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00776 <font class="stringliteral">"Attempt to create PCI .Aux labelled dataset with an illegal\n"</font> 00777 <font class="stringliteral">"data type (%s).\n"</font>, 00778 GDALGetDataTypeName(eType) ); 00779 00780 <font class="keywordflow">return</font> NULL; 00781 } 00782 00783 <font class="comment">/* -------------------------------------------------------------------- */</font> 00784 <font class="comment">/* Try to create the file. */</font> 00785 <font class="comment">/* -------------------------------------------------------------------- */</font> 00786 FILE *fp; 00787 00788 fp = VSIFOpen( pszFilename, <font class="stringliteral">"w"</font> ); 00789 00790 <font class="keywordflow">if</font>( fp == NULL ) 00791 { 00792 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_OpenFailed, 00793 <font class="stringliteral">"Attempt to create file `%s' failed.\n"</font>, 00794 pszFilename ); 00795 <font class="keywordflow">return</font> NULL; 00796 } 00797 00798 <font class="comment">/* -------------------------------------------------------------------- */</font> 00799 <font class="comment">/* Just write out a couple of bytes to establish the binary */</font> 00800 <font class="comment">/* file, and then close it. */</font> 00801 <font class="comment">/* -------------------------------------------------------------------- */</font> 00802 VSIFWrite( (<font class="keywordtype">void</font> *) <font class="stringliteral">"\0\0"</font>, 2, 1, fp ); 00803 VSIFClose( fp ); 00804 00805 <font class="comment">/* -------------------------------------------------------------------- */</font> 00806 <font class="comment">/* Create the aux filename. */</font> 00807 <font class="comment">/* -------------------------------------------------------------------- */</font> 00808 pszAuxFilename = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(strlen(pszFilename)+5); 00809 strcpy( pszAuxFilename, pszFilename );; 00810 00811 <font class="keywordflow">for</font>( <font class="keywordtype">int</font> i = strlen(pszAuxFilename)-1; i > 0; i-- ) 00812 { 00813 <font class="keywordflow">if</font>( pszAuxFilename[i] == <font class="charliteral">'.'</font> ) 00814 { 00815 pszAuxFilename[i] = <font class="charliteral">'\0'</font>; 00816 <font class="keywordflow">break</font>; 00817 } 00818 } 00819 00820 strcat( pszAuxFilename, <font class="stringliteral">".aux"</font> ); 00821 00822 <font class="comment">/* -------------------------------------------------------------------- */</font> 00823 <font class="comment">/* Open the file. */</font> 00824 <font class="comment">/* -------------------------------------------------------------------- */</font> 00825 fp = VSIFOpen( pszAuxFilename, <font class="stringliteral">"wt"</font> ); 00826 <font class="keywordflow">if</font>( fp == NULL ) 00827 { 00828 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_OpenFailed, 00829 <font class="stringliteral">"Attempt to create file `%s' failed.\n"</font>, 00830 pszAuxFilename ); 00831 <font class="keywordflow">return</font> NULL; 00832 } 00833 00834 <font class="comment">/* -------------------------------------------------------------------- */</font> 00835 <font class="comment">/* We need to write out the original filename but without any */</font> 00836 <font class="comment">/* path components in the AuxilaryTarget line. Do so now. */</font> 00837 <font class="comment">/* -------------------------------------------------------------------- */</font> 00838 <font class="keywordtype">int</font> iStart; 00839 00840 iStart = strlen(pszFilename)-1; 00841 <font class="keywordflow">while</font>( iStart > 0 && pszFilename[iStart-1] != <font class="charliteral">'/'</font> 00842 && pszFilename[iStart-1] != <font class="charliteral">'\\'</font> ) 00843 iStart--; 00844 00845 VSIFPrintf( fp, <font class="stringliteral">"AuxilaryTarget: %s\n"</font>, pszFilename + iStart ); 00846 00847 <font class="comment">/* -------------------------------------------------------------------- */</font> 00848 <font class="comment">/* Write out the raw definition for the dataset as a whole. */</font> 00849 <font class="comment">/* -------------------------------------------------------------------- */</font> 00850 VSIFPrintf( fp, <font class="stringliteral">"RawDefinition: %d %d %d\n"</font>, 00851 nXSize, nYSize, nBands ); 00852 00853 <font class="comment">/* -------------------------------------------------------------------- */</font> 00854 <font class="comment">/* Write out a definition for each band. We always write band */</font> 00855 <font class="comment">/* sequential files for now as these are pretty efficiently */</font> 00856 <font class="comment">/* handled by GDAL. */</font> 00857 <font class="comment">/* -------------------------------------------------------------------- */</font> 00858 <font class="keywordtype">int</font> nImgOffset = 0; 00859 00860 <font class="keywordflow">for</font>( <font class="keywordtype">int</font> iBand = 0; iBand < nBands; iBand++ ) 00861 { 00862 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszTypeName; 00863 <font class="keywordtype">int</font> nPixelOffset; 00864 <font class="keywordtype">int</font> nLineOffset; 00865 00866 nPixelOffset = GDALGetDataTypeSize(eType)/8; 00867 nLineOffset = nXSize * nPixelOffset; 00868 00869 <font class="keywordflow">if</font>( eType == GDT_Float32 ) 00870 pszTypeName = <font class="stringliteral">"32R"</font>; 00871 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( eType == GDT_Int16 ) 00872 pszTypeName = <font class="stringliteral">"16S"</font>; 00873 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( eType == GDT_UInt16 ) 00874 pszTypeName = <font class="stringliteral">"16U"</font>; 00875 <font class="keywordflow">else</font> 00876 pszTypeName = <font class="stringliteral">"8U"</font>; 00877 00878 VSIFPrintf( fp, <font class="stringliteral">"ChanDefinition-%d: %s %d %d %d %s\n"</font>, 00879 iBand+1, pszTypeName, 00880 nImgOffset, nPixelOffset, nLineOffset, 00881 #ifdef CPL_LSB 00882 <font class="stringliteral">"Swapped"</font> 00883 #<font class="keywordflow">else</font> 00884 <font class="stringliteral">"Unswapped"</font> 00885 #endif 00886 ); 00887 00888 nImgOffset += nYSize * nLineOffset; 00889 } 00890 00891 <font class="comment">/* -------------------------------------------------------------------- */</font> 00892 <font class="comment">/* Cleanup */</font> 00893 <font class="comment">/* -------------------------------------------------------------------- */</font> 00894 VSIFClose( fp ); 00895 00896 <font class="keywordflow">return</font> (<a class="code" href="class_GDALDataset.html">GDALDataset</a> *) <a class="code" href="gdal_h.html#a60">GDALOpen</a>( pszFilename, GA_Update ); 00897 } 00898 \endverbatim 00899 00900 File formats supporting dynamic creation, or even just update-in-place 00901 access also need to implement an IWriteBlock() method 00902 on the raster band <font class="keyword">class</font>. It has semantics similar to IReadBlock(). 00903 As well, <font class="keywordflow">for</font> various esoteric reasons, it is critical that a FlushCache() 00904 method be implemented in the raster band destructor. This is to ensure that 00905 any write cache blocks <font class="keywordflow">for</font> the band be flushed out before the destructor 00906 is called. 00907 00908 <h2><a name=<font class="stringliteral">"raw"</font>>RawDataset/RawRasterBand Helper Classes</a></h2> 00909 00910 Many file formats have the actual imagery data stored in a regular, 00911 binary, scanline oriented format. Rather than re-implement the access 00912 semantics <font class="keywordflow">for</font> <font class="keyword">this</font> <font class="keywordflow">for</font> each formats, there are provided RawDataset and 00913 RawRasterBand classes declared in gdal/frmts/raw that can be utilized to 00914 implement efficient and convenient access. 00915 00916 In these cases the format specific band <font class="keyword">class </font>may not be required, or if 00917 required it can be derived from RawRasterBand. The dataset class should 00918 be derived from RawDataset. 00919 00920 The Open() method for the dataset then instantiates raster bands passing 00921 all the layout information to the constructor. For instance, the PNM driver 00922 uses the following calls to create it's raster bands. 00923 00924 \code 00925 if( poOpenInfo->pabyHeader[1] == '5' ) 00926 { 00927 poDS->SetBand( 00928 1, <font class="keyword">new</font> RawRasterBand( poDS, 1, poDS->fpImage, 00929 iIn, 1, nWidth, GDT_Byte, TRUE )); 00930 } 00931 <font class="keywordflow">else</font> 00932 { 00933 poDS->SetBand( 00934 1, <font class="keyword">new</font> RawRasterBand( poDS, 1, poDS->fpImage, 00935 iIn, 3, nWidth*3, GDT_Byte, TRUE )); 00936 poDS->SetBand( 00937 2, <font class="keyword">new</font> RawRasterBand( poDS, 2, poDS->fpImage, 00938 iIn+1, 3, nWidth*3, GDT_Byte, TRUE )); 00939 poDS->SetBand( 00940 3, <font class="keyword">new</font> RawRasterBand( poDS, 3, poDS->fpImage, 00941 iIn+2, 3, nWidth*3, GDT_Byte, TRUE )); 00942 } 00943 \endcode 00944 00945 The RawRasterBand takes the following arguments. 00946 00947 <ul> 00948 <li> <b>poDS</b>: The <a class="code" href="class_GDALDataset.html">GDALDataset</a> <font class="keyword">this</font> band will be a child of. This 00949 dataset must be of a <font class="keyword">class </font>derived from RawRasterDataset. 00950 <li> <b>nBand</b>: The band it is on that dataset, 1 based. 00951 <li> <b>fpRaw</b>: The FILE * handle to the file containing the raster data. 00952 <li> <b>nImgOffset</b>: The byte offset to the first pixel of raster data for 00953 the first scanline. 00954 <li> <b>nPixelOffset</b>: The byte offset from the start of one pixel to the 00955 start of the next within the scanline. 00956 <li> <b>nLineOffset</b>: The byte offset from the start of one scanline to 00957 the start of the next. 00958 <li> <b>eDataType</b>: The GDALDataType code for the type of the data on disk. 00959 <li> <b>bNativeOrder</b>: FALSE if the data is not in the same endianness as 00960 the machine GDAL is running on. The data will be automatically byte swapped. 00961 </ul> 00962 00963 Simple file formats utilizing the Raw services are normally placed all within 00964 one file in the gdal/frmts/raw directory. There are numerous examples there 00965 of format implementation.<p> 00966 00967 <h2><a name="metadata">Metadata, and Other Exotic Extensions</a></h2> 00968 00969 There are various other items in the GDAL data model, for which <font class="keyword">virtual</font> 00970 methods exist on the <a class="code" href="class_GDALDataset.html">GDALDataset</a> and <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a>. They include: 00971 00972 <ul> 00973 <li> <b>Metadata</b>: Name/value text values about a dataset or band. The 00974 GDALMajorObject (base class for <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a> and <a class="code" href="class_GDALDataset.html">GDALDataset</a>) has builtin 00975 support for holding metadata, so for read access it only needs to be 00976 set with calls to SetMetadataItem() during the Open(). The SAR_CEOS 00977 (frmts/ceos2/sar_ceosdataset.cpp) and GeoTIFF drivers are examples of drivers 00978 implementing readable metadata. 00979 00980 <li> <b>ColorTables</b>: GDT_Byte raster bands can have color tables associated 00981 with them. The frmts/png/pngdataset.cpp driver contains an example of a 00982 format that supports colortables. 00983 00984 <li> <b>ColorInterpretation</b>: The PNG driver contains an example of a 00985 driver that returns an indication of whether a band should be treated as 00986 a Red, Green, Blue, Alpha or Greyscale band. 00987 00988 <li> <b>GCPs</b>: GDALDatasets can have a set of ground control points 00989 associated with them (as opposed to an explicit affine transform returned by 00990 GetGeotransform()) relating the raster to georeferenced coordinates. The 00991 MFF2 (gdal/frmts/raw/hkvdataset.cpp) format is a simple example of a format 00992 supporting GCPs. 00993 00994 <li> <b>NoDataValue</b>: Bands with known "nodata" values can implement 00995 the GetNoDataValue() method. See the PAux (frmts/raw/pauxdataset.cpp) for 00996 an example of this. 00997 00998 <li> <b>Category Names</b>: Classified images with names for each class can 00999 return them using the GetCategoryNames() method though no formats currently 01000 implement this. 01001 01002 </ul> 01003 01004 */ 01005 01006 01007 </div></pre><hr><address><small>Generated at Thu Mar 28 09:47:28 2002 for GDAL by <a href="http://www.stack.nl/~dimitri/doxygen/index.html"> <img src="doxygen.gif" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.3-20001105 written by <a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>, © 1997-2000</small></address> </body> </html>