0

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";
HakuteiJ
  • 557
  • 4
  • 12
  • 1
    It will be very hard to help you without the relevant piece of code . – o_weisman Mar 22 '16 at 08:09
  • So, what is the question? Where your code goes wrong? Maybe at line x? Yes, that is probably the error. We can try to find x if you show us the code.. – TaW Mar 22 '16 at 09:38

1 Answers1

0

You don't provide enough information to reproduce the problem but if I had to guess I'd blame this line:

using (StreamReader reader = new StreamReader(zipInput))

zipInput is a Stream; an unbounded stream of arbitrary bytes. The StreamReader constructor without an encoding parameter assumes a stream of UTF8 bytes and I bet that's not what a GZipInputStream is. UTF8 enforces rules and if you don't follow the rules you get an exception.

So what should you do? That depends on what you pass to Decompress, what encoding it is in, and what you do with the result; and you haven't shown us any of those things. Find out the encoding of whatever is passed to Decompress and use that, or just use zipInput.Read and return the decompressed bytes, don't assume it is UTF8.

Dour High Arch
  • 21,513
  • 29
  • 75
  • 90