世界上的文字可以被四个字节完全覆盖,也就是UTF-32,其他都是变长的格式。而恰好ARGB加起来四个字节,于是完全可以把一个字符映射为一个像素点嘛!
并且图片上的字节可以再次加密,非常好玩!我仅演示的超级无敌简单的取反操作。
我自己习惯看方形的图片,于是开平方取整,如果字符数量不足就从字符本身随机取一段,这是为了图片尾部不会几个像素留白,炒鸡不美观,以白色(0xFFFFFFFF)作为终止字符。
static Bitmap ArgbTextEncode(string input)
{
var x = 0;
var y = 0;
var lenth = input.Length;
var yValue = (int)(Math.Sqrt(input.Length) + 1);
var fill = (yValue * yValue) % (Encoding.Unicode.GetByteCount(input) / 4);
input += input.Substring(Rnd.random.Next(input.Length - fill - 1), fill);
var image = new Bitmap(yValue, yValue);
//fill
for (int i = 0; i < yValue * yValue; i++)
{
if (i == lenth - 1)
{
image.SetPixel(x, y, Color.White);
}
else
{
byte[] bytes = Encoding.Unicode.GetBytes(input[i].ToString());
var prefix = 4 - bytes.Length;
bytes = Enumerable.Repeat<byte>(0, prefix).Concat(bytes).ToArray();
Encrypt(bytes);
image.SetPixel(x, y, Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]));
}
//Console.WriteLine("{0},{1} = {2}", x, y, input[i]);
x++;
if (x % yValue == 0)
{
x = 0;
y++;
}
}
return image;
}
找了一个日志文本,看看效果

解码函数
static string DecodeTextFromArgb(Bitmap image)
{
//ComplexImage comp = ComplexImage.FromBitmap(image);
//comp.BackwardFourierTransform();
var str = "";
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
var color = image.GetPixel(j, i);
if (color.A == 255 && color.R == 255 && color.G == 255 && color.B == 255)
return str;
var bytes = new byte[] { color.A, color.R, color.G, color.B };
Decrypt(bytes);
int skip = 0;
if (bytes[0] == 0)
{
if (bytes[1] == 0)
{
skip = 2;
}
else
{
skip = 1;
}
}
else
{
skip = 0;
}
var t = Encoding.Unicode.GetString(bytes.Skip(skip).ToArray());
//Console.WriteLine("{0},{1} = {2}", j, i, t);
str += t;
}
}
return str;
}
里面用到的Encrypt和Decrypt是取反的,不然图片一片漆黑,啥看不见。这句是我刚想到真的用取反操作符来,实际我是用的255去减的。
unchecked((byte)~(byte)value)
Encrypt和Decrypt,其实一样的。。哈哈
static byte[] Encrypt(byte[] values)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = (byte)(255 - values[i]);
}
return values;
}
static byte[] Decrypt(byte[] values)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = (byte)(255 - values[i]);
}
return values;
}
本程序完整代码如下:
class Program
{
static void Main(string[] args)
{
if (!args.Any())
{
return;
}
else if (args[0].EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
var textRaw = File.ReadAllText(args[0], Encoding.Unicode);
var image = ArgbTextEncode(textRaw);
var imagePath = Path.ChangeExtension(args[0], ".png");
image.Save(imagePath, ImageFormat.Png);
image.Dispose();
Console.WriteLine("TXT->PNG, " + imagePath);
try
{
Process.Start(imagePath);
}
catch
{
}
}
else if (args[0].EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
var image = (Bitmap)Bitmap.FromFile(args[0]);
string text = "";
try
{
text = DecodeTextFromArgb(image);
}
catch (Exception ex)
{
Console.WriteLine("PNG->TXT, 转换失败");
return;
}
var txtPath = Path.ChangeExtension(args[0], ".txt");
File.WriteAllText(txtPath, text, Encoding.Unicode);
Console.WriteLine("PNG->TXT, " + txtPath);
try
{
Process.Start(txtPath);
}
catch
{
}
}
else
{
Console.WriteLine("只支持TXT和PNG文件");
}
}
static Bitmap ArgbTextEncode(string input)
{
var x = 0;
var y = 0;
var lenth = input.Length;
var yValue = (int)(Math.Sqrt(input.Length) + 1);
var fill = (yValue * yValue) % (Encoding.Unicode.GetByteCount(input) / 4);
input += input.Substring(Rnd.random.Next(input.Length - fill - 1), fill);
var image = new Bitmap(yValue, yValue);
//fill
for (int i = 0; i < yValue * yValue; i++)
{
if (i == lenth - 1)
{
image.SetPixel(x, y, Color.White);
}
else
{
byte[] bytes = Encoding.Unicode.GetBytes(input[i].ToString());
var prefix = 4 - bytes.Length;
bytes = Enumerable.Repeat<byte>(0, prefix).Concat(bytes).ToArray();
Encrypt(bytes);
image.SetPixel(x, y, Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]));
}
//Console.WriteLine("{0},{1} = {2}", x, y, input[i]);
x++;
if (x % yValue == 0)
{
x = 0;
y++;
}
}
return image;
}
static byte[] Encrypt(byte[] values)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = (byte)(255 - values[i]);
}
return values;
}
static byte[] Decrypt(byte[] values)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = (byte)(255 - values[i]);
}
return values;
}
static string DecodeTextFromArgb(Bitmap image)
{
//ComplexImage comp = ComplexImage.FromBitmap(image);
//comp.BackwardFourierTransform();
var str = "";
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
var color = image.GetPixel(j, i);
if (color.A == 255 && color.R == 255 && color.G == 255 && color.B == 255)
return str;
var bytes = new byte[] { color.A, color.R, color.G, color.B };
Decrypt(bytes);
int skip = 0;
if (bytes[0] == 0)
{
if (bytes[1] == 0)
{
skip = 2;
}
else
{
skip = 1;
}
}
else
{
skip = 0;
}
var t = Encoding.Unicode.GetString(bytes.Skip(skip).ToArray());
//Console.WriteLine("{0},{1} = {2}", j, i, t);
str += t;
}
}
return str;
}
}
源码地址:https://gitee.com/kstudio/ArgbText