public FileModel Demux(IImageWrapper source) { Pixel[,] dataSet = new Pixel[source.Width, source.Height]; for (var x = 0; x < source.Width; ++x) { for (var y = 0; y < source.Height; ++y) { Pixel p = new Pixel(); p.R = source.GetRedAtPosition(x, y); p.G = source.GetGreenAtPosition(x, y); p.B = source.GetBlueAtPosition(x, y); dataSet[x, y] = p; } } return(demuxxImage(dataSet)); }
private Pixel[,] muxxImageAndFile(FileModel fileModel, IImageWrapper container) { // warning, this is very verbose code. // i could have written this in linq much more elegantly, // however i wrote this so that others can pick it up without needing to know c# / linq / lambdas if (!this.encryptionFeasible(fileModel, container)) { throw new Exception("image is too small to hide this file in"); } int byteSpread = this.getByteSpread(); int bitShiftCount = (BITS_PER_CHANNEL - BITS_USED_PER_CHANNEL); int maxValue = (0x01 << BITS_PER_CHANNEL) - 0x01; int partMask = maxValue >> bitShiftCount; int visibleMask = (byte)(maxValue << (0x08 - bitShiftCount)); var header = new EncryptionHeader(); header.FileName = fileModel.FileName; header.FileSize = (int)fileModel.FileContents.Length; var headerBytesUnspread = header.ToBytes(); var fileBytesUnspread = new byte[fileModel.FileContents.Length]; fileModel.FileContents.Read(fileBytesUnspread, 0, (int)fileModel.FileContents.Length); var unspreadBytes = new byte[headerBytesUnspread.Length + fileBytesUnspread.Length]; var spreadBytes = new byte[unspreadBytes.Length * byteSpread]; int unspreadIndex = 0; for (var i = 0; i < headerBytesUnspread.Length; ++i) { unspreadBytes [unspreadIndex] = headerBytesUnspread [i]; ++unspreadIndex; } for (var i = 0; i < fileBytesUnspread.Length; ++i) { unspreadBytes [unspreadIndex] = fileBytesUnspread [i]; ++unspreadIndex; } int spreadIndex = 0; for (var i = 0; i < unspreadBytes.Length; ++i) { var toSpread = unspreadBytes [i]; for (var s = 0; s < byteSpread; ++s) // going least significant bit to most { var spreadShift = s * BITS_USED_PER_CHANNEL; var shifted = toSpread >> spreadShift; var masked = shifted & partMask; spreadBytes [spreadIndex] = (byte)masked; ++spreadIndex; } } // sanity check var maxSpreadValue = (0x01 << (BITS_USED_PER_CHANNEL)) - 1; for (var i = 0; i < spreadBytes.Length; ++i) { var sb = spreadBytes [i]; if (sb > maxSpreadValue) { throw new Exception("the author is a moron"); } } Pixel[,] dataSet = new Pixel[container.Width, container.Height]; var numberOfChannels = Enum.GetValues(typeof(LosslessFileMuxxer.ByteOrder)).GetLength(0); var channelIndex = 0; spreadIndex = 0; var rand = new Random(Guid.NewGuid().GetHashCode()); var randomiseNonDatasetBytes = false; for (var x = 0; x < container.Width; ++x) { for (var y = 0; y < container.Height; ++y) { Pixel p = new Pixel(); p.R = container.GetRedAtPosition(x, y); p.G = container.GetGreenAtPosition(x, y); p.B = container.GetBlueAtPosition(x, y); if (spreadIndex < spreadBytes.Length) { for (var c = 0; c < numberOfChannels; ++c) { if (spreadIndex < spreadBytes.Length) { var byteToHide = spreadBytes [spreadIndex]; var whichChannel = (ByteOrder)channelIndex; switch (whichChannel) { case ByteOrder.Red: p.R = (byte)(((int)p.R & visibleMask) + byteToHide); break; case ByteOrder.Green: p.G = (byte)(((int)p.G & visibleMask) + byteToHide); break; case ByteOrder.Blue: p.B = (byte)(((int)p.B & visibleMask) + byteToHide); break; } channelIndex = channelIndex == numberOfChannels - 1 ? 0 : channelIndex + 1; ++spreadIndex; } else { if (randomiseNonDatasetBytes) { // not a data pixel, give it a random value var newVal = rand.Next(0, maxSpreadValue); p.R = (byte)(((int)p.R & visibleMask) + newVal); newVal = rand.Next(0, maxSpreadValue); p.G = (byte)(((int)p.G & visibleMask) + newVal); newVal = rand.Next(0, maxSpreadValue); p.B = (byte)(((int)p.B & visibleMask) + newVal); } } } } else { if (randomiseNonDatasetBytes) { // not a data pixel, give it a random value var newVal = rand.Next(0, maxSpreadValue); p.R = (byte)(((int)p.R & visibleMask) + newVal); newVal = rand.Next(0, maxSpreadValue); p.G = (byte)(((int)p.G & visibleMask) + newVal); newVal = rand.Next(0, maxSpreadValue); p.B = (byte)(((int)p.B & visibleMask) + newVal); } } dataSet [x, y] = p; } } return(dataSet); }