• Content Count

  • Joined

  • Last visited

Community Reputation

  1. I don't think you are going to manage to write a complete solution using just the System.Windows.Imaging.Media namespace as I think you then are completely dependent on the Windows Imaging Codec (WIC) system arbitrating which codec decoder gets used for each image file extension you list that you can support, which would be completely subject to the number of codecs installed for each and the manufacturer supplied ones would likely be given the priority. Accordingly, I think you are going to have to use the wrappers, and just in case you aren't familiar with producing those I included a couple of examples in my last post, but forgot to use the Code markers for proper indentation, etc. As follows: The ISequentialStream interface wrapper: using System; using System.Runtime.InteropServices; namespace WIC { [ComImport, Guid("0c733a30-2a1c-11ce-ade5-00aa0044773d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISequentialStream { [PreserveSig] int Read( [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, [in] uint cb, [Out] out uint cbRead); [PreserveSig] int Write( [in, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, [in] uint cb, [Out] out uint cbWritten); } } and the IStream interface wrapper, which adds to it: using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace WIC { [ComImport, Guid("0000000C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IStream : ISequentialStream { [PreserveSig] new int Read( [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, [in] uint cb, [Out] out uint cbRead); [PreserveSig] new int Write( [in, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, [in] uint cb, [Out] out uint cbWritten); [PreserveSig] int Seek( [in] long dlibMove, [in] uint dwOrigin, [Out] out ulong libNewPosition); [PreserveSig] int SetSize( [in] ulong libNewSize); [PreserveSig] int CopyTo( [in, MarshalAs(UnmanagedType.Interface)] IStream stm, [in] ulong cb, [Out] out ulong cbRead, [Out] out ulong cbWritten); [PreserveSig] int Commit( [in] uint grfCommitFlags); [PreserveSig] int Revert(); [PreserveSig] int LockRegion( [in] ulong libOffset, [in] ulong cb, [in] uint dwLockType); [PreserveSig] int UnlockRegion( [in] ulong libOffset, [in] ulong cb, [in] uint dwLockType); [PreserveSig] int Stat( [Out] out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, [in] uint grfStatFlag); [PreserveSig] int Clone( [Out, MarshalAs(UnmanagedType.Interface)] out IStream stm); } } In case you've never produced these before, you need to declare the methods in the exact order that they are declared in the C++ header files and an interface that builds on another interface needs to redeclare all the same methods as the previous interface(s) first with the new keyword as IStream above is based on ISequentialStream. The above two interfaces allow you to create a wrapper class for the Stream object that is passed to your OnLoad method for your FileType class so that you can pass the IStream interface pointer as an argument to the decoders and not have to do this by getting a file name. As Rick says, at some point you might be passed a MemoryStream rather than a FileStream and the FileName would not apply. As to wanting your plugin to work with any installed codec, that is entirely a matter of your program logic as to what you do once you have enumerated all installed codecs: You can put first priority on the FPV ones if they are found and revert to just providing a generic handling and let WIC arbitrate for any others for that file type if they exist and the FPV one does not. Also, I think you should create different FileType classes for each file extension handled and either link them to to the specific FPV codec or to the generic case; in this way you can automatically support all image file classes by getting the file extensions supported from the decoder enumeration, which would avoid requests such as ks8802's for support for the Panasonic '.rw2' file type as below. I think your method should always work as you seem to use the same method as used by Rick Brewster in his WIC codec support for the HD file format (now WDF or other). I'm sure you must be used to using Reflector to see what others are doing in their code, just as I can see what you are doing with yours? There are actually even further capabilities you could add, as the FPV decoders support the IWICDevelopRaw interface (or at least some of them do) and allow you to do exposure adjustments to the raw development before it would be passed to Paint.NET. This would require a bit of a user interface form with a histogram, an image preview (preferably with clipping flashies), and EV adjustment slider and value adjustment controls, but would make this more resemble a full raw development plugin for Paint.NET! Regards, Gordon
  2. Hi, This WIC plugin seems like a very good idea that should have been done a long time ago. It also seems reasonable to base it on Axel's donation-ware FastPictureViewer Codec's, which automatically install on both 32 and 64 bit Windows OS's and are frequently updated as to supporting new camera models. Axel's suggestion below seems to be a good one in principle, as follows: However, I have a few further suggestions, as follows: 1) Rather than enumerating all installed codec's and excluding those written by Microsoft, I suggest that you only support those codec's with the FastPictureViewer VendorGUID, which is {A6D092A4-081A-4F0E-9356-DA167E87D922} and make the presence of the codec's a condition for supporting each type of file (and file extension). In this way, your plugin would only handle file types for which the codec is installed. 2) Further, when the plugin is called to do a conversion, force the selection of the decoder based on the Container GUID as supported by each of the FastPictureViewer codecs and the preferred VendorID as above so that you know you will be getting a consistent raw conversion by a known codec even if other codec's such as the camera manufacturer ones are installed as well. 3) Finally, you may find it much easier to do the above if you write the plugin in managed C++ in order to be able to call the WIC interfaces by just including the WIC header files in your main C++ code; all or most other marshaling of data between the managed plugin and the unmanaged WIC codec system would then be done by managed C++'s IJW (It Just Works) system so the code to do such a thing is not much more than you have now. You can do the same thing using C#, but you will have to declare all the WIC interfaces in C# as ComImport compatible interfaces, which can be very time consuming. For instance, to declare the IStream interface which is based on ISequentialStream, and which is required to be passed to many process the data in the stream, you would need to declare the following: (EDIT: Shown further down the thread in a later post) You will need to declare an object that wraps the DotNet native Stream class in a COM compatible IStream interface in order to be able to pass the stream through to WIC. These are just two of at least a dozen interfaces you will need to declare out of the full set of WIC interfaces in order to accomplish the proposed changes. There are other similar complexities such as in declaring a C# object to represent the PROPVARIANT structure, which is required to receive what is returned by the IWICMetadataQueryReader.GetMetadataByName method you use when you read metadata using WIC directly instead of the BitmapMetadata class's GetQuery method you use now. All of the available classes you currently use do all of this marshaling, interfacing, and conversion for you behind the scenes, but they aren't capable of selecting specific WIC decoders out of the set of available ones. In short, if you want to implement the suggestions, using managed C++ for your plugin would be much easier. However, if you want to do it with C#, it is possible and I may be able to help. Regards, Gordon