1 /******************************************************************************
2  * $Id: GDALReadDirect.cs 13437 2007-12-21 21:02:38Z tamas $
3  *
4  * Name:     GDALDatasetRasterIO.cs
5  * Project:  GDAL CSharp Interface
6  * Purpose:  A sample app to read GDAL raster data directly to a C# bitmap.
7  * Author:   Tamas Szekeres, szekerest@gmail.com
8  *
9  ******************************************************************************
10  * Copyright (c) 2007, Tamas Szekeres
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  *****************************************************************************/
30 
31 using System;
32 using System.Drawing;
33 using System.Drawing.Imaging;
34 
35 using OSGeo.GDAL;
36 
37 
38 /**
39 
40  * <p>Title: GDAL C# GDALDatasetRasterIO example.</p>
41  * <p>Description: A sample app to read GDAL raster data directly to a C# bitmap.</p>
42  * @author Tamas Szekeres (szekerest@gmail.com)
43  * @version 1.0
44  */
45 
46 
47 
48 /// <summary>
49 /// A C# based sample to read GDAL raster data directly to a C# bitmap.
50 /// </summary>
51 
52 class GDALReadDirect {
53 
usage()54 	public static void usage()
55 
56 	{
57         Console.WriteLine("usage: GDALDatasetRasterIO {GDAL dataset name} {output file name}");
58 		System.Environment.Exit(-1);
59 	}
60 
Main(string[] args)61     public static void Main(string[] args)
62     {
63         if (args.Length < 2) usage();
64 
65         // Using early initialization of System.Console
66         Console.WriteLine("");
67 
68         try
69         {
70             /* -------------------------------------------------------------------- */
71             /*      Register driver(s).                                             */
72             /* -------------------------------------------------------------------- */
73             Gdal.AllRegister();
74 
75             /* -------------------------------------------------------------------- */
76             /*      Open dataset.                                                   */
77             /* -------------------------------------------------------------------- */
78             Dataset ds = Gdal.Open( args[0], Access.GA_ReadOnly );
79 
80             if (ds == null)
81             {
82                 Console.WriteLine("Can't open " + args[0]);
83                 System.Environment.Exit(-1);
84             }
85 
86             Console.WriteLine("Raster dataset parameters:");
87             Console.WriteLine("  Projection: " + ds.GetProjectionRef());
88             Console.WriteLine("  RasterCount: " + ds.RasterCount);
89             Console.WriteLine("  RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")");
90 
91             /* -------------------------------------------------------------------- */
92             /*      Get driver                                                      */
93             /* -------------------------------------------------------------------- */
94             Driver drv = ds.GetDriver();
95 
96             if (drv == null)
97             {
98                 Console.WriteLine("Can't get driver.");
99                 System.Environment.Exit(-1);
100             }
101 
102             Console.WriteLine("Using driver " + drv.LongName);
103 
104             /* -------------------------------------------------------------------- */
105             /*      Processing the raster                                           */
106             /* -------------------------------------------------------------------- */
107             SaveBitmapDirect(args[1], ds, 0, 0, ds.RasterXSize, ds.RasterYSize, ds.RasterXSize, ds.RasterYSize);
108 
109         }
110         catch (Exception e)
111         {
112             Console.WriteLine("Application error: " + e.Message);
113         }
114     }
115 
SaveBitmapDirect(string filename, Dataset ds, int xOff, int yOff, int width, int height, int imageWidth, int imageHeight)116     private static void SaveBitmapDirect(string filename, Dataset ds, int xOff, int yOff, int width, int height, int imageWidth, int imageHeight)
117     {
118         if (ds.RasterCount == 0)
119             return;
120 
121         int[] bandMap = new int[4] { 1, 1, 1, 1 };
122         int channelCount = 1;
123         bool hasAlpha = false;
124         bool isIndexed = false;
125         int channelSize = 8;
126         ColorTable ct = null;
127         // Evaluate the bands and find out a proper image transfer format
128         for (int i = 0; i < ds.RasterCount; i++)
129         {
130             Band band = ds.GetRasterBand(i + 1);
131             if (Gdal.GetDataTypeSize(band.DataType) > 8)
132                 channelSize = 16;
133             switch (band.GetRasterColorInterpretation())
134             {
135                 case ColorInterp.GCI_AlphaBand:
136                     channelCount = 4;
137                     hasAlpha = true;
138                     bandMap[3] = i + 1;
139                     break;
140                 case ColorInterp.GCI_BlueBand:
141                     if (channelCount < 3)
142                         channelCount = 3;
143                     bandMap[0] = i + 1;
144                     break;
145                 case ColorInterp.GCI_RedBand:
146                     if (channelCount < 3)
147                         channelCount = 3;
148                     bandMap[2] = i + 1;
149                     break;
150                 case ColorInterp.GCI_GreenBand:
151                     if (channelCount < 3)
152                         channelCount = 3;
153                     bandMap[1] = i + 1;
154                     break;
155                 case ColorInterp.GCI_PaletteIndex:
156                     ct = band.GetRasterColorTable();
157                     isIndexed = true;
158                     bandMap[0] = i + 1;
159                     break;
160                 case ColorInterp.GCI_GrayIndex:
161                     isIndexed = true;
162                     bandMap[0] = i + 1;
163                     break;
164                 default:
165                     // we create the bandmap using the dataset ordering by default
166                     if (i < 4 && bandMap[i] == 0)
167                     {
168                         if (channelCount < i)
169                             channelCount = i;
170                         bandMap[i] = i + 1;
171                     }
172                     break;
173             }
174         }
175 
176         // find out the pixel format based on the gathered information
177         PixelFormat pixelFormat;
178         DataType dataType;
179         int pixelSpace;
180 
181         if (isIndexed)
182         {
183             pixelFormat = PixelFormat.Format8bppIndexed;
184             dataType = DataType.GDT_Byte;
185             pixelSpace = 1;
186         }
187         else
188         {
189             if (channelCount == 1)
190             {
191                 if (channelSize > 8)
192                 {
193                     pixelFormat = PixelFormat.Format16bppGrayScale;
194                     dataType = DataType.GDT_Int16;
195                     pixelSpace = 2;
196                 }
197                 else
198                 {
199                     pixelFormat = PixelFormat.Format24bppRgb;
200                     channelCount = 3;
201                     dataType = DataType.GDT_Byte;
202                     pixelSpace = 3;
203                 }
204             }
205             else
206             {
207                 if (hasAlpha)
208                 {
209                     if (channelSize > 8)
210                     {
211                         pixelFormat = PixelFormat.Format64bppArgb;
212                         dataType = DataType.GDT_UInt16;
213                         pixelSpace = 8;
214                     }
215                     else
216                     {
217                         pixelFormat = PixelFormat.Format32bppArgb;
218                         dataType = DataType.GDT_Byte;
219                         pixelSpace = 4;
220                     }
221                     channelCount = 4;
222                 }
223                 else
224                 {
225                     if (channelSize > 8)
226                     {
227                         pixelFormat = PixelFormat.Format48bppRgb;
228                         dataType = DataType.GDT_UInt16;
229                         pixelSpace = 6;
230                     }
231                     else
232                     {
233                         pixelFormat = PixelFormat.Format24bppRgb;
234                         dataType = DataType.GDT_Byte;
235                         pixelSpace = 3;
236                     }
237                     channelCount = 3;
238                 }
239             }
240         }
241 
242 
243         // Create a Bitmap to store the GDAL image in
244         Bitmap bitmap = new Bitmap(imageWidth, imageHeight, pixelFormat);
245 
246         if (isIndexed)
247         {
248             // setting up the color table
249             if (ct != null)
250             {
251                 int iCol = ct.GetCount();
252                 ColorPalette pal = bitmap.Palette;
253                 for (int i = 0; i < iCol; i++)
254                 {
255                     ColorEntry ce = ct.GetColorEntry(i);
256                     pal.Entries[i] = Color.FromArgb(ce.c4, ce.c1, ce.c2, ce.c3);
257                 }
258                 bitmap.Palette = pal;
259             }
260             else
261             {
262                 // grayscale
263                 ColorPalette pal = bitmap.Palette;
264                 for (int i = 0; i < 256; i++)
265                     pal.Entries[i] = Color.FromArgb(255, i, i, i);
266                 bitmap.Palette = pal;
267             }
268         }
269 
270         // Use GDAL raster reading methods to read the image data directly into the Bitmap
271         BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.ReadWrite, pixelFormat);
272 
273         try
274         {
275             int stride = bitmapData.Stride;
276             IntPtr buf = bitmapData.Scan0;
277 
278             ds.ReadRaster(xOff, yOff, width, height, buf, imageWidth, imageHeight, dataType,
279                 channelCount, bandMap, pixelSpace, stride, 1);
280         }
281         finally
282         {
283             bitmap.UnlockBits(bitmapData);
284         }
285 
286         bitmap.Save(filename);
287     }
288 }