TWAIN захваченные изображения все серые - PullRequest
0 голосов
/ 19 мая 2019

У меня есть приложение для архивирования WPF, которое может использовать для сканирования как TWAIN, так и WIA.Все было хорошо, некоторые сканеры работали с Twain отлично, а некоторые старые с WIA.Пока клиент не купил canon dr-f120!

Что ж, теперь WIA работает нормально, но не поддерживает дуплекс, и Twain (!!), все захваченные изображения Twain - серые.Twain captured images

Я пробовал это с другими сканерами, и это было хорошо.Я использовал Saraff TWAIN, поэтому подумал, что может быть проблема с ним, я скачал его образцы, и ни один из них не работал с этим странным сканером!Поэтому я искал другое решение и нашел NTwain , и его образец WPF работал со сканером canon dr-f120.

Так что теперь я использую новый TWAIN и снова он серый!Я не понимаю, почему это происходит.Вот как я использую twain:

У меня есть абстрактный класс, чтобы можно было переключаться между TWAIN и WIA:

public abstract class AbstractScanner
{
    protected bool showScannerUI;
    protected int fileCounter = 1;
    protected List<string> scans = new List<string>();
    protected string defaultDevice, tempPath = string.Format("{0}SAMControls.ScannerTmp", Path.GetTempPath());

    public event EventHandler ScannerEvent;

    public string TempPath
    {
        set { tempPath = value; }
        get { return tempPath; }
    }
    public string DefaultDevice
    {
        set { defaultDevice = value; }
        get { return defaultDevice; }
    }

    public void Configurator(string defaultScanner, bool showUI)
    {
        showScannerUI = showUI;
        defaultDevice = defaultScanner;
    }
    public void RaiseScannerEvent(object sender)
    {
        if (ScannerEvent != null)
            ScannerEvent.Invoke(sender, new ScannerEventArgs { ImagesPath = new List<string>(scans) });
    }
    public string GenerateTempAddress(string extension)
    {
        string temp = string.Format("{0}{1}.{2}", tempPath, fileCounter, extension);
        while (File.Exists(temp))
        {
            fileCounter++;
            temp = string.Format("{0}{1}.{2}", tempPath, fileCounter, extension);
        }
        fileCounter++;
        return temp;
    }

    public abstract List<string> GetScannersList();
    public abstract void Acquire();
    public abstract void Dispose();
}

, а затем реализация Saraff Twain:

public class TwainHandler : AbstractScanner
{
    Twain32 twain;
    ImageSource img;
    ScanMode scanMode;
    bool initialized = false;

    private bool Initializer()
    {
        twain = new Twain32();
        twain.OpenDSM();
        if (!string.IsNullOrEmpty(defaultDevice))
            for (int i = 0; i < twain.SourcesCount; i++)
                if (twain.GetSourceProductName(i) == defaultDevice)
                {
                    twain.SourceIndex = i;
                    break;
                }
        twain.OpenDataSource();
        twain.ShowUI = showScannerUI;
        if (twain.Capabilities.Compression.IsSupported() != 0)
        {
            twain.Capabilities.Compression.Set(TwCompression.Jpeg);
        }
        //twain.SetCap(TwCap.IXferMech, TwSX.Memory);
        //twain.SetupMemXferEvent += Twain_SetupMemXferEvent;
        //twain.MemXferEvent += Twain_MemXferEvent;
        //scanMode = ScanMode.Memory;
        if (twain.Capabilities.XferMech.IsSupported() != 0)
        {
            twain.SetCap(TwCap.IXferMech, TwSX.File);
            twain.SetupFileXferEvent += Twain_SetupFileXferEvent;
            twain.FileXferEvent += Twain_FileXferEvent;
            scanMode = ScanMode.File;
        }
        else
        {
            twain.SetCap(TwCap.IXferMech, TwSX.Memory);
            twain.SetupMemXferEvent += Twain_SetupMemXferEvent;
            twain.MemXferEvent += Twain_MemXferEvent;
            scanMode = ScanMode.Memory;
        }
        twain.AcquireCompleted += AcquireCompleted;
        return true;
    }

    public override List<string> GetScannersList()
    {
        twain = new Twain32();
        twain.OpenDSM();

        List<string> output = new List<string>();
        for (int i = 0; i < twain.SourcesCount; i++)
            output.Add(twain.GetSourceProductName(i));
        twain.Dispose();
        return output;
    }

