Created
June 6, 2018 13:59
-
-
Save diamondo25/34234c06e4c0142184f87439a8df8ae9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Drawing; | |
using System.Drawing.Imaging; | |
using System.IO; | |
using System.Windows.Forms; | |
namespace qnd_png_conversion | |
{ | |
class Program | |
{ | |
[STAThread] | |
static void Main(string[] args) | |
{ | |
bool ui = false; | |
if (args.Length < 1) | |
{ | |
args = new string[1]; | |
var ofd = new OpenFileDialog(); | |
ofd.Filter = "PNG|*.png"; | |
if (ofd.ShowDialog() != DialogResult.OK) return; | |
args[0] = ofd.FileName; | |
ui = true; | |
} | |
if (args.Length < 2) | |
{ | |
Array.Resize(ref args, 2); | |
args[1] = Microsoft.VisualBasic.Interaction.InputBox("Format (argb4444 or rgb565)"); | |
ui = true; | |
} | |
var path = args[0]; | |
if (!File.Exists(path)) | |
{ | |
Console.WriteLine("File not found: {0}", path); | |
goto exit; | |
} | |
PixelFormat pf; | |
switch (args[1].ToLower()) | |
{ | |
case "r5g6b5": | |
case "rgb565": pf = PixelFormat.Format16bppRgb565; break; | |
case "a4r4g4b4": | |
case "argb4444": pf = PixelFormat.Format4bppIndexed; break; | |
default: | |
Console.WriteLine("Unknown format. {0}", args[1]); | |
goto exit; | |
} | |
try | |
{ | |
using (var bm = new Bitmap(path)) | |
{ | |
// _Nbpp == increments | |
// 256 to n bits | |
// 2 to 128 == 256 / 2 == 256 / ((1 << 2) - 1) | |
// 256 to 128 multiplier == x0.5 == 1 / (256 / 128) | |
// 128 to 256 multiplier == x2 = 1 / 1 / (256 / 128) | |
// 4 to 17 == 256 / 15 == 256 / ((1 << 4) - 1) | |
// 5 to 31 == 256 / 8 == 256 / ((1 << 5) - 1) | |
const double _4bpp_f = (256.0 / ((2 << 4 - 1) - 1)); | |
const double _5bpp_f = (256.0 / ((2 << 5 - 1) - 1)); | |
const double _6bpp_f = (256.0 / ((2 << 6 - 1) - 1)); | |
const byte _4bpp = (byte)_4bpp_f; | |
const byte _5bpp = (byte)_5bpp_f; | |
const byte _6bpp = (byte)_6bpp_f; | |
Bitmap nbm; | |
nbm = new Bitmap(bm.Width, bm.Height, PixelFormat.Format32bppArgb); | |
for (int x = 0; x < bm.Width; x++) | |
{ | |
for (int y = 0; y < bm.Height; y++) | |
{ | |
var color = bm.GetPixel(x, y); | |
int a, r, g, b; | |
if (pf == PixelFormat.Format16bppRgb565) | |
{ | |
a = 0xFF; | |
r = (byte)(Math.Round(color.R / _5bpp_f) * _5bpp); | |
g = (byte)(Math.Round(color.G / _6bpp_f) * _6bpp); | |
b = (byte)(Math.Round(color.B / _5bpp_f) * _5bpp); | |
Debug.Assert((r % _5bpp) == 0); | |
Debug.Assert((g % _6bpp) == 0); | |
Debug.Assert((b % _5bpp) == 0); | |
} | |
else if (pf == PixelFormat.Format4bppIndexed) | |
{ | |
a = (byte)(Math.Round(color.A / _4bpp_f) * _4bpp); | |
r = (byte)(Math.Round(color.R / _4bpp_f) * _4bpp); | |
g = (byte)(Math.Round(color.G / _4bpp_f) * _4bpp); | |
b = (byte)(Math.Round(color.B / _4bpp_f) * _4bpp); | |
Debug.Assert((a % _4bpp) == 0); | |
Debug.Assert((r % _4bpp) == 0); | |
Debug.Assert((g % _4bpp) == 0); | |
Debug.Assert((b % _4bpp) == 0); | |
} | |
else | |
{ | |
return; | |
} | |
nbm.SetPixel(x, y, Color.FromArgb(a, r, g, b)); | |
} | |
} | |
var pathWithoutExt = Path.GetFileNameWithoutExtension(path); | |
var newFile = Path.Combine(Path.GetDirectoryName(path), pathWithoutExt + "_converted.png"); | |
Console.WriteLine("Initial format: {0}", bm.PixelFormat); | |
Console.WriteLine("New format: {0}", nbm.PixelFormat); | |
Console.WriteLine("Output file: {0}", newFile); | |
nbm.Save(newFile, ImageFormat.Png); | |
} | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("exception!"); | |
Console.WriteLine(ex.ToString()); | |
goto exit; | |
} | |
if (!ui) return; | |
exit: | |
Console.WriteLine("Press any key to exit"); | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment