/// <summary> /// Get a list of all pointer of the cameras connected to the host /// </summary> /// <returns>A list of connected cameras as pointer</returns> /// <exception cref="ObjectDisposedException">This instance has been disposed already</exception> /// <exception cref="SDKException">An SDK call failed</exception> protected IEnumerable <IntPtr> GetCameraPointerList() { if (IsDisposed) { throw new ObjectDisposedException(nameof(CanonAPI)); } IntPtr camlist; //Get camera list ErrorHandler.CheckError(this, CanonSDK.EdsGetCameraList(out camlist)); //Get number of connected cameras int camCount; ErrorHandler.CheckError(this, CanonSDK.EdsGetChildCount(camlist, out camCount)); List <IntPtr> ptrList = new List <IntPtr>(); for (int i = 0; i < camCount; i++) { //Get camera pointer IntPtr cptr; ErrorHandler.CheckError(this, CanonSDK.EdsGetChildAtIndex(camlist, i, out cptr)); ptrList.Add(cptr); } //Release the list ErrorHandler.CheckError(this, CanonSDK.EdsRelease(camlist)); return(ptrList); }
/// <summary> /// Gets a <see cref="Bitmap"/> from an EDSDK pointer to an image (Jpg or Raw) /// </summary> /// <param name="imgStream">Stream pointer to the image</param> /// <param name="imageSource">The result image type</param> /// <returns>A <see cref="Bitmap"/> image from the given stream pointer</returns> protected Bitmap GetImage(IntPtr imgStream, ImageSource imageSource) { IntPtr imgRef = IntPtr.Zero; IntPtr streamPointer = IntPtr.Zero; ImageInfo imageInfo; try { //create reference and get image info ErrorHandler.CheckError(this, CanonSDK.EdsCreateImageRef(imgStream, out imgRef)); ErrorHandler.CheckError(this, CanonSDK.EdsGetImageInfo(imgRef, imageSource, out imageInfo)); Size outputSize = new Size(); outputSize.Width = imageInfo.EffectiveRect.Width; outputSize.Height = imageInfo.EffectiveRect.Height; //calculate amount of data int datalength = outputSize.Height * outputSize.Width * 3; //create buffer that stores the image byte[] buffer = new byte[datalength]; //create a stream to the buffer using (var stream = new SDKStream(buffer)) { //load image into the buffer ErrorHandler.CheckError(this, CanonSDK.EdsGetImage(imgRef, imageSource, TargetImageType.RGB, imageInfo.EffectiveRect, outputSize, stream.Reference)); //make BGR from RGB (System.Drawing (i.e. GDI+) uses BGR) unsafe { byte tmp; fixed(byte *pix = buffer) { for (long i = 0; i < datalength; i += 3) { tmp = pix[i]; //Save B value pix[i] = pix[i + 2]; //Set B value with R value pix[i + 2] = tmp; //Set R value with B value } } } //Get pointer to stream data ErrorHandler.CheckError(this, CanonSDK.EdsGetPointer(stream.Reference, out streamPointer)); //Create bitmap with the data in the buffer return(new Bitmap(outputSize.Width, outputSize.Height, datalength, PixelFormat.Format24bppRgb, streamPointer)); } } finally { //Release all data if (imgStream != IntPtr.Zero) { ErrorHandler.CheckError(this, CanonSDK.EdsRelease(imgStream)); } if (imgRef != IntPtr.Zero) { ErrorHandler.CheckError(this, CanonSDK.EdsRelease(imgRef)); } } }
/// <summary> /// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK file stream /// </summary> /// <param name="filepath">Path to the file</param> /// <param name="createDisposition">State how to create the stream</param> /// <param name="access">File access type</param> public SDKStream(string filepath, FileCreateDisposition createDisposition, FileAccess access) { if (filepath == null) { throw new ArgumentNullException(nameof(filepath)); } ErrorHandler.CheckError(CanonSDK.EdsCreateFileStreamEx(filepath, createDisposition, access, out _Reference)); }
/// <summary> /// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream. /// This stream will resize itself if the current length is exceeded /// </summary> /// <param name="length">Initial buffer size of the stream in bytes</param> public SDKStream(long length) { ErrorCode err; if (CanonSDK.IsVerGE34) { err = CanonSDK.EdsCreateMemoryStream(length, out _Reference); } else { err = CanonSDK.EdsCreateMemoryStream((int)length, out _Reference); } ErrorHandler.CheckError(err); }
/// <summary> /// Initializes the SDK /// </summary> /// <param name="useCallingThread">If true, the calling thread will be used as SDK main thread; /// if false, a separate thread will be created</param> public CanonAPI(bool useCallingThread) { try { //Ensure that only one caller at a time can increase the counter lock (InitLock) { //If no instance exists yet, initialize everything if (RefCount == 0) { if (useCallingThread) { if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { throw new ThreadStateException("Calling thread must be in STA"); } ErrorHandler.CheckError(this, CanonSDK.EdsInitializeSDK()); } else { //Trying to trigger DllNotFoundException so it's not thrown //in the event loop on a different thread: CanonSDK.EdsRelease(IntPtr.Zero); //Start the main thread where SDK will run on MainThread = new ApiThread(); MainThread.Start(); //Initialize the SDK on the main thread MainThread.Invoke(() => ErrorHandler.CheckError(this, CanonSDK.EdsInitializeSDK())); } CanonSDK.InitializeVersion(); //Subscribe to the CameraAdded event CameraAddedEvent = new SDKCameraAddedHandler(CanonAPI_CameraAddedEvent); ErrorHandler.CheckError(this, CanonSDK.EdsSetCameraAddedHandler(CameraAddedEvent, IntPtr.Zero)); _IsSDKInitialized = true; } RefCount++; } } catch (Exception e) { IsDisposed = true; if (MainThread?.IsRunning == true) { MainThread.Shutdown(); } throw; } }
/// <summary> /// Releases this entry but not the subentries /// </summary> /// <param name="managed">True if called from Dispose, false if called from the finalizer/destructor</param> protected virtual void Dispose(bool managed) { if (!IsDisposed) { if (managed) { DisposeThumb(); } if (Reference != IntPtr.Zero) { CanonSDK.EdsRelease(Reference); } IsDisposed = true; } }
protected override void WaitForNotification() { lock (threadLock1) { while (block1 && IsRunning) { Monitor.Wait(threadLock1, 0); lock (ExecLock) { CanonSDK.EdsGetEvent(); Monitor.Wait(ExecLock, 40); } } block1 = true; } }
/// <summary> /// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream. /// Note that this stream will not resize itself /// </summary> /// <param name="buffer">Pointer to the memory buffer to use for the stream</param> /// <param name="length">The size of the memory buffer in bytes</param> public SDKStream(IntPtr buffer, long length) { if (buffer == IntPtr.Zero) { throw new ArgumentNullException(nameof(buffer)); } ErrorCode err; if (CanonSDK.IsVerGE34) { err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, length, out _Reference); } else { err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)length, out _Reference); } ErrorHandler.CheckError(err); }
/// <summary> /// Creates a new instance of the <see cref="SDKStream"/> class with an underlying SDK memory stream. /// Note that this stream will not resize itself /// </summary> /// <param name="buffer">The memory buffer to use for the stream</param> public SDKStream(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } ErrorCode err; if (CanonSDK.IsVerGE34) { err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, buffer.LongLength, out _Reference); } else { err = CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)buffer.LongLength, out _Reference); } ErrorHandler.CheckError(err); }
/// <summary> /// Creates a new instance of the <see cref="DownloadInfo"/> class /// </summary> /// <param name="inRef">Pointer to the downloadable object</param> internal protected DownloadInfo(IntPtr inRef) { if (inRef == IntPtr.Zero) { throw new ArgumentNullException(nameof(inRef)); } this.inRef = inRef; ErrorHandler.CheckError(this, CanonSDK.GetDirectoryItemInfo(inRef, out dirInfo)); string ext = Path.GetExtension(FileName).ToLower(); if (ext == ".crw" || ext == ".cr2") { IsRAW = true; } else { IsRAW = false; } }
/// <summary> /// Terminates the SDK and disposes resources /// </summary> /// <param name="managed">True if called from Dispose, false if called from the finalizer/destructor</param> protected virtual void Dispose(bool managed) { //Ensure that only one caller at a time can decrease the counter lock (InitLock) { if (!IsDisposed) { //If it's the last instance, release everything if (RefCount == 1) { _IsSDKInitialized = false;//Set beforehand because if an error happens, the SDK will be in an unstable state anyway //Remove event handler for the CameraAdded event ErrorCode err = CanonSDK.EdsSetCameraAddedHandler(null, IntPtr.Zero); if (managed) { ErrorHandler.CheckError(this, err); //Dispose all the connected cameras CurrentCameras.ForEach(t => t.Dispose()); } //Terminate the SDK if (MainThread?.IsRunning == true) { err = MainThread.Invoke(() => { return(CanonSDK.EdsTerminateSDK()); }); } //Close the main thread if (MainThread?.IsRunning == true) { MainThread.Shutdown(); } if (managed) { ErrorHandler.CheckError(this, err); } } RefCount--; IsDisposed = true; } } }
/// <summary> /// Sets the position within the current stream. /// </summary> /// <param name="offset">A byte offset relative to the origin parameter.</param> /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the /// reference point used to obtain the new position.</param> /// <returns>The new position within the current stream.</returns> public override long Seek(long offset, SeekOrigin origin) { SDK.SeekOrigin sdkOrigin; switch (origin) { case SeekOrigin.Begin: sdkOrigin = SDK.SeekOrigin.Begin; break; case SeekOrigin.Current: sdkOrigin = SDK.SeekOrigin.Current; break; case SeekOrigin.End: sdkOrigin = SDK.SeekOrigin.End; break; default: throw new ArgumentException("Not a valid enum value", nameof(origin)); } if (CanonSDK.IsVerGE34) ErrorHandler.CheckError(CanonSDK.EdsSeek(_Reference, offset, sdkOrigin)); }
/// <summary> /// Reads a sequence of bytes from the current stream and advances the position /// within the stream by the number of bytes read. /// </summary> /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified /// byte array with the values between offset and (offset + count - 1) replaced by /// the bytes read from the current source.</param> /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read /// from the current stream.</param> /// <param name="count">The maximum number of bytes to be read from the current stream.</param> /// <returns>The total number of bytes read into the buffer. This can be less than the number /// of bytes requested if that many bytes are not currently available, or zero (0) /// if the end of the stream has been reached.</returns> public unsafe long Read(byte[] buffer, long offset, long count) { if (buffer.LongLength < offset + count) { throw new ArgumentOutOfRangeException(); fixed(byte *bufferPtr = buffer) { byte *offsetBufferPtr = bufferPtr + offset; if (CanonSDK.IsVerGE34) { long read; ErrorHandler.CheckError(CanonSDK.EdsRead(_Reference, count, (IntPtr)offsetBufferPtr, out read)); return(read); } else { int read; ErrorHandler.CheckError(CanonSDK.EdsRead(_Reference, (int)count, (IntPtr)offsetBufferPtr, out read)); return(read); } } }