    private void Twain_SetupMemXferEvent(object sender, Twain32.SetupMemXferEventArgs e)
    {
        PixelFormat _format = PixelFormats.Default;
        BitmapPalette _pallete = null;
        switch (e.ImageInfo.PixelType)
        {
            case TwPixelType.BW:
                _format = PixelFormats.BlackWhite;
                break;
            case TwPixelType.Gray:
                _format = new Dictionary<short, PixelFormat> {
                                    {2,PixelFormats.Gray2},
                                    {4,PixelFormats.Gray4},
                                    {8,PixelFormats.Gray8},
                                    {16,PixelFormats.Gray16}
                                }[e.ImageInfo.BitsPerPixel];
                break;
            case TwPixelType.Palette:
                _pallete = new BitmapPalette(new Func<IList<System.Windows.Media.Color>>(() =>
                {
                    var _res = new Collection<System.Windows.Media.Color>();
                    var _colors = twain.Palette.Get().Colors;
                    for (int i = 0; i < _colors.Length; i++)
                    {
                        _res.Add(System.Windows.Media.Color.FromArgb(_colors[i].A, _colors[i].R, _colors[i].G, _colors[i].B));
                    }
                    return _res;
                })());
                _format = new Dictionary<short, PixelFormat> {
                                    {2,PixelFormats.Indexed1},
                                    {4,PixelFormats.Indexed2},
                                    {8,PixelFormats.Indexed4},
                                    {16,PixelFormats.Indexed8}
                                }[e.ImageInfo.BitsPerPixel];
                break;
            case TwPixelType.RGB:
                _format = new Dictionary<short, PixelFormat> {
                                    {8,PixelFormats.Rgb24},
                                    {24,PixelFormats.Rgb24},
                                    {16,PixelFormats.Rgb48},
                                    {48,PixelFormats.Rgb48}
                                }[e.ImageInfo.BitsPerPixel];
                break;
            default:
                break;
        }
        img = new WriteableBitmap(
            e.ImageInfo.ImageWidth,
            e.ImageInfo.ImageLength,
            e.ImageInfo.XResolution,
            e.ImageInfo.YResolution,
            _format,
            _pallete);
        scans.Add(GenerateTempAddress("jpg"));
    }

    private void Twain_MemXferEvent(object sender, Twain32.MemXferEventArgs e)
    {
        (img as WriteableBitmap).WritePixels(
            new Int32Rect(0, 0, (int)e.ImageMemXfer.Columns, (int)e.ImageMemXfer.Rows),
            e.ImageMemXfer.ImageData,
            (int)e.ImageMemXfer.BytesPerRow,
            (int)e.ImageMemXfer.XOffset,
            (int)e.ImageMemXfer.YOffset);


        using (var filestream = new FileStream(scans[scans.Count - 1], FileMode.Create))
        {
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(img as WriteableBitmap));
            encoder.Save(filestream);
        }
    }

    private void Twain_SetupFileXferEvent(object sender, Twain32.SetupFileXferEventArgs e)
    {
        e.FileName = GenerateTempAddress("bmp");
        scans.Add(e.FileName);
    }

    private void Twain_FileXferEvent(object sender, Twain32.FileXferEventArgs e)
    {
        using (Image image = LoadBitmapUnlocked(scans[scans.Count - 1]))
        {
            string file = GenerateTempAddress("jpg");
            image.Save(file, System.Drawing.Imaging.ImageFormat.Jpeg);
            File.Delete(scans[scans.Count - 1]);
            scans[scans.Count - 1] = file;
        }
    }

    private void AcquireCompleted(object sender, EventArgs e)
    {
        if (scanMode == ScanMode.Memory)
        {
            string tempAddress;
            for (int i = 0; i < twain.ImageCount; i++)
            {
                tempAddress = GenerateTempAddress("jpg");
                twain.GetImage(i).Save(tempAddress, System.Drawing.Imaging.ImageFormat.Jpeg);
                scans.Add(tempAddress);
            }
        }
        RaiseScannerEvent(sender);
        Dispose();
    }

    public override void Acquire()
    {
        if (!initialized)
            initialized = Initializer();
        if (initialized)
            twain.Acquire();
        else
            RaiseScannerEvent(null);
    }

    private Bitmap LoadBitmapUnlocked(string file_name)
    {
        using (Bitmap bm = new Bitmap(file_name))
        {
            return new Bitmap(bm);
        }
    }

    public override void Dispose()
    {
        scans.Clear();
        if (twain != null)
        {
            twain.CloseDataSource();
            twain.CloseDSM();
            twain.Dispose();
        }
        initialized = false;
    }
}

и NTWAIN:

public class NTwainHandler : AbstractScanner
{
    ImageSource img;
    DataSource myDS;
    TwainSession _session;

    private IntPtr _winHandle;
    public IntPtr WindowHandle
    {
        get { return _winHandle; }
        set
        {
            _winHandle = value;
        }
    }

