Monday, December 20, 2004

I can read pictures through the proprietary software!

I finally got images off this stupid Kodak camera. Only 1 task left, but I'll let you see what I've done so far.

'Get a handle to the directory
myStatus = Me.KAllocDirItemByPath(myCameraRef, myFolder, myDir)

'Allocate a direcotry iterator for that folder
If myStatus = 0 Then myStatus = Me.KAllocDirectoryIter(myDir, myDirIter)

'Iterate to the next directory item
myStatus = Me.KIteratorNext(myDirIter, myDirItem)

Do Until myStatus <> 0

I set it up this way. You have to get a handle to directory, passing in a string for the path name. (ie. "Camera\Card1\DCIM\FolderName\")

Then you get an iterator, and walk the iterator for the different files.

In my loop I have this code:
'Create a handle to the source file
myStatus = Me.KAllocIORef(myDirItem, mySrcIO)

'Create the handle to the file. The handle is a fileStream(fStream).handle
fStream = New IO.FileStream(memPath.ToString, IO.FileMode.Create)

'Create a handle to the destination
myStatus = Me.KAllocIORefFromFileHandleRef(Me.myLibMgr, fStream.Handle, Me.myTrgIO)

You follow all that? When I get the file as 'myDirItem' (an IntPtr Kodak's software uses to point to the file) I pass it to Kodak to create an IO Reference to the file. I create a file stream (much simplified thanks to .Net) and then pass that to Kodak to get an IO Reference to the stream.

Then I use one more Kodak functions to read from the IO Ref to the file, filling a buffer, then another to write to the IO Ref to the stream. They sure have a lot of functions.

The problem I had had was what to do for a buffer. Mostly when I've written a file, I've read right into the stream, or something similar. I had to create a buffer like so:
Dim theBuffer(524288) As Byte

Now some of you sharp guys will say, 'Hey, files aren't always going to be 500k!' You're right. I did this:
numBlocks = CType(Math.Floor(fileSize / theBuffer.Length), Integer)
finalBlock = fileSize - (numBlocks * 524288)

For blockIndex = 0 To numBlocks - 1
'// Read from the camera's memory
myStatus = Me.KRead(mySrcIO, theBuffer.Length, theBuffer)

'// Write to the host file
myStatus = Me.KWrite(myTrgIO, theBuffer.Length, theBuffer)

'// Read the final block
ReDim theBuffer(finalBlock)
myStatus = Me.KRead(mySrcIO, finalBlock, theBuffer)

I broke the file into 500k chunks, then when I was done with the nice clean chunks, wrote the leftovers.

Now, for any of you who are saying, 'This guy knows his stuff!' or 'This guys an idiot!', I'm simply porting Kodak's demo code for reading/writing files.

One more thing. The unmanaged read/write wraps:
Declare Auto Function KRead Lib "DCSPro4SLR.dll" Alias "KPDCRead" (ByVal inIORef As IntPtr, ByVal inCount As Integer, ByVal outBuffer As Byte()) As Integer

Declare Auto Function KWrite Lib "DCSPro4SLR.dll" Alias "KPDCWrite" (ByVal inIORef As IntPtr, ByVal inCount As Integer, ByVal inBuffer As Byte()) As Integer

You've got to Marshal the Buffer (Byte() or Byte array) to an unmanaged LPArray.
So that's it. Hope this helps somebody.

My next issue? The unmanaged code firing an event in my code!!! Look here! I know the unmanaged code is recognizing events, because it makes my code throw an exception. Not sure why, or how to troubleshoot.

No comments: