C#程序可将文本文件藏于位图中,也可导出
发布日期:2021-06-30 19:12:01
浏览次数:2
分类:技术文章
本文共 7281 字,大约阅读时间需要 24 分钟。
//使用方法: // BmpSafe.exe /file2bmp (input BMP) (input file to hide) [output file] //BmpSafe.exe /bmp2file (data BMP) [output file] using System; using System.IO; using System.Drawing; public class Bitmap24Writer { protected Bitmap bmp; protected int curX, curY, iRGB; protected uint bitsLeft, bitsTotal; protected byte r, g, b; public Bitmap24Writer(Bitmap bmp) { if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) throw new ArgumentException(); // assign vars curX = curY = iRGB = 0; this.bmp = bmp; bitsLeft = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3; } public uint GetUnusedBitCount() { return bitsLeft; } public uint GetMaxBitStorageCount() { return bitsTotal; } public Bitmap GetBitmap() { return bmp; } public bool WriteByte(byte by) { if (bitsLeft < 8) return false; uint bits2Do = 8; for (; curX < bmp.Width; curX++) { if (curY >= bmp.Height) curY = 0; for (; curY < bmp.Height; curY++) { if (bits2Do == 0) return true; Color col = bmp.GetPixel(curX, curY); r = col.R; g = col.G; b = col.B; for ( ; ; ) { byte curBit = (byte)(by & 1); switch( iRGB ) { case 0: r = (byte)(r & 0xFE); r |= curBit; break; case 1: g = (byte)(g & 0xFE); g |= curBit; break; case 2: b = (byte)(b & 0xFE); b |= curBit; break; } --bits2Do; --bitsLeft; by >>= 1; bmp.SetPixel(curX, curY, Color.FromArgb(r, g, b)); if (iRGB == 2) { iRGB = 0; break; } iRGB++; if (bits2Do == 0) return true; } } } return true; } } public class Bitmap24Reader { protected Bitmap bmp; protected int curX, curY, iRGB; protected uint bitsLeft, bitsTotal; public Bitmap24Reader(Bitmap bmp) { if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) throw new ArgumentException(); curX = curY = iRGB = 0; this.bmp = bmp; bitsLeft = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3; } public uint GetUnusedBitCount() { return bitsLeft; } public uint GetMaxBitStorageCount() { return bitsTotal; } public Bitmap GetBitmap() { return bmp; } public bool ReadByte(out byte by) { by = 0; if (bitsLeft < 8) return false; byte bit = 0; uint bits2Do = 8; for (; curX < bmp.Width; curX++) { if (curY >= bmp.Height) curY = 0; for (; curY < bmp.Height; curY++) { if (bits2Do == 0) return true; Color col = bmp.GetPixel(curX, curY); for ( ; ; ) { switch( iRGB ) { case 0: bit = (byte)(col.R & 1); break; case 1: bit = (byte)(col.G & 1); break; case 2: bit = (byte)(col.B & 1); break; } --bits2Do; --bitsLeft; by |= (byte)(bit << 7); if (bits2Do != 0) by >>= 1; if (iRGB == 2) { iRGB = 0; break; } iRGB++; if (bits2Do == 0) return true; } } } return true; } } public class BitmapWorks { public static bool Data2Bmp(FileStream dataStream, FileStream bmpStream, string outFName, out string error) { error = ""; Bitmap bmp; try { bmp = new Bitmap(bmpStream); } catch { error = "Are you sure the specified bitmap is a valid bitmap ?"; return false; } if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) { error = "Please drop only 24bit bitmaps,thanks !"; return false; } error += "-> Bitmap info: height=" + bmp.Height + " width=" + bmp.Width + ".../n"; if (dataStream.Length == 0) { error = "Input data has a not supported size of 0 !"; return false; } uint maxByteStorage = ((uint)bmp.Height * (uint)bmp.Width * 3) / 8; error += "-> Up to " + (maxByteStorage-4) + " bytes could be stored in this bitmap.../n"; if (maxByteStorage < dataStream.Length + 4) { error = "Not enough pixel in target bitmap to hide the input data block !"; return false; } Bitmap24Writer bmpWriter = new Bitmap24Writer(bmp); uint dataSize = (uint)dataStream.Length; try { for (uint u = 0; u < 4; u++) { bmpWriter.WriteByte( (byte)dataSize ); dataSize >>= 8; } for (uint u = 0; u < dataStream.Length; u++) bmpWriter.WriteByte( (byte)dataStream.ReadByte() ); } catch { error = "Error while modifing the bitmap's pixels !"; return false; } double maxBitStorage = bmpWriter.GetMaxBitStorageCount(); double spaceUsed = (100 * (maxBitStorage - bmpWriter.GetUnusedBitCount())) / maxBitStorage; error += "-> Space used: " + Convert.ToUInt32(spaceUsed) + "%.../n"; try { if ( File.Exists( outFName ) ) File.Delete( outFName ); bmpWriter.GetBitmap().Save(outFName); } catch { error = "Couldn't save output to " + outFName + " !"; return false; } error += "-> Output saved to: " + outFName + ".../n"; return true; } public static bool Bmp2Data(FileStream bmpStream, string outFName, out string error) { error = ""; Bitmap bmp; try { bmp = new Bitmap(bmpStream); } catch { error = "Are you sure the specified bitmap is a valid bitmap ?"; return false; } Bitmap24Reader bmpReader; try { bmpReader = new Bitmap24Reader(bmp); } catch (ArgumentException) { error = "This isn't a 24bit bitmap !"; return false; } FileStream outStream; try { outStream = File.Create( outFName ); } catch { error = "Couldn't create output file: " + outFName + " !"; return false; } uint dataSize = 0; byte outByte; try { for (uint u = 0; u < 4; u++) { if ( !bmpReader.ReadByte( out outByte ) ) throw new Exception(); dataSize |= (uint)( outByte << 8*3 ); if (u != 3) dataSize >>= 8; } error += "-> Size of hidden data: " + dataSize + " bytes.../n"; for (uint u = 0; u < dataSize; u++) { if ( !bmpReader.ReadByte( out outByte ) ) throw new Exception(); outStream.WriteByte( outByte ); } } catch { error = "Exception caught while reading the hidden data !"; return false; } finally { outStream.Close(); } error += "-> Output saved to: " + outFName + ".../n"; return true; } } class BmpSafe { public static string cmdLine = "Command line:/n" + " BmpSafe.exe /file2bmp (input BMP) (input file to hide) [output file]/n" + " BmpSafe.exe /bmp2file (data BMP) [output file]"; private static string serviceOne = "/file2bmp"; private static string serviceTwo = "/bmp2file"; [STAThread] static void Main(string[] args) { Console.WriteLine( "BmpSafe - hide files in 24bit bitmaps/n" + " a little steganografie implementation/n" + " by yoda/n" + "-------------------------------------------------------------------------------/n"); string inFile = "", inBmp, outFile; bool bFile2Bmp; if (args.Length < 2) { Console.WriteLine("!! Invalid number of arguments :("); Console.WriteLine(cmdLine); return; // ERR } if ( String.Compare(args[0], serviceOne, true) == 0 ) bFile2Bmp = true; else if ( String.Compare(args[0], serviceTwo, true) == 0) bFile2Bmp = false; else { Console.WriteLine("!! First parameters must be either /"/file2bmp/" or /"/bmp2file/" !"); return; } inBmp = args[1]; if (bFile2Bmp) { if (args.Length < 3) { Console.WriteLine("!! Invalid number of arguments :("); Console.WriteLine(cmdLine); return; } inFile = args[2]; if (args.Length > 3) outFile = args[3]; else outFile = "Secret.BMP"; } else { if (args.Length > 2) outFile = args[2]; else outFile = "Secret.bin"; } Console.WriteLine("-> Processing input..."); try { string err; bool ret; if (bFile2Bmp) ret = BitmapWorks.Data2Bmp( File.OpenRead(inFile), File.OpenRead(inBmp), outFile, out err ); else ret = BitmapWorks.Bmp2Data( File.OpenRead(inBmp), outFile, out err); if (!ret) { Console.WriteLine("!! " + err); return; } else Console.Write( err ); } catch(FileNotFoundException) { Console.WriteLine("!! At least one file could not be found :("); return; } catch { Console.WriteLine("!! An exception occurred :("); return; } Console.WriteLine("-> Job done..."); return; } }转载地址:https://linuxstyle.blog.csdn.net/article/details/1539931 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月26日 00时18分16秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
UIApplicationDelegate中几个常用的回调方法
2019-04-30
iOS开发遇到的问题
2019-04-30
Shell基本运算符
2019-04-30
Shell printf命令
2019-04-30
Shell流程控制
2019-04-30
Linux 命令大全
2019-04-30
Python的函数
2019-04-30
Python模块
2019-04-30
至联云讲解《下一代互联网是怎样的?》
2019-04-30
至联云讲解《比特币矿工要想参与IPFS/FIL挖矿需要做什么准备?》
2019-04-30
至联云讲解《FIL和BTC的区别是什么?》
2019-04-30
Filecoin主网离正式上线还有多远?go-filecoin、lotus已正式互通
2019-04-30
Filecoin周报-42:波卡/Opera/以太坊/互操作实现/大矿工奖励..
2019-04-30
IPFS周报-84期:最新路线图、以太坊大会、多方合作…IPFS Q1重大事件集锦
2019-04-30
Filecoin周报-43期:Filecoin官方屡提大矿工,测试目标重大转变
2019-04-30
IPFS周报-85期:IPFS发行网站改成什么样了?
2019-04-30
Filecoin周报-44:Filecoin火炎焱,本周戏码相当多
2019-04-30
IPFS周报-86期:IPFS移动版设计中,手机也可以接入啦!
2019-04-30
Filecoin周报-45:Filecoin网络关键性重置后,又发生了什么?
2019-04-30
Filecoin周报-47:v26发布,Filecoin第二阶段测试即将来袭!
2019-04-30