    public NTwainHandler()
    {
        var appId = TWIdentity.CreateFromAssembly(DataGroups.Image | DataGroups.Audio, Assembly.GetEntryAssembly());
        _session = new TwainSession(appId);
        _session.TransferError += _session_TransferError;
        _session.TransferReady += _session_TransferReady;
        _session.DataTransferred += _session_DataTransferred;
        _session.SourceDisabled += _session_SourceDisabled;
        // _session.StateChanged += (s, e) => { RaisePropertyChanged(() => State); };
    }

    public override void Acquire()
    {
        _session.Open();
        myDS = _session.FirstOrDefault();
        myDS.Open();
        _session.CurrentSource.Capabilities.ICapXferMech.SetValue(XferMech.File); /////////////////// Scanner Mode
        var rc = _session.CurrentSource.Enable(showScannerUI ? SourceEnableMode.ShowUI : SourceEnableMode.NoUI, false, WindowHandle);
    }

    public override void Dispose()
    {
    }

    public override List<string> GetScannersList()
    {
        _session.Open();
        List<string> output = new List<string>();
        IEnumerable<DataSource> sources = _session.GetSources();
        for (int i = 0, count = sources.Count(); i < count; i++)
            output.Add(sources.ElementAt(i).Name);
        _session.Close();
        return output;
    }

    void _session_SourceDisabled(object sender, EventArgs e)
    {
        RaiseScannerEvent(sender);
        myDS.Close();
        _session.Close();
        scans.Clear();
    }

    void _session_TransferError(object sender, TransferErrorEventArgs e)
    {
    }

    void _session_TransferReady(object sender, TransferReadyEventArgs e)
    {
        var mech = _session.CurrentSource.Capabilities.ICapXferMech.GetCurrent();
        if (mech == XferMech.File)
        {
            var formats = _session.CurrentSource.Capabilities.ICapImageFileFormat.GetValues();
            var wantFormat = formats.Contains(FileFormat.Tiff) ? FileFormat.Tiff : FileFormat.Bmp;

            var fileSetup = new TWSetupFileXfer
            {
                Format = wantFormat,
                FileName = GenerateTempAddress("bmp")
                // FileName = GetUniqueName(Path.GetTempPath(), "twain-test", "." + wantFormat)
            };
            var rc = _session.CurrentSource.DGControl.SetupFileXfer.Set(fileSetup);
        }
        else if (mech == XferMech.Memory)
        {
            PixelFormat _format = PixelFormats.Default;
            BitmapPalette _pallete = null;
            switch (e.PendingImageInfo.PixelType)
            {
                case PixelType.BlackWhite:
                    _format = PixelFormats.BlackWhite;
                    break;
                case PixelType.Gray:
                    _format = new Dictionary<short, PixelFormat> {
                                    {2,PixelFormats.Gray2},
                                    {4,PixelFormats.Gray4},
                                    {8,PixelFormats.Gray8},
                                    {16,PixelFormats.Gray16}
                                }[e.PendingImageInfo.BitsPerPixel];
                    break;
                case PixelType.RGB:
                    _format = new Dictionary<short, PixelFormat> {
                                    {8,PixelFormats.Rgb24},
                                    {24,PixelFormats.Rgb24},
                                    {16,PixelFormats.Rgb48},
                                    {48,PixelFormats.Rgb48}
                                }[e.PendingImageInfo.BitsPerPixel];
                    break;
                default:
                    break;
            }
            img = new WriteableBitmap(
                e.PendingImageInfo.ImageWidth,
                e.PendingImageInfo.ImageLength,
                e.PendingImageInfo.XResolution,
                e.PendingImageInfo.YResolution,
                _format,
                _pallete);
        }
    }

    void _session_DataTransferred(object sender, DataTransferredEventArgs e)
    {
        string filePath;
        switch (e.TransferType)
        {
            case XferMech.File:
                scans.Add(e.FileDataPath);
                break;
            case XferMech.Memory:
                filePath = GenerateTempAddress("jpg");
                (img as WriteableBitmap).WritePixels(
                    new Int32Rect(0, 0, (int)e.MemoryInfo.Columns, (int)e.MemoryInfo.Rows),
                    e.MemoryData,
                    (int)e.MemoryInfo.BytesPerRow,
                    (int)e.MemoryInfo.XOffset,
                    (int)e.MemoryInfo.YOffset);


                using (var filestream = new FileStream(filePath, FileMode.Create))
                {
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(img as WriteableBitmap));
                    encoder.Save(filestream);
                }
                scans.Add(filePath);
                break;
            case XferMech.Native:
                filePath = GenerateTempAddress("jpg");
                using (Stream nativeStream = e.GetNativeImageStream())
                {
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(img as WriteableBitmap));
                    encoder.Save(nativeStream);
                }
                scans.Add(filePath);
                break;
            case XferMech.MemFile:
                break;
        }

    }
}
...