Sophie

Sophie

distrib > Mandriva > 9.0 > i586 > by-pkgid > d67485fb8ce60f8952179bbde3b5d022 > files > 85

libgdal0-devel-1.1.7-2mdk.i586.rpm

<!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> &nbsp; <a class="qindex" href="hierarchy.html">Class Hierarchy</a> &nbsp; <a class="qindex" href="annotated.html">Compound List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; <a class="qindex" href="globals.html">File Members</a> &nbsp; <a class="qindex" href="pages.html">Related Pages</a> &nbsp; </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-&gt;fp == NULL || poOpenInfo-&gt;nHeaderBytes &lt; 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-&gt;pabyHeader+11,<font class="stringliteral">"19"</font>,2)
00082           &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+11,<font class="stringliteral">"20"</font>,2))
00083         || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+15,<font class="stringliteral">"19"</font>,2)
00084              &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+15,<font class="stringliteral">"20"</font>,2))
00085         || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+19,<font class="stringliteral">"19"</font>,2)
00086              &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;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-&gt;poDriver = poJDEMDriver;
00099     poDS-&gt;fp = poOpenInfo-&gt;fp;
00100     poOpenInfo-&gt;fp = NULL;
00101     
00102 <font class="comment">/* -------------------------------------------------------------------- */</font>
00103 <font class="comment">/*      Read the header.                                                */</font>
00104 <font class="comment">/* -------------------------------------------------------------------- */</font>
00105     VSIFSeek( poDS-&gt;fp, 0, SEEK_SET );
00106     VSIFRead( poDS-&gt;abyHeader, 1, 1012, poDS-&gt;fp );
00107 
00108     poDS-&gt;nRasterXSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS-&gt;abyHeader + 23, 3 );
00109     poDS-&gt;nRasterYSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS-&gt;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-&gt;nBands = 1;
00115     poDS-&gt;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 &lt;b&gt;bStatOK&lt;/b&gt; flag 
00148 will be set, and the &lt;b&gt;sStat&lt;/b&gt; 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 &lt;b&gt;fp&lt;/b&gt; 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 &lt;b&gt;pabyHeader&lt;/b&gt;, with the exact size in 
00154 &lt;b&gt;nHeaderBytes&lt;/b&gt;.
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 &lt;i&gt;magic&lt;/i&gt; 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-&gt;fp == NULL || poOpenInfo-&gt;nHeaderBytes &lt; 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-&gt;pabyHeader+11,<font class="stringliteral">"19"</font>,2)
00170           &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+11,<font class="stringliteral">"20"</font>,2))
00171         || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+15,<font class="stringliteral">"19"</font>,2)
00172              &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+15,<font class="stringliteral">"20"</font>,2))
00173         || (!EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;pabyHeader+19,<font class="stringliteral">"19"</font>,2)
00174              &amp;&amp; !EQUALN((<font class="keywordtype">char</font> *)poOpenInfo-&gt;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 &lt;i&gt;is <font class="keyword">this</font> my format&lt;/i&gt; 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-&gt;poDriver = poJDEMDriver;
00195     poDS-&gt;fp = poOpenInfo-&gt;fp;
00196     poOpenInfo-&gt;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 &lt;b&gt;assume ownership&lt;/b&gt; 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-&gt;fp, 0, SEEK_SET );
00213     VSIFRead( poDS-&gt;abyHeader, 1, 1012, poDS-&gt;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-&gt;nRasterXSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS-&gt;abyHeader + 23, 3 );
00222     poDS-&gt;nRasterYSize = JDEMGetField( (<font class="keywordtype">char</font> *) poDS-&gt;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-&gt;SetBand( 1, new JDEMRasterBand( poDS, 1 ));
00230 
00231     <font class="keywordflow">return</font>( poDS );
00232 \endcode
00233 
00234 &lt;h2&gt;&lt;a name=<font class="stringliteral">"rasterband"</font>&gt;Implementing the RasterBand&lt;/a&gt;&lt;/h2&gt;
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-&gt;poDS = poDS;
00261     this-&gt;nBand = nBand;
00262     
00263     eDataType = GDT_Float32;
00264 
00265     nBlockXSize = poDS-&gt;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 &lt;ul&gt;
00274 &lt;li&gt; &lt;b&gt;poDS&lt;/b&gt;: Pointer to the parent <a class="code" href="class_GDALDataset.html">GDALDataset</a>. 
00275 &lt;li&gt; &lt;b&gt;nBand&lt;/b&gt;: The band number within the dataset. 
00276 &lt;li&gt; &lt;b&gt;eDataType&lt;/b&gt;: The data type of pixels in <font class="keyword">this</font> band. 
00277 &lt;li&gt; &lt;b&gt;nBlockXSize&lt;/b&gt;: The width of one block in <font class="keyword">this</font> band. 
00278 &lt;li&gt; &lt;b&gt;nBlockYSize&lt;/b&gt;: The height of one block in <font class="keyword">this</font> band. 
00279 &lt;/ul&gt;
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 &lt;i&gt;natural&lt;/i&gt; 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-&gt;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-&gt;fp );
00304 
00305     <font class="keywordflow">if</font>( !EQUALN((<font class="keywordtype">char</font> *) poGDS-&gt;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 &lt; 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 &lt;ul&gt;
00335 &lt;li&gt; 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 &lt;li&gt; If an error occurs, report it with CPLError(), and return CE_Failure. 
00341 Otherwise return CE_None.  
00342 
00343 &lt;li&gt; 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 &lt;li&gt; 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 &lt;/ul&gt;
00353 
00354 &lt;h2&gt;&lt;a name="driver"&gt;The Driver&lt;/a&gt;&lt;/h2&gt;
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-&gt;pszShortName = <font class="stringliteral">"JDEM"</font>;
00380         poDriver-&gt;pszLongName = <font class="stringliteral">"Japanese DEM (.mem)"</font>;
00381         poDriver-&gt;pszHelpTopic = <font class="stringliteral">"frmt_various.html#JDEM"</font>;
00382         
00383         poDriver-&gt;pfnOpen = JDEMDataset::Open;
00384 
00385         GetGDALDriverManager()-&gt;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 &lt;ul&gt;
00396 &lt;li&gt; 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 &lt;li&gt; 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 &lt;li&gt; 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 &lt;li&gt; pfnOpen: The function to call to <font class="keywordflow">try</font> opening files of <font class="keyword">this</font> format. 
00408 (optional) 
00409 
00410 &lt;li&gt; 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 &lt;li&gt; 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 &lt;li&gt; pfnDelete: The function to call to <font class="keyword">delete</font> a dataset of <font class="keyword">this</font> format.
00417 (optional)
00418 
00419 &lt;/ul&gt;
00420 
00421 &lt;h2&gt;&lt;a name=<font class="stringliteral">"addingdriver"</font>&gt;Adding Driver to GDAL Tree&lt;/a&gt;&lt;/h2&gt;
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 &lt;ol&gt;
00428 &lt;li&gt; Add a driver directory under gdal/frmts, with the directory name the same
00429 as the pszShortName value. 
00430 
00431 &lt;li&gt; Add a GNUmakefile and makefile.vc in that directory modelled on those
00432 from other similar directories (ie. the jdem directory). 
00433 
00434 &lt;li&gt; Add the module with the dataset, and rasterband implementation.  
00435 Generally <font class="keyword">this</font> is called &lt;short_name&gt;dataset.cpp, with all the GDAL specifc
00436 code in one file, though that is not required.
00437 
00438 &lt;li&gt; Add the registration entry point declaration (ie. GDALRegister_JDEM()) to
00439 gdal/core/gdal_frmts.h.
00440 
00441 &lt;li&gt; Add a call to the registration function to frmts/gdalallregister.c,
00442 <font class="keyword">protected</font> by an appropriate #ifdef.  
00443 
00444 &lt;li&gt; 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 &lt;li&gt; Add a format specific item to the EXTRAFLAGS macro in frmts/makefile.vc. 
00448 &lt;/ol&gt;
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 &lt;h2&gt;&lt;a name=<font class="stringliteral">"georef"</font>&gt;Adding Georeferencing&lt;/a&gt;&lt;/h2&gt;
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> &lt;a href=<font class="stringliteral">"jdemdataset.cpp.html"</font>&gt;jdemdataset.cpp&lt;/a&gt; can be reviewed 
00521 as needed.
00522 
00523 &lt;h2&gt;&lt;a name=<font class="stringliteral">"overviews"</font>&gt;Overviews&lt;/a&gt;&lt;/h2&gt;
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-&gt;oOvManager.Initialize( poDS, poOpenInfo-&gt;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 &lt;h2&gt;&lt;a name=<font class="stringliteral">"creation"</font>&gt;File Creation&lt;/a&gt;&lt;/h2&gt;
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 &lt;h3&gt;CreateCopy&lt;/h3&gt;
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 &lt;ul&gt;
00587 &lt;li&gt; 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 &lt;li&gt; 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 &lt;li&gt; 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 &lt;li&gt; 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 &lt;/ul&gt;
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-&gt;<a class="code" href="class_GDALDataset.html#a3">GetRasterCount</a>();
00617     <font class="keywordtype">int</font>  nXSize = poSrcDS-&gt;<a class="code" href="class_GDALDataset.html#a1">GetRasterXSize</a>();
00618     <font class="keywordtype">int</font>  nYSize = poSrcDS-&gt;<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 &amp;&amp; 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-&gt;GetRasterBand(1)-&gt;GetRasterDataType() != GDT_Byte &amp;&amp; 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-&gt;GetRasterBand(1)-&gt;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 &lt; 10 || nQuality &gt; 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( &amp;sJErr );
00686     jpeg_create_compress( &amp;sCInfo );
00687     
00688     jpeg_stdio_dest( &amp;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( &amp;sCInfo );
00704     
00705     jpeg_set_quality( &amp;sCInfo, nQuality, TRUE );
00706 
00707     <font class="keywordflow">if</font>( bProgressive )
00708         jpeg_simple_progression( &amp;sCInfo );
00709 
00710     jpeg_start_compress( &amp;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 &lt; nYSize; iLine++ )
00721     {
00722         JSAMPLE      *ppSamples;
00723 
00724         <font class="keywordflow">for</font>( <font class="keywordtype">int</font> iBand = 0; iBand &lt; nBands; iBand++ )
00725         {
00726             <a class="code" href="class_GDALRasterBand.html">GDALRasterBand</a> * poBand = poSrcDS-&gt;GetRasterBand( iBand+1 );
00727             eErr = poBand-&gt;<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( &amp;sCInfo, &amp;ppSamples, 1 );
00734     }
00735 
00736     CPLFree( pabyScanline );
00737 
00738     jpeg_finish_compress( &amp;sCInfo );
00739     jpeg_destroy_compress( &amp;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 &lt;h3&gt;Dynamic Creation&lt;/h3&gt;
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 &amp;&amp; eType != GDT_Float32 &amp;&amp; eType != GDT_UInt16
00773         &amp;&amp; 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 &gt; 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 &gt; 0 &amp;&amp; pszFilename[iStart-1] != <font class="charliteral">'/'</font>
00842            &amp;&amp; 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 &lt; 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 &lt;h2&gt;&lt;a name=<font class="stringliteral">"raw"</font>&gt;RawDataset/RawRasterBand Helper Classes&lt;/a&gt;&lt;/h2&gt;
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-&gt;pabyHeader[1] == '5' )
00926     {
00927         poDS-&gt;SetBand( 
00928             1, <font class="keyword">new</font> RawRasterBand( poDS, 1, poDS-&gt;fpImage,
00929                                   iIn, 1, nWidth, GDT_Byte, TRUE ));
00930     }
00931     <font class="keywordflow">else</font> 
00932     {
00933         poDS-&gt;SetBand( 
00934             1, <font class="keyword">new</font> RawRasterBand( poDS, 1, poDS-&gt;fpImage,
00935                                   iIn, 3, nWidth*3, GDT_Byte, TRUE ));
00936         poDS-&gt;SetBand( 
00937             2, <font class="keyword">new</font> RawRasterBand( poDS, 2, poDS-&gt;fpImage,
00938                                   iIn+1, 3, nWidth*3, GDT_Byte, TRUE ));
00939         poDS-&gt;SetBand( 
00940             3, <font class="keyword">new</font> RawRasterBand( poDS, 3, poDS-&gt;fpImage,
00941                                   iIn+2, 3, nWidth*3, GDT_Byte, TRUE ));
00942     }
00943 \endcode
00944 
00945 The RawRasterBand takes the following arguments. 
00946 
00947 &lt;ul&gt;
00948 &lt;li&gt; &lt;b&gt;poDS&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;nBand&lt;/b&gt;: The band it is on that dataset, 1 based. 
00951 &lt;li&gt; &lt;b&gt;fpRaw&lt;/b&gt;: The FILE * handle to the file containing the raster data.
00952 &lt;li&gt; &lt;b&gt;nImgOffset&lt;/b&gt;: The byte offset to the first pixel of raster data for 
00953 the first scanline. 
00954 &lt;li&gt; &lt;b&gt;nPixelOffset&lt;/b&gt;: The byte offset from the start of one pixel to the 
00955 start of the next within the scanline. 
00956 &lt;li&gt; &lt;b&gt;nLineOffset&lt;/b&gt;: The byte offset from the start of one scanline to
00957 the start of the next. 
00958 &lt;li&gt; &lt;b&gt;eDataType&lt;/b&gt;: The GDALDataType code for the type of the data on disk.
00959 &lt;li&gt; &lt;b&gt;bNativeOrder&lt;/b&gt;: 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 &lt;/ul&gt;
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.&lt;p&gt;
00966 
00967 &lt;h2&gt;&lt;a name="metadata"&gt;Metadata, and Other Exotic Extensions&lt;/a&gt;&lt;/h2&gt;
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 &lt;ul&gt;
00973 &lt;li&gt; &lt;b&gt;Metadata&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;ColorTables&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;ColorInterpretation&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;GCPs&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;NoDataValue&lt;/b&gt;: 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 &lt;li&gt; &lt;b&gt;Category Names&lt;/b&gt;: Classified images with names for each class can
00999 return them using the GetCategoryNames() method though no formats currently
01000 implement this.
01001 
01002 &lt;/ul&gt; 
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>,
 &copy;&nbsp;1997-2000</small></address>
</body>
</html>