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