This project has moved. For the latest updates, please go here.

Tiff corrupted using buffered memory transfer

Oct 17, 2016 at 11:03 PM
I am using the example code and the tiffs sent back are corrupted. With a disk file transfer everything works, but not when I try to switch to memory transfer.
private void Twain_MemXferEvent(object sender, Twain32.MemXferEventArgs e)
        {
            try
            {
                if (TiffMemXfer.Current != null)
                {
                    long _bitsPerRow = e.ImageInfo.BitsPerPixel * e.ImageMemXfer.Columns;
                    long _bytesPerRow = Math.Min(e.ImageMemXfer.BytesPerRow, (_bitsPerRow >> 3) + ((_bitsPerRow & 0x07) != 0 ? 1 : 0));
                    using (MemoryStream _stream = new MemoryStream())
                    {
                        for (int i = 0; i < e.ImageMemXfer.Rows; i++)
                        {
                            _stream.Position = 0;
                            _stream.Write(e.ImageMemXfer.ImageData, (int)(e.ImageMemXfer.BytesPerRow * i), (int)_bytesPerRow);
                            TiffMemXfer.Current.Strips.Add(TiffMemXfer.Current.Writer.WriteData(_stream.ToArray()));
                            TiffMemXfer.Current.StripByteCounts.Add((uint)_stream.Length);
                        }
                    }
                }
                else
                {
                    MemFileXfer.Current.Writer.Write(e.ImageMemXfer.ImageData);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("{0}: {1}\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace));
            }
        }

        private void Twain_SetupMemXferEvent(object sender, Twain32.SetupMemXferEventArgs e)
        {
            try
            {
                if (this._twain.Capabilities.XferMech.GetCurrent() == TwSetupTransfer.Memory)
                {
                    if (TiffMemXfer.Current == null)
                    {
                        TiffMemXfer.Create((int)e.BufferSize);
                    }

                    #region Color Map

                    if (e.ImageInfo.PixelType == TwPixelType.Palette)
                    {
                        Twain32.ColorPalette _palette = this._twain.Palette.Get();
                        TiffMemXfer.Current.ColorMap = new ushort[_palette.Colors.Length * 3];
                        for (int i = 0; i < _palette.Colors.Length; i++)
                        {
                            TiffMemXfer.Current.ColorMap[i] = (ushort)(_palette.Colors[i].R);
                            TiffMemXfer.Current.ColorMap[i + _palette.Colors.Length] = (ushort)(_palette.Colors[i].G);
                            TiffMemXfer.Current.ColorMap[i + (_palette.Colors.Length << 1)] = (ushort)(_palette.Colors[i].B);
                        }
                    }

                    #endregion

                }
                else
                { // MemFile
                    MemFileXfer.Create((int)e.BufferSize, this._twain.Capabilities.ImageFileFormat.GetCurrent().ToString().ToLower());
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("{0}: {1}\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace));
            }
        }

        private void Twain_XferDone(object sender, Twain32.XferDoneEventArgs e)
        {
            if (TiffMemXfer.Current != null && TiffMemXfer.Current.Writer != null)
            {
                Twain32.ImageInfo _info = e.GetImageInfo();
                Collection<ITag> _tags = new Collection<ITag> {
                        Tag<uint>.Create(TiffTags.ImageWidth,(uint)_info.ImageWidth),
                        Tag<uint>.Create(TiffTags.ImageLength,(uint)_info.ImageLength),
                        Tag<ushort>.Create(TiffTags.SamplesPerPixel,(ushort)_info.BitsPerSample.Length),
                        Tag<ushort>.Create(TiffTags.BitsPerSample,new Func<short[],ushort[]>(val=>{
                            ushort[] _result=new ushort[_info.BitsPerSample.Length];
                            for(int i=0; i<_result.Length; i++) {
                                _result[i]=(ushort)_info.BitsPerSample[i];
                            }
                            return _result;
                        })(_info.BitsPerSample)),
                        Tag<ushort>.Create(TiffTags.Orientation,(ushort)TiffOrientation.TOPLEFT),
                        Tag<TiffCompression>.Create(TiffTags.Compression,TiffCompression.NONE),
                        Tag<TiffResolutionUnit>.Create(TiffTags.ResolutionUnit,new Func<TwUnits,TiffResolutionUnit>(val=>{
                            switch(val){
                                case TwUnits.Centimeters:
                                    return TiffResolutionUnit.CENTIMETER;
                                case TwUnits.Inches:
                                    return TiffResolutionUnit.INCH;
                                default:
                                    return TiffResolutionUnit.NONE;
                            }
                        })(this._twain.Capabilities.Units.GetCurrent())),
                        Tag<ulong>.Create(TiffTags.XResolution,(1UL<<32)|(ulong)_info.XResolution),
                        Tag<ulong>.Create(TiffTags.YResolution,(1UL<<32)|(ulong)_info.YResolution),
                        Tag<TiffHandle>.Create(TiffTags.StripOffsets,TiffMemXfer.Current.Strips.ToArray()),
                        Tag<uint>.Create(TiffTags.StripByteCounts,TiffMemXfer.Current.StripByteCounts.ToArray()),
                        Tag<uint>.Create(TiffTags.RowsPerStrip,1u),
                        //Tag<char>.Create(TiffTags.Software, Application.ProductName.ToCharArray()),
                        Tag<char>.Create(TiffTags.Model,this._twain.GetSourceProductName(this._twain.SourceIndex).ToCharArray()),
                        Tag<char>.Create(TiffTags.DateTime,DateTime.Now.ToString("yyyy:MM:dd HH:mm:ss").PadRight(20,'\0').ToCharArray()),
                        Tag<char>.Create(TiffTags.HostComputer,Environment.MachineName.ToCharArray()),
                        Tag<ushort>.Create(TiffTags.PlanarConfiguration,(ushort)TiffPlanarConfig.CONTIG),
                        Tag<char>.Create(TiffTags.Copyright,((AssemblyCopyrightAttribute)this.GetType().Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute),false)[0]).Copyright.ToCharArray())
                    };
                switch (_info.PixelType)
                {
                    case TwPixelType.BW:
                        _tags.Add(Tag<TiffPhotoMetric>.Create(TiffTags.PhotometricInterpretation, TiffPhotoMetric.BlackIsZero));
                        break;
                    case TwPixelType.Gray:
                        _tags.Add(Tag<TiffPhotoMetric>.Create(TiffTags.PhotometricInterpretation, TiffPhotoMetric.BlackIsZero));
                        break;
                    case TwPixelType.Palette:
                        _tags.Add(Tag<TiffPhotoMetric>.Create(TiffTags.PhotometricInterpretation, TiffPhotoMetric.Palette));
                        _tags.Add(Tag<ushort>.Create(TiffTags.ColorMap, TiffMemXfer.Current.ColorMap));
                        break;
                    case TwPixelType.RGB:
                        _tags.Add(Tag<TiffPhotoMetric>.Create(TiffTags.PhotometricInterpretation, TiffPhotoMetric.RGB));
                        break;
                    default:
                        break;
                }
                TiffMemXfer.Current.Handle = TiffMemXfer.Current.Writer.WriteImageFileDirectory(TiffMemXfer.Current.Handle, _tags);
                TiffMemXfer.Current.Strips.Clear();
                TiffMemXfer.Current.StripByteCounts.Clear();
            }
        }

        private void Twain_AcquireCompleted(object sender, EventArgs e)
        {
            if (this._twain.ImageCount > 0)
            {
                this.CurrentBitmap = this._twain.GetImage(0) as Bitmap;
            }

            if (TiffMemXfer.Current != null)
            {
                try
                {
                    TiffMemXfer.Current.Writer.BaseStream.Seek(0, SeekOrigin.Begin);
                    this.CurrentBitmap = Image.FromStream(TiffMemXfer.Current.Writer.BaseStream) as Bitmap;
                }
                finally
                {
                    TiffMemXfer.Dispose();
                }
            }

            FinalizeScan();            
        }

        private void Twain_AcquireError(object sender, Twain32.AcquireErrorEventArgs e)
        {
            FinalizeScan();

            if (e.Exception.ConditionCode != TwCC.Success)
            {
                _onError?.Invoke("Twain encountered an acquire error: " + e.Exception.ToString());
            }
        }
Coordinator
Oct 18, 2016 at 7:27 PM
Hello, ghostbust555.
It's just a sample code. It does not cover all possible situations.
Marked as answer by SARAFF on 10/22/2016 at 1:34 PM