TWAIN Working Group

Newsletter Signup
Donate
Help keep TWAIN free
  • About TWAIN
    • What’s New?
    • News
    • Events
    • Membership
    • Consider a Donation
    • Contact Us
  • Why TWAIN?
  • Developers
    • Driver Developer
    • Application Developer
    • TWAIN Features
    • Specification & Tools
    • Self Certification Process
  • Support Forums
  • Scanner End-User
  • Find Certified Drivers
    • Facebook
    • LinkedIn
    • Vimeo

Nikon Coolscan IV ED TWAIN Memory Transfer

Forums › TWAIN Classic › Nikon Coolscan IV ED TWAIN Memory Transfer

  • This topic has 2 replies, 2 voices, and was last updated 7 years, 7 months ago by spike.
Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • August 13, 2013 at 2:48 pm #22879 Reply
    jhmgbl
    Participant
    • Topics - 2
    • Replies - 4
    • Total Posts - 6

    Hallo, I have problems with the above Scanner (all other Scanners work fine). In Native Mode the application crashes with an Access violation on

    rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, hbitmap)

    and with MemoryTransfer

    pImageMemX.BytesWritten

    is 0. I assume that perhaps a further initialisation is necessary.

    Here is the code:

    Public Function TransferPictures() As ArrayList

    Dim pics As New ArrayList
    If (srcds.Id = IntPtr.Zero) Then
    Return pics
    End If
    Dim rc As TwRC
    Dim hbitmap As IntPtr = IntPtr.Zero
    Dim pxfr As New TwPendingXfers()


    Do
    Try
    pxfr.Count = 0
    hbitmap = IntPtr.Zero

    Dim iinf As New TwImageInfo()
    Dim iLayout As New TwImageLayout
    rc = DSiinf(appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf)
    Dim rc2 As TwRC = DSilayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Get, iLayout)
    If iinf.PixelType <> TWPT.RGB Then MsgBox("Wrong Pixeltype: " & System.Enum.GetName(GetType(TWPT), CType(iinf.PixelType, TWPT)))
    If (rc <> TwRC.Success) Then

    CloseSrc()
    Return pics

    End If

    Dim setupMemXfer As New TW_SetupMemXfer()
    rc = DsmEntry(appid, srcds, TwMSG.Get, setupMemXfer)
    'rc = TwRC.Failure
    If rc = TwRC.Success Then
    Dim lHasNextBuffer As Boolean = True
    Dim pImageMemX As New TwImageMemXFer(setupMemXfer)
    pImageMemX.Compression = CUShort(iinf.Compression)
    Dim lBuffer, LHBuffer As IntPtr
    Dim TotalBytes As UInt32
    Dim lMemoryStream As New IO.MemoryStream
    Dim fh As New BITMAPFILEHEADER
    fh.bfSize = Marshal.SizeOf(fh)
    fh.bfType = &H4D42
    fh.bfReserved1 = 0
    fh.bfReserved2 = 0
    fh.bfOffBits = Marshal.SizeOf(fh) + Marshal.SizeOf(GetType(BITMAPINFOHEADER))
    Dim bmi As New BITMAPINFOHEADER
    bmi.biSize = Marshal.SizeOf(bmi)
    bmi.biPlanes = 1
    bmi.biBitCount = iinf.BitsPerPixel
    bmi.biCompression = iinf.Compression
    bmi.biSizeImage = CInt(((((iinf.ImageWidth * iinf.BitsPerPixel + 31) / 32) * 4) * Math.Abs(iinf.ImageLength)))

    bmi.biXPelsPerMeter = 0
    bmi.biYPelsPerMeter = 0
    bmi.biClrUsed = 0
    bmi.biClrImportant = 0
    bmi.biWidth = iinf.ImageWidth
    bmi.biHeight = iinf.ImageLength
    lMemoryStream.Seek(0, SeekOrigin.Begin)
    Dim pFH, pBMI As IntPtr
    Dim FHLength, BMILength As Integer
    FHLength = Marshal.SizeOf(fh)
    BMILength = Marshal.SizeOf(bmi)
    pFH = Marshal.AllocHGlobal(FHLength)
    pBMI = Marshal.AllocHGlobal(BMILength)
    Marshal.StructureToPtr(fh, pFH, True)
    Marshal.StructureToPtr(bmi, pBMI, True)
    Dim Arrfh(FHLength - 1) As Byte
    Dim ArrBMI(BMILength - 1) As Byte
    Marshal.Copy(pFH, Arrfh, 0, FHLength)
    Marshal.Copy(pBMI, ArrBMI, 0, BMILength)
    lMemoryStream.Write(Arrfh, 0, FHLength)
    lMemoryStream.Write(ArrBMI, 0, BMILength)
    Marshal.FreeHGlobal(pFH)
    Marshal.FreeHGlobal(pBMI)

    LHBuffer = GlobalAlloc(&H42, CInt(setupMemXfer.preferred))
    lBuffer = GlobalLock(LHBuffer)
    pImageMemX.Memory.TheMem = lBuffer

    While lHasNextBuffer
    Select Case DSmemxfer(appid, srcds, TwDG.Image, TwDAT.ImageMemXfer, TwMSG.Get, pImageMemX)

    Case TwRC.Success
    If pImageMemX.BytesWritten = 0 Then lHasNextBuffer = False : Exit Select
    Dim lByteArray As Byte() = New Byte(CInt(pImageMemX.BytesWritten - 1)) {}

    Marshal.Copy(lBuffer, lByteArray, 0, lByteArray.Length)
    Debug.Print(CStr(pImageMemX.Memory.Length))
    TotalBytes = TotalBytes + pImageMemX.BytesWritten
    lMemoryStream.Write(lByteArray, 0, lByteArray.Length)

    Dim lMessage As String = String.Format("pimagememx.BytesWritten = {0}", pImageMemX.BytesWritten)
    Debug.Print(lMessage)

    ' Free the current buffer
    GlobalUnlock(lBuffer)
    GlobalFree(LHBuffer)

    LHBuffer = IntPtr.Zero
    lBuffer = IntPtr.Zero

    LHBuffer = GlobalAlloc(&H42, CInt(setupMemXfer.preferred))
    lBuffer = GlobalLock(LHBuffer)

    pImageMemX = New TwImageMemXFer(setupMemXfer)
    pImageMemX.Memory.TheMem = lBuffer



    Exit Select
    Case TwRC.XferDone
    Dim lByteArray1 As Byte() = New Byte(CInt(pImageMemX.BytesWritten - 1)) {}


    Dim lMessage As String = String.Format("pimagememx.BytesWritten = {0}", pImageMemX.BytesWritten)
    Debug.Print(lMessage)
    Marshal.Copy(lBuffer, lByteArray1, 0, lByteArray1.Length)

    TotalBytes = TotalBytes + pImageMemX.BytesWritten
    lMemoryStream.Write(lByteArray1, 0, lByteArray1.Length)
    Try
    Dim img As Image = Image.FromStream(lMemoryStream)
    img.RotateFlip(RotateFlipType.RotateNoneFlipY)
    lMemoryStream.Close()
    GlobalUnlock(lBuffer)
    GlobalFree(LHBuffer)
    Dim b As Bitmap = DirectCast(img, Bitmap)
    Dim width As Integer = img.Width
    Dim height As Integer = img.Height
    Dim data As BitmapData = b.LockBits(New Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
    Dim offset As Integer = data.Stride - data.Width * 3
    Dim offs As Integer
    Dim ptr As IntPtr = data.Scan0
    Dim y As Integer = 0
    While y < height
    Dim x As Integer = 0
    While x < width
    Dim swap As Byte = Marshal.ReadByte(ptr, offs)
    Marshal.WriteByte(ptr, offs, Marshal.ReadByte(ptr, offs + 2))
    Marshal.WriteByte(ptr, offs + 2, swap)
    x += 1
    offs += 3
    End While
    y += 1
    offs += offset
    End While
    b.UnlockBits(data)

    pics.Add(img)
    Catch ex As Exception
    MsgBox(ex.Message)
    End Try
    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr)
    If (rc <> TwRC.Success) Then
    CloseSrc()
    Return pics
    End If

    lHasNextBuffer = False
    Exit Select

    Case TwRC.Cancel
    Exit Select
    Case TwRC.Failure
    Exit Select

    End Select
    End While
    Else
    Try
    rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, hbitmap)
    Catch
    End Try
    'hbitmap = CType(ptrBitmap, IntPtr)
    If (rc <> TwRC.XferDone) Then

    CloseSrc()
    Return pics
    End If

    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr)
    If (rc <> TwRC.Success) Then

    CloseSrc()
    Return pics
    End If

    pics.Add(hbitmap)
    End If

    Catch ex As Exception
    MsgBox(ex.Message)
    CloseSrc()
    Return pics
    End Try
    Loop While pxfr.Count <> 0


    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr)
    Return pics

    End Function

    And in C#

    public ArrayList TransferPictures()
    {

    ArrayList pics = new ArrayList();
    if ((srcds.Id == IntPtr.Zero)) {
    return pics;
    }
    TwRC rc = default(TwRC);
    IntPtr hbitmap = IntPtr.Zero;
    TwPendingXfers pxfr = new TwPendingXfers();


    do {
    try {
    pxfr.Count = 0;
    hbitmap = IntPtr.Zero;

    TwImageInfo iinf = new TwImageInfo();
    TwImageLayout iLayout = new TwImageLayout();
    rc = DSiinf(appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf);
    TwRC rc2 = DSilayout(appid, srcds, TwDG.Image, TwDAT.ImageLayout, TwMSG.Get, iLayout);
    if (iinf.PixelType != TWPT.RGB)
    Interaction.MsgBox("Wrong Pixeltype: " + System.Enum.GetName(typeof(TWPT), (TWPT)iinf.PixelType));

    if ((rc != TwRC.Success)) {
    CloseSrc();
    return pics;

    }

    TW_SetupMemXfer setupMemXfer = new TW_SetupMemXfer();
    rc = DsmEntry(appid, srcds, TwMSG.Get, setupMemXfer);
    //rc = TwRC.Failure
    if (rc == TwRC.Success) {
    bool lHasNextBuffer = true;
    TwImageMemXFer pImageMemX = new TwImageMemXFer(setupMemXfer);
    pImageMemX.Compression = Convert.ToUInt16(iinf.Compression);
    IntPtr lBuffer = default(IntPtr);
    IntPtr LHBuffer = default(IntPtr);
    UInt32 TotalBytes = default(UInt32);
    System.IO.MemoryStream lMemoryStream = new System.IO.MemoryStream();
    BITMAPFILEHEADER fh = new BITMAPFILEHEADER();
    fh.bfSize = Marshal.SizeOf(fh);
    fh.bfType = 0x4d42;
    fh.bfReserved1 = 0;
    fh.bfReserved2 = 0;
    fh.bfOffBits = Marshal.SizeOf(fh) + Marshal.SizeOf(typeof(BITMAPINFOHEADER));
    BITMAPINFOHEADER bmi = new BITMAPINFOHEADER();
    bmi.biSize = Marshal.SizeOf(bmi);
    bmi.biPlanes = 1;
    bmi.biBitCount = iinf.BitsPerPixel;
    bmi.biCompression = iinf.Compression;
    bmi.biSizeImage = Convert.ToInt32(((((iinf.ImageWidth * iinf.BitsPerPixel + 31) / 32) * 4) * Math.Abs(iinf.ImageLength)));

    bmi.biXPelsPerMeter = 0;
    bmi.biYPelsPerMeter = 0;
    bmi.biClrUsed = 0;
    bmi.biClrImportant = 0;
    bmi.biWidth = iinf.ImageWidth;
    bmi.biHeight = iinf.ImageLength;
    lMemoryStream.Seek(0, SeekOrigin.Begin);
    IntPtr pFH = default(IntPtr);
    IntPtr pBMI = default(IntPtr);
    int FHLength = 0;
    int BMILength = 0;
    FHLength = Marshal.SizeOf(fh);
    BMILength = Marshal.SizeOf(bmi);
    pFH = Marshal.AllocHGlobal(FHLength);
    pBMI = Marshal.AllocHGlobal(BMILength);
    Marshal.StructureToPtr(fh, pFH, true);
    Marshal.StructureToPtr(bmi, pBMI, true);
    byte[] Arrfh = new byte[FHLength];
    byte[] ArrBMI = new byte[BMILength];
    Marshal.Copy(pFH, Arrfh, 0, FHLength);
    Marshal.Copy(pBMI, ArrBMI, 0, BMILength);
    lMemoryStream.Write(Arrfh, 0, FHLength);
    lMemoryStream.Write(ArrBMI, 0, BMILength);
    Marshal.FreeHGlobal(pFH);
    Marshal.FreeHGlobal(pBMI);

    LHBuffer = GlobalAlloc(0x42, Convert.ToInt32(setupMemXfer.preferred));
    lBuffer = GlobalLock(LHBuffer);
    pImageMemX.Memory.TheMem = lBuffer;

    while (lHasNextBuffer) {
    switch (DSmemxfer(appid, srcds, TwDG.Image, TwDAT.ImageMemXfer, TwMSG.Get, pImageMemX)) {

    case TwRC.Success:
    if (pImageMemX.BytesWritten == 0){lHasNextBuffer = false;break; // TODO: might not be correct. Was : Exit Select
    }
    byte[] lByteArray = new byte[Convert.ToInt32(pImageMemX.BytesWritten - 1) + 1];

    Marshal.Copy(lBuffer, lByteArray, 0, lByteArray.Length);
    Debug.Print(Convert.ToString(pImageMemX.Memory.Length));
    TotalBytes = TotalBytes + pImageMemX.BytesWritten;
    lMemoryStream.Write(lByteArray, 0, lByteArray.Length);

    string lMessage = string.Format("pimagememx.BytesWritten = {0}", pImageMemX.BytesWritten);
    Debug.Print(lMessage);

    // Free the current buffer
    GlobalUnlock(lBuffer);
    GlobalFree(LHBuffer);

    LHBuffer = IntPtr.Zero;
    lBuffer = IntPtr.Zero;

    LHBuffer = GlobalAlloc(0x42, Convert.ToInt32(setupMemXfer.preferred));
    lBuffer = GlobalLock(LHBuffer);

    pImageMemX = new TwImageMemXFer(setupMemXfer);
    pImageMemX.Memory.TheMem = lBuffer;



    break; // TODO: might not be correct. Was : Exit Select

    break;
    case TwRC.XferDone:
    byte[] lByteArray1 = new byte[Convert.ToInt32(pImageMemX.BytesWritten - 1) + 1];


    string lMessage = string.Format("pimagememx.BytesWritten = {0}", pImageMemX.BytesWritten);
    Debug.Print(lMessage);
    Marshal.Copy(lBuffer, lByteArray1, 0, lByteArray1.Length);

    TotalBytes = TotalBytes + pImageMemX.BytesWritten;
    lMemoryStream.Write(lByteArray1, 0, lByteArray1.Length);
    try {
    Image img = Image.FromStream(lMemoryStream);
    img.RotateFlip(RotateFlipType.RotateNoneFlipY);
    lMemoryStream.Close();
    GlobalUnlock(lBuffer);
    GlobalFree(LHBuffer);
    Bitmap b = (Bitmap)img;
    int width = img.Width;
    int height = img.Height;
    BitmapData data = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    int offset = data.Stride - data.Width * 3;
    int offs = 0;
    IntPtr ptr = data.Scan0;
    int y = 0;
    while (y < height) {
    int x = 0;
    while (x < width) {
    byte swap = Marshal.ReadByte(ptr, offs);
    Marshal.WriteByte(ptr, offs, Marshal.ReadByte(ptr, offs + 2));
    Marshal.WriteByte(ptr, offs + 2, swap);
    x += 1;
    offs += 3;
    }
    y += 1;
    offs += offset;
    }
    b.UnlockBits(data);

    pics.Add(img);
    } catch (Exception ex) {
    Interaction.MsgBox(ex.Message);
    }
    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr);
    if ((rc != TwRC.Success)) {
    CloseSrc();
    return pics;
    }

    lHasNextBuffer = false;
    break; // TODO: might not be correct. Was : Exit Select


    break;
    case TwRC.Cancel:
    break; // TODO: might not be correct. Was : Exit Select

    break;
    case TwRC.Failure:
    break; // TODO: might not be correct. Was : Exit Select


    break;
    }
    }
    } else {
    try {
    rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, hbitmap);
    } catch {
    }
    //hbitmap = CType(ptrBitmap, IntPtr)

    if ((rc != TwRC.XferDone)) {
    CloseSrc();
    return pics;
    }

    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr);

    if ((rc != TwRC.Success)) {
    CloseSrc();
    return pics;
    }

    pics.Add(hbitmap);
    }

    } catch (Exception ex) {
    Interaction.MsgBox(ex.Message);
    CloseSrc();
    return pics;
    }
    } while (pxfr.Count != 0);


    rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr);
    return pics;

    }

    Regards Hans

    August 20, 2013 at 5:34 pm #25972 Reply
    jhmgbl
    Participant
    • Topics - 2
    • Replies - 4
    • Total Posts - 6

    I got the code working by setting the following capability:

    If Me.blnMemXFer Then SetCap(TwCap.IXferMech, twsx.MEMORY) Else SetCap(TwCap.IXferMech, twsx.NATIVE)

    The only problem is now that if PixelType is Grey the image gets distortet.

    Regards

    Hans

    August 27, 2013 at 8:28 pm #25973 Reply
    spike
    Participant
    • Topics - 10
    • Replies - 139
    • Total Posts - 149

    What’s the distortion look like?
    Are you taking account of the fact that in a bitmap (DIB) the size of each row is a multiple of 4 bytes?
    I see you using that to calculate the size of the DIB, but I don’t see you padding each row up to a multiple of 4 bytes when you copy data from the buffer during memory transfer.
    Also, Windows has no concept of grayscale DIB – grayscale images are managed as 256-color DIBs. So there has to be a 256-entry color table after the header, and I don’t see that either.
    I just skimmed the code, I’m sorry if I missed something!

  • Author
    Posts
Viewing 3 posts - 1 through 3 (of 3 total)
Reply To: Nikon Coolscan IV ED TWAIN Memory Transfer
Your information:




Quick Links

Service Providers
TWAIN Support Forums
Membership
Contact Us
Privacy Policy

Newsletter Signup

TWAIN Working Group Family

TWAIN Working Group
TWAIN Direct®
TWAIN Resources
TWAIN Certified Drivers
PDF/raster

  • Facebook
  • GitHub
  • LinkedIn
  • Vimeo

Recent Topics

  • Sports betting Bonus Code
  • PDF/R For who and where?
  • Making searchable PDF with PDF/R
  • Backward compatibility with PDF/A and traditional PDF
  • could not open the twain source. Make sure there is a valid source for your sca
  • Quarterly Newsletter
  • TWAIN Working Group Membership
  • Logo Usage
  • TWAIN License
  • Contact Us
Privacy Policy • Privacy Tools • Copyright © 2021 TWAIN Working Group • by iHwy, LLC • Log in

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.