Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for rotateimage.cs

(view source code of rotateimage.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7.  
  8.  
  9. namespace RobvanderWoude
  10. {
  11. 	class RotateImage
  12. 	{
  13. 		static string progver = "1.02";
  14.  
  15.  
  16. 		static int Main( string[] args )
  17. 		{
  18. 			#region Parse Command Line
  19.  
  20. 			if ( args.Length < 2 || args.Length > 4 )
  21. 			{
  22. 				return ShowHelp( );
  23. 			}
  24.  
  25. 			string imagepath = String.Empty;
  26. 			string outputfile = String.Empty;
  27. 			string fileextout = String.Empty;
  28. 			int maxwidth = 0;
  29. 			int maxheight = 0;
  30. 			int rotateby = 90;
  31.  
  32. 			foreach ( string arg in args )
  33. 			{
  34. 				if ( arg[0] == '/' )
  35. 				{
  36. 					if ( arg.Length > 3 && arg[2] == ':' )
  37. 					{
  38. 						switch ( arg.ToUpper( )[1] )
  39. 						{
  40. 							case 'M':
  41. 								if ( maxwidth != 0 )
  42. 								{
  43. 									return ShowHelp( "Duplicate command line switch /M" );
  44. 								}
  45. 								try
  46. 								{
  47. 									if ( arg.Substring( 3 ).ToLower( ).IndexOf( 'x' ) > 1 )
  48. 									{
  49. 										maxwidth = Convert.ToInt32( arg.Substring( 3, arg.ToLower( ).IndexOf( 'x' ) - 3 ) );
  50. 										maxheight = Convert.ToInt32( arg.Substring( arg.ToLower( ).IndexOf( 'x' ) + 1 ) );
  51. 									}
  52. 									else
  53. 									{
  54. 										maxwidth = Convert.ToInt32( arg.Substring( 3 ) );
  55. 										maxheight = maxwidth;
  56. 									}
  57. 								}
  58. 								catch
  59. 								{
  60. 									return ShowHelp( "size must be integer" );
  61. 								}
  62. 								if ( maxwidth < 50 || maxwidth > 10000 )
  63. 								{
  64. 									return ShowHelp( "size must be an integer between 50 and 10000" );
  65. 								}
  66. 								break;
  67. 							case 'R':
  68. 								if ( rotateby != 90 )
  69. 								{
  70. 									return ShowHelp( "Duplicate command line switch /R" );
  71. 								}
  72. 								try
  73. 								{
  74. 									rotateby = Convert.ToInt32( arg.Substring( 3 ) );
  75. 								}
  76. 								catch
  77. 								{
  78. 									return ShowHelp( "deg must be integer" );
  79. 								}
  80. 								if ( ( rotateby % 90 ) != 0 )
  81. 								{
  82. 									return ShowHelp( "deg must be a multiple of 90 degrees" );
  83. 								}
  84. 								break;
  85. 							default:
  86. 								return ShowHelp( "Invalid command line argument: \"{0}\"", arg );
  87. 						}
  88. 					}
  89. 					else
  90. 					{
  91. 						return ShowHelp( "Invalid command line argument: \"{0}\"", arg );
  92. 					}
  93. 				}
  94. 				else
  95. 				{
  96. 					if ( String.IsNullOrEmpty( imagepath ) )
  97. 					{
  98. 						imagepath = arg;
  99. 						if ( !File.Exists( imagepath ) )
  100. 						{
  101. 							return ShowHelp( "Image file not found: \"{0}\"", imagepath );
  102. 						}
  103. 					}
  104. 					else if ( String.IsNullOrEmpty( outputfile ) )
  105. 					{
  106. 						outputfile = arg;
  107. 						if ( !Directory.Exists( Directory.GetParent( outputfile ).FullName ) )
  108. 						{
  109. 							return ShowHelp( "Directory for output file not found: \"{0}\"", Directory.GetParent( outputfile ).FullName );
  110. 						}
  111. 						fileextout = Path.GetExtension( outputfile ).ToLower( );
  112. 					}
  113. 					else
  114. 					{
  115. 						return ShowHelp( "Invalid command line argument: \"{0}\"", arg );
  116. 					}
  117. 				}
  118. 			}
  119.  
  120. 			#endregion Parse Command Line
  121.  
  122. 			#region Validate Command Line
  123.  
  124. 			string fileextin = Path.GetExtension( imagepath ).ToLower( );
  125. 			if ( String.IsNullOrEmpty( fileextout ) )
  126. 			{
  127. 				fileextout = fileextin;
  128. 			}
  129. 			string filenamein = Path.GetFileNameWithoutExtension( imagepath );
  130. 			string parentfolderin = Directory.GetParent( imagepath ).FullName;
  131. 			if ( String.IsNullOrEmpty( outputfile ) )
  132. 			{
  133. 				outputfile = Path.Combine( parentfolderin, filenamein + "_rotated" + ( ( rotateby + 720 ) % 360 ).ToString( ) );
  134. 			}
  135. 			ImageFormat formatout;
  136. 			switch ( fileextout )
  137. 			{
  138. 				case ".bmp":
  139. 					formatout = ImageFormat.Bmp;
  140. 					break;
  141. 				case ".gif":
  142. 					formatout = ImageFormat.Gif;
  143. 					break;
  144. 				case ".jpg":
  145. 				case ".jpeg":
  146. 					formatout = ImageFormat.Jpeg;
  147. 					break;
  148. 				case ".png":
  149. 					formatout = ImageFormat.Png;
  150. 					break;
  151. 				case ".tif":
  152. 				case ".tiff":
  153. 					formatout = ImageFormat.Tiff;
  154. 					break;
  155. 				default:
  156. 					return -1;
  157. 			}
  158.  
  159. 			#endregion Validate Command Line
  160.  
  161. 			Bitmap bitmap = new Bitmap( imagepath );
  162. 			int imagewidth = bitmap.Width;
  163. 			int imageheight = bitmap.Height;
  164. 			int rc = imagewidth; // Return code = image width before rotation
  165. 			if ( maxwidth > 0 )
  166. 			{
  167. 				float aspectratio = (float) imagewidth / (float) imageheight;
  168. 				if ( imagewidth > maxwidth || imageheight > maxheight )
  169. 				{
  170. 					float scale = Math.Min( (float) maxwidth / (float) imagewidth, (float) maxheight / (float) imageheight );
  171. 					int newwidth = (int) ( (float) imagewidth * scale );
  172. 					int newheight = (int) ( (float) imageheight * scale );
  173. 					rc = newwidth;
  174. 					Bitmap resized = new Bitmap( newwidth, newheight ); // Return code = resized image width before rotation
  175. 					// Based on blog entry by DeltaWolf7
  176. 					// http://www.deltasblog.co.uk/code-snippets/c-resizing-a-bitmap-image/
  177. 					using ( Graphics graph = Graphics.FromImage( resized ) )
  178. 					{
  179. 						graph.DrawImage( bitmap, 0, 0, newwidth, newheight );
  180. 					}
  181. 					bitmap = resized;
  182. 				}
  183. 			}
  184. 			switch ( ( rotateby + 720 ) % 360 )
  185. 			{
  186. 				case 90:
  187. 					bitmap.RotateFlip( RotateFlipType.Rotate90FlipNone );
  188. 					break;
  189. 				case 180:
  190. 					bitmap.RotateFlip( RotateFlipType.Rotate180FlipNone );
  191. 					break;
  192. 				case 270:
  193. 					bitmap.RotateFlip( RotateFlipType.Rotate270FlipNone );
  194. 					break;
  195. 				default:
  196. 					// rotation 0 or invalid: do nothing
  197. 					break;
  198. 			}
  199.  
  200. 			bitmap.Save( outputfile, formatout );
  201.  
  202. 			return rc;
  203. 		}
  204.  
  205.  
  206. 		#region Error handling
  207.  
  208. 		public static int ShowHelp( params string[] errmsg )
  209. 		{
  210. 			#region Error Message
  211.  
  212. 			if ( errmsg.Length > 0 )
  213. 			{
  214. 				List<string> errargs = new List<string>( errmsg );
  215. 				errargs.RemoveAt( 0 );
  216. 				Console.Error.WriteLine( );
  217. 				Console.ForegroundColor = ConsoleColor.Red;
  218. 				Console.Error.Write( "ERROR:\t" );
  219. 				Console.ForegroundColor = ConsoleColor.White;
  220. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  221. 				Console.ResetColor( );
  222. 			}
  223.  
  224. 			#endregion Error Message
  225.  
  226. 			#region Help Text
  227.  
  228. 			/*
  229. 			RotateImage.exe,  Version 1.02
  230. 			Rotate a bitmap by a multiple of 90 degrees
  231.  
  232. 			Usage:   ROTATEIMAGE  image  [ output ]  [ options ]
  233.  
  234. 			Where:   image        input image file (bmp, gif, jpg, png or tif)
  235. 			         output       output file name and type (default: image_rotateddeg,
  236. 			                      same type as input image)
  237.  			
  238. 			Options: /M:size      Maximum dimension of rotated image in pixels, either as
  239. 			                      (original) width x (original) height (e.g. /M:1024x768)
  240. 			                      or as a single number for the largest dimension (e.g.
  241. 			                      /M:1024, equivalent to /M:1024x1024); if image does not
  242. 			                      fit within the specified dimensions, it will be resized
  243. 			                      while preserving its original aspect ratio
  244. 			         /R:deg       Rotation in degrees (90, 180 or 270)
  245.  
  246. 			Notes:   Unless an output file name is specified, the rotated output file name
  247. 			         is the input image file name with "_rotated" and the amount of degrees
  248. 			         appended, e.g. image_rotated90.gif; if no output file is specified,
  249. 			         the file types of input and output file are identical.
  250. 			         Return code ("errorlevel") equals the width of the (resized) output
  251. 			         image before rotation, or -1 in case of errors
  252.  
  253. 			Written by Rob van der Woude
  254. 			http://www.robvanderwoude.com
  255. 			*/
  256.  
  257. 			Console.Error.WriteLine( );
  258.  
  259. 			Console.Error.WriteLine( "RotateImage.exe,  Version {0}", progver );
  260.  
  261. 			Console.Error.WriteLine( "Rotate a bitmap by a multiple of 90 degrees" );
  262.  
  263. 			Console.Error.WriteLine( );
  264.  
  265. 			Console.Error.Write( "Usage:   " );
  266.  
  267. 			Console.ForegroundColor = ConsoleColor.White;
  268. 			Console.Error.WriteLine( "ROTATEIMAGE  image  [ output ]  [ options ]" );
  269. 			Console.ResetColor( );
  270.  
  271. 			Console.Error.WriteLine( );
  272.  
  273. 			Console.Error.Write( "Where:   " );
  274. 			Console.ForegroundColor = ConsoleColor.White;
  275. 			Console.Error.Write( "image" );
  276. 			Console.ResetColor( );
  277. 			Console.Error.WriteLine( "        input image file (bmp, gif, jpg, png or tif)" );
  278.  
  279. 			Console.ForegroundColor = ConsoleColor.White;
  280. 			Console.Error.Write( "         output" );
  281. 			Console.ResetColor( );
  282. 			Console.Error.Write( "       output file name and type (default: " );
  283. 			Console.ForegroundColor = ConsoleColor.White;
  284. 			Console.Error.Write( "image" );
  285. 			Console.ResetColor( );
  286. 			Console.Error.Write( "_rotated" );
  287. 			Console.ForegroundColor = ConsoleColor.White;
  288. 			Console.Error.Write( "deg" );
  289. 			Console.ResetColor( );
  290. 			Console.Error.WriteLine( ",)" );
  291.  
  292. 			Console.Error.WriteLine( "                      same type as input image)" );
  293.  
  294. 			Console.Error.WriteLine( );
  295.  
  296. 			Console.Error.Write( "Options: " );
  297. 			Console.ForegroundColor = ConsoleColor.White;
  298. 			Console.Error.Write( "/M:size      M" );
  299. 			Console.ResetColor( );
  300. 			Console.Error.WriteLine( "aximum dimension of rotated image in pixels, either as" );
  301.  
  302. 			Console.Error.Write( "                      (original) " );
  303. 			Console.ForegroundColor = ConsoleColor.White;
  304. 			Console.Error.Write( "width x" );
  305. 			Console.ResetColor( );
  306. 			Console.Error.Write( " (original) " );
  307. 			Console.ForegroundColor = ConsoleColor.White;
  308. 			Console.Error.Write( "height" );
  309. 			Console.ResetColor( );
  310. 			Console.Error.Write( " (e.g. " );
  311. 			Console.ForegroundColor = ConsoleColor.White;
  312. 			Console.Error.Write( "/M:1024x768" );
  313. 			Console.ResetColor( );
  314. 			Console.Error.WriteLine( ")" );
  315.  
  316. 			Console.Error.WriteLine( "                      or as a single number for the largest dimension (e.g." );
  317.  
  318. 			Console.ForegroundColor = ConsoleColor.White;
  319. 			Console.Error.Write( "                      /M:1024" );
  320. 			Console.ResetColor( );
  321. 			Console.Error.Write( ", equivalent to " );
  322. 			Console.ForegroundColor = ConsoleColor.White;
  323. 			Console.Error.Write( "/M:1024x1024" );
  324. 			Console.ResetColor( );
  325. 			Console.Error.WriteLine( "); if image does not" );
  326.  
  327. 			Console.Error.WriteLine( "                      fit within the specified dimensions, it will be resized" );
  328.  
  329. 			Console.Error.WriteLine( "                      while preserving its original aspect ratio" );
  330.  
  331. 			Console.ForegroundColor = ConsoleColor.White;
  332. 			Console.Error.Write( "         /R:deg       R" );
  333. 			Console.ResetColor( );
  334. 			Console.Error.Write( "otation in " );
  335. 			Console.ForegroundColor = ConsoleColor.White;
  336. 			Console.Error.Write( "deg" );
  337. 			Console.ResetColor( );
  338. 			Console.Error.WriteLine( "rees (90, 180 or 270; default: 0)" );
  339.  
  340. 			Console.Error.WriteLine( );
  341.  
  342. 			Console.Error.WriteLine( "Notes:   Unless an output file name is specified, the rotated output file name" );
  343.  
  344. 			Console.Error.WriteLine( "         is the input image file name with \"_rotated\" and the amount of degrees" );
  345.  
  346. 			Console.Error.Write( "         appended, e.g. " );
  347. 			Console.ForegroundColor = ConsoleColor.White;
  348. 			Console.Error.Write( "image" );
  349. 			Console.ResetColor( );
  350. 			Console.Error.Write( "_rotated" );
  351. 			Console.ForegroundColor = ConsoleColor.White;
  352. 			Console.Error.Write( "90" );
  353. 			Console.ResetColor( );
  354. 			Console.Error.WriteLine( ".gif; if no output file is specified," );
  355.  
  356. 			Console.Error.WriteLine( "         the file types of input and output file are identical." );
  357.  
  358. 			Console.Error.WriteLine( "         Return code (\"errorlevel\") equals the width of the (resized) output" );
  359.  
  360. 			Console.Error.WriteLine( "         image before rotation, or -1 in case of errors" );
  361.  
  362. 			Console.Error.WriteLine( );
  363.  
  364. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  365.  
  366. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  367.  
  368. 			#endregion Help Text
  369.  
  370. 			return -1;
  371. 		}
  372.  
  373. 		#endregion Error handling
  374. 	}
  375. }
  376.  

page last modified: 2024-04-16; loaded in 0.0083 seconds