Problems Background
I'm currently working on a Universal Windows Platform application in C# using Visual Studio 2015. In the project, I'm using SharpZipLib.Portable to perform compression and decompression for a long string (get from EXIF) before embed the information into the image.
After that, I will retrieve the bits back from the LSB value of each pixel (8 bits) of image and do decompression to get the EXIF back. The process is as below:
String➡compression➡bits array of compression➡embed into image➡get back the bits array➡decompression➡original string
I'm testing using images with 440*440 and 256*256 dimension. My problem now is that when I do decompression, I cannot get the original string back and the decompression gives error:
For 440*440 image:
ICSharpCode.SharpZipLib.SharpZipBaseException was unhandled by user code
HResult=-2146233088
Message=Unexpected EOF
Source=ICSharpCode.SharpZipLib.Portable
StackTrace:
at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream.Fill()
at ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at ICSharpCode.SharpZipLib.GZip.GZipInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
at RenderImage.Services.GZipCompression.Decompress(Byte[] bytes)
at RenderImage.Services.Watermarking.Extracting(Byte[] pixelData, Int32 stringByteLength)
at RenderImage.ReadInfoFromImage.<Extract_Click>d__1.MoveNext()
InnerException:
For 256*256 image:
ICSharpCode.SharpZipLib.GZip.GZipException was unhandled by user code
HResult=-2146233088
Message=GZIP crc sum mismatch, theirs "-1895135477" and ours "-1621298539
Source=ICSharpCode.SharpZipLib.Portable
StackTrace:
at ICSharpCode.SharpZipLib.GZip.GZipInputStream.ReadFooter()
at ICSharpCode.SharpZipLib.GZip.GZipInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
at RenderImage.Services.GZipCompression.Decompress(Byte[] bytes)
at RenderImage.Services.Watermarking.Extracting(Byte[] pixelData, Int32 stringByteLength)
at RenderImage.ReadInfoFromImage.<Extract_Click>d__1.MoveNext()
InnerException:
Programme Code
Compression and Decompression
namespace RenderImage.Services
{
class GZipCompression
{
public static byte[] Compress(string text)
{
if (text == null)
return null;
using (Stream memOutput = new MemoryStream())
{
using (GZipOutputStream zipOut = new GZipOutputStream(memOutput))
{
using (StreamWriter writer = new StreamWriter(zipOut))
{
writer.Write(text);
writer.Flush();
zipOut.Finish();
byte[] bytes = new byte[memOutput.Length];
memOutput.Seek(0, SeekOrigin.Begin);
memOutput.Read(bytes, 0, bytes.Length);
return bytes;
}
}
}
}
public static string Decompress(byte[] bytes)
{
if (bytes == null)
return null;
using (Stream memInput = new MemoryStream(bytes))
using (GZipInputStream zipInput = new GZipInputStream(memInput))
using (StreamReader reader = new StreamReader(zipInput))
{
string text = reader.ReadToEnd();
return text;
}
}
}
}
Watermarking
namespace RenderImage.Services
{
class Watermarking
{
public static byte[] Embedding(byte[] pixelData, byte[] compressedString)
{
byte[] embedded = new byte[compressedString.Length * 8];
string[] binary = compressedString.Select(bytes => Convert.ToString(bytes, 2).PadLeft(8, '0')).ToArray();
for (int i = 0; i < compressedString.Length; i++)
{
int[] b = binary[i].Select(chars => Convert.ToInt32(chars)).ToArray();
int jump = i*8;
embedded[jump] = (b[0] == 49) ? (byte)1 : (byte)254;
embedded[jump+1] = (b[1] == 49) ? (byte)1 : (byte)254;
embedded[jump+2] = (b[2] == 49) ? (byte)1 : (byte)254;
embedded[jump+3] = (b[3] == 49) ? (byte)1 : (byte)254;
embedded[jump+4] = (b[4] == 49) ? (byte)1 : (byte)254;
embedded[jump+5] = (b[5] == 49) ? (byte)1 : (byte)254;
embedded[jump+6] = (b[6] == 49) ? (byte)1 : (byte)254;
embedded[jump+7] = (b[7] == 49) ? (byte)1 : (byte)254;
}
for (int counter = 0; counter < embedded.Length; counter++)
{
if (embedded[counter]==(byte)254)
{
pixelData[counter] &= embedded[counter];
}
else
{
pixelData[counter] |= embedded[counter];
}
}
return pixelData;
}
public static string Extracting(byte[] pixelData, int stringByteLength) //read until the last byte in the pixel data that contain the last bit of long string
{
byte[] extracted = new byte[stringByteLength]; //string array of the info that make up of 8 bits
byte embeddedBit = 1;
for (int i = 0; i < stringByteLength; i++)
{
int jump = i * 8;
extracted[i] = pixelData[jump];
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 1] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 2] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 3] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 4] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 5] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 6] & embeddedBit);
extracted[i] <<= 1;
extracted[i] |= (byte)(pixelData[jump + 7] & embeddedBit);
}
var decompressString = GZipCompression.Decompress(extracted);
return decompressString;
}
}
}
The string that I want to embed:
string patientInfo = "$ exiv2 -pt img_1771.jpg "+
"\nExif.Image.Make Ascii 6 Canon"+
"\nExif.Image.Model Ascii 20 Canon PowerShot S40"+
"\nExif.Image.Orientation Short 1 top, left"+
"\nExif.Image.XResolution Rational 1 180"+
"\nExif.Image.YResolution Rational 1 180"+
"\nExif.Image.ResolutionUnit Short 1 inch"+
"\nExif.Image.DateTime Ascii 20 2003:12:14 12:01:44"+
"\nExif.Image.YCbCrPositioning Short 1 Centered"+
"\nExif.Image.ExifTag Long 1 196"+
"\nExif.Photo.ExposureTime Rational 1 1 / 500 s"+
"\nExif.Photo.FNumber Rational 1 F4.9" +
"\nExif.Photo.ExifVersion Undefined 4 2.20" +
"\nExif.Photo.DateTimeOriginal Ascii 20 2003:12:14 12:01:44" +
"\nExif.Photo.DateTimeDigitized Ascii 20 2003:12:14 12:01:44" +
"\nExif.Photo.ComponentsConfiguration Undefined 4 YCbCr" +
"\nExif.Photo.CompressedBitsPerPixel Rational 1 5" +
"\nExif.Photo.ShutterSpeedValue SRational 1 1 / 501 s" +
"\nExif.Photo.ApertureValue Rational 1 F5" +
"\nExif.Photo.ExposureBiasValue SRational 1 0 EV" +
"\nExif.Photo.MaxApertureValue Rational 1 F2.8" +
"\nExif.Photo.MeteringMode Short 1 Center weighted average" +
"\nExif.Photo.Flash Short 1 No, auto" +
"\nExif.Photo.FocalLength Rational 1 21.3 mm" +
"\nExif.Photo.MakerNote Undefined 450(Binary value suppressed)" +
"\nExif.MakerNote.Offset Long 1 942" +
"\nExif.MakerNote.ByteOrder Ascii 3 II" +
"\nExif.CanonCs.Macro Short 1 Off" +
"\nExif.CanonCs.Selftimer Short 1 Off" +
"\nExif.CanonCs.Quality Short 1 Superfine" +
"\nExif.CanonCs.FlashMode Short 1 Auto" +
"\nExif.CanonCs.DriveMode Short 1 Single / timer" +
"\nExif.CanonCs.FocusMode Short 1 Single" +
"\nExif.CanonCs.ImageSize Short 1 Large" +
"\nExif.CanonCs.EasyMode Short 1 Manual" +
"\nExif.CanonCs.DigitalZoom Short 1 None" +
"\nExif.CanonCs.Contrast Short 1 Normal" +
"\nExif.CanonCs.Saturation Short 1 Normal" +
"\nExif.CanonCs.Sharpness Short 1 Normal" +
"\nExif.CanonCs.ISOSpeed Short 1 100" +
"\nExif.CanonCs.MeteringMode Short 1 Center weighted" +
"\nExif.CanonCs.FocusType Short 1 Auto" +
"\nExif.CanonCs.AFPoint Short 1 Center" +
"\nExif.CanonCs.ExposureProgram Short 1 Program(P)" +
"\nExif.CanonCs.LensType Short 1(65535)" +
"\nExif.CanonCs.Lens Short 3 7.1 - 21.3 mm" +
"\nExif.CanonCs.MaxAperture Short 1 F5" +
"\nExif.CanonCs.MinAperture Short 1 F8" +
"\nExif.CanonCs.FlashActivity Short 1 Did not fire" +
"\nExif.CanonCs.FlashDetails Short 1" +
"\nExif.CanonCs.FocusContinuous Short 1 Single" +
"\nExif.CanonCs.AESetting Short 1 Normal AE" +
"\nExif.CanonCs.ImageStabilization Short 1(65535)"+
"\nExif.CanonCs.DisplayAperture Short 1 49" +
"\nExif.CanonCs.ZoomSourceWidth Short 1 2272" +
"\nExif.CanonCs.ZoomTargetWidth Short 1 2272" +
"\nExif.CanonCs.SpotMeteringMode Short 1 AF Point" +
"\nExif.Canon.FocalLength Short 4 21.3 mm" +
"\nExif.CanonSi.ISOSpeed Short 1 100" +
"\nExif.CanonSi.MeasuredEV Short 1 13.63" +
"\nExif.CanonSi.TargetAperture Short 1 F5" +
"\nExif.CanonSi.TargetShutterSpeed Short 1 1 / 501 s" +
"\nExif.CanonSi.WhiteBalance Short 1 Auto" +
"\nExif.CanonSi.Sequence Short 1 0" +
"\nExif.CanonSi.AFPointUsed Short 1 3 focus points; center used" +
"\nExif.CanonSi.FlashBias Short 1 0 EV" +
"\nExif.CanonSi.SubjectDistance Short 1 782" +
"\nExif.CanonSi.ApertureValue Short 1 F5" +
"\nExif.CanonSi.ShutterSpeedValue Short 1 1 / 523 s" +
"\nExif.CanonSi.MeasuredEV2 Short 1 - 6.00" +
"\nExif.Canon.ImageType Ascii 32 IMG: PowerShot S40 JPEG" +
"\nExif.Canon.FirmwareVersion Ascii 24 Firmware Version 1.10" +
"\nExif.Canon.FileNumber Long 1 117 - 1771" +
"\nExif.Canon.OwnerName Ascii 32 Andreas Huggel" +
"\nExif.Canon.ModelID Long 1 PowerShot S40" +
"\nExif.Canon.CameraInfo Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0" +
"\nExif.Photo.UserComment Undefined 264(Binary value suppressed)" +
"\nExif.Photo.FlashpixVersion Undefined 4 1.00" +
"\nExif.Photo.ColorSpace Short 1 sRGB" +
"\nExif.Photo.PixelXDimension Short 1 2272" +
"\nExif.Photo.PixelYDimension Short 1 1704" +
"\nExif.Photo.InteroperabilityTag Long 1 1416" +
"\nExif.Iop.InteroperabilityIndex Ascii 4 R98" +
"\nExif.Iop.InteroperabilityVersion Undefined 4 1.00" +
"\nExif.Iop.RelatedImageWidth Short 1 2272" +
"\nExif.Iop.RelatedImageLength Short 1 1704" +
"\nExif.Photo.FocalPlaneXResolution Rational 1 8114.29" +
"\nExif.Photo.FocalPlaneYResolution Rational 1 8114.29" +
"\nExif.Photo.FocalPlaneResolutionUnit Short 1 inch" +
"\nExif.Photo.SensingMethod Short 1 One - chip color area" +
"\nExif.Photo.FileSource Undefined 1 Digital still camera" +
"\nExif.Photo.CustomRendered Short 1 Normal process" +
"\nExif.Photo.ExposureMode Short 1 Auto" +
"\nExif.Photo.WhiteBalance Short 1 Auto" +
"\nExif.Photo.DigitalZoomRatio Rational 1 1.0" +
"\nExif.Photo.SceneCaptureType Short 1 Standard" +
"\nExif.Thumbnail.Compression Short 1 JPEG(old - style)" +
"\nExif.Thumbnail.XResolution Rational 1 180" +
"\nExif.Thumbnail.YResolution Rational 1 180" +
"\nExif.Thumbnail.ResolutionUnit Short 1 inch"+
"\nExif.Thumbnail.JPEGInterchangeFormat Long 1 2036" +
"\nExif.Thumbnail.JPEGInterchangeFormatLength Long 1 5448";