After hours of testing and banging my head, I think I've finally figured out the issue.
For those who are curious, the problem was that the import form would retrieve each File object by id (as passed in the checkboxes on the import form) and then set its ClassName property to whatever your file class for that object is. In the case of ImageGallery, most of the time, it's ImageGalleryImage. After updating the ClassName property to ImageGalleryImage, the function runs the write() method on the file object. That's where it errors out.
What I found out was that the wildcard method __call() was reporting the current object as ImageGalleryImage, but a get_class($file) showed that it was still an Image object. That is, updating the ClassName property, while good enough for Silverstripe, is certainly not good enough for PHP. The two were out of sync. Silverstripe was trying to handle the object like an ImageGalleryImage, but to PHP, it was still the same thing it got out of the database, regardless of its ClassName property.
The solution we owe to the geniuses at Silverstripe who never fail to amaze me in their provision of useful methods that go largely unrecognized.
$image = $file->newClassInstance($this->fileClassName);
Thanks for all your testing and patience, guys. Please have a crack at the latest rev and let me know your findings (fingers crossed).