读取 CR2 文件时佳能 EDSDK.EdsGetImage 错误 EDS_ERR_NOT_SUPPORTED
Canon EDSDK.EdsGetImage error EDS_ERR_NOT_SUPPORTED when reading CR2 file
我正在尝试使用 Canon EDSDKv0309W 读取 CR2 文件。我没有找到此 SDK 版本的示例,因此我查看了旧版本中的几个示例并创建了以下代码。但我总是在 EDSDK.EdsGetImage(..) 行得到 EDS_ERR_NOT_SUPPORTED。
使用 .Net4.6.1 下的 32 位编译,我可以从使用 EOS500D 和 M100 拍摄的图像中读取正确的高度。但我没有得到图像。所以我的假设是我从 EdsCreateMemoryStream 得到了一个错误的指针。但是我看不出有什么问题以及如何调试它。
任何帮助将不胜感激。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EDSDKLib;
using System.Drawing;
using System.Drawing.Imaging;
namespace CR2Reader
{
class Program
{
static Bitmap GetImage(IntPtr img_stream, EDSDK.EdsImageSource imageSource)
{
IntPtr stream = IntPtr.Zero;
IntPtr img_ref = IntPtr.Zero;
IntPtr streamPointer = IntPtr.Zero;
EDSDK.EdsImageInfo imageInfo;
uint error = 0;
try
{
//create reference and get image info
error = EDSDK.EdsCreateImageRef(img_stream, out img_ref);
if (error == 0)
{
error = EDSDK.EdsGetImageInfo(img_ref, imageSource, out imageInfo);
if (error == 0)
{
EDSDK.EdsSize outputSize = new EDSDK.EdsSize();
outputSize.width = imageInfo.EffectiveRect.width;
outputSize.height = imageInfo.EffectiveRect.height;
//calculate amount of data
int datalength = outputSize.height * outputSize.width * (int)imageInfo.NumOfComponents * (int)(imageInfo.ComponentDepth / 8);
//create buffer that stores the image
error = EDSDK.EdsCreateMemoryStream((ulong)datalength, out stream);
if (error == 0)
{
//load image into the buffer
error = EDSDK.EdsGetImage(img_ref, imageSource, EDSDK.EdsTargetImageType.RGB16, imageInfo.EffectiveRect, outputSize, stream);
if (error == 0)
{
//make BGR from RGB (System.Drawing (i.e. GDI+) uses BGR)
byte[] buffer = new byte[datalength];
unsafe
{
System.Runtime.InteropServices.Marshal.Copy(stream, buffer, 0, datalength);
byte tmp;
fixed (byte* pix = buffer)
{
for (int 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
error = EDSDK.EdsGetPointer(stream, out streamPointer);
if (error == 0)
{
//Create bitmap with the data in the buffer
return new Bitmap(outputSize.width, outputSize.height, datalength, PixelFormat.Format24bppRgb, streamPointer);
}
}
}
}
}
return null;
}
finally
{
//Release all data
if (img_ref != IntPtr.Zero) error = EDSDK.EdsRelease(img_ref);
if (stream != IntPtr.Zero) error = EDSDK.EdsRelease(stream);
}
}
static Bitmap ReadCR2Image(string fileName)
{
IntPtr outStream = new IntPtr();
uint error = EDSDK.EdsInitializeSDK();
error += EDSDK.EdsCreateFileStream(fileName,
EDSDK.EdsFileCreateDisposition.OpenExisting,
EDSDK.EdsAccess.Read,
out outStream);
Bitmap bmp = null;
if (error == 0)
{
bmp = GetImage(outStream, EDSDK.EdsImageSource.FullView);
}
if (outStream != IntPtr.Zero)
{
error = EDSDK.EdsRelease(outStream);
}
EDSDK.EdsTerminateSDK();
return bmp;
}
static void Main(string[] args)
{
Bitmap bmp = ReadCR2Image("IMG_3113.CR2");
}
}
}
您使用了错误的 EdsImageSource
类型。
由于您正在加载 RAW 图像,因此您还必须使用 EdsImageSource.RAWFullView
。 EdsImageSource.FullView
适用于例如JPG 或 TIFF。
一旦你改变它,一切都会正常工作。
编辑: 刚刚看到您正在使用 RGB16
作为目标,但其余代码假定为正常的 8 位 RGB。您必须更改一大堆东西才能使其正常工作。我建议你使用 RGB
除非你真的需要 16 位。
编辑 2: 看起来图书馆在这方面有点过时(我真的应该更新它)。在任何情况下,您始终可以检查 SDK 的头文件以获取最新值。这是 EdsImageSource
的当前定义:
enum EdsImageSource
{
FullView = 0,
Thumbnail,
Preview,
RAWThumbnail,
RAWFullView,
}
至于 16 位所需的更改:
datalength
不正确
- 您使用
byte
而不是 ushort
来设置像素
- 你用
PixelFormat.Format24bppRgb
创建了 Bitmap
- 还有一点
Bitmap
不完全支持16Bit。有关详细信息,请参阅 this article。
根据您需要执行的操作,最好直接使用从 SDK 获取的原始像素数据或使用不同的图形库(例如 WPF、SkiaSharp、ImageSharp 等)
我正在尝试使用 Canon EDSDKv0309W 读取 CR2 文件。我没有找到此 SDK 版本的示例,因此我查看了旧版本中的几个示例并创建了以下代码。但我总是在 EDSDK.EdsGetImage(..) 行得到 EDS_ERR_NOT_SUPPORTED。
使用 .Net4.6.1 下的 32 位编译,我可以从使用 EOS500D 和 M100 拍摄的图像中读取正确的高度。但我没有得到图像。所以我的假设是我从 EdsCreateMemoryStream 得到了一个错误的指针。但是我看不出有什么问题以及如何调试它。 任何帮助将不胜感激。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EDSDKLib;
using System.Drawing;
using System.Drawing.Imaging;
namespace CR2Reader
{
class Program
{
static Bitmap GetImage(IntPtr img_stream, EDSDK.EdsImageSource imageSource)
{
IntPtr stream = IntPtr.Zero;
IntPtr img_ref = IntPtr.Zero;
IntPtr streamPointer = IntPtr.Zero;
EDSDK.EdsImageInfo imageInfo;
uint error = 0;
try
{
//create reference and get image info
error = EDSDK.EdsCreateImageRef(img_stream, out img_ref);
if (error == 0)
{
error = EDSDK.EdsGetImageInfo(img_ref, imageSource, out imageInfo);
if (error == 0)
{
EDSDK.EdsSize outputSize = new EDSDK.EdsSize();
outputSize.width = imageInfo.EffectiveRect.width;
outputSize.height = imageInfo.EffectiveRect.height;
//calculate amount of data
int datalength = outputSize.height * outputSize.width * (int)imageInfo.NumOfComponents * (int)(imageInfo.ComponentDepth / 8);
//create buffer that stores the image
error = EDSDK.EdsCreateMemoryStream((ulong)datalength, out stream);
if (error == 0)
{
//load image into the buffer
error = EDSDK.EdsGetImage(img_ref, imageSource, EDSDK.EdsTargetImageType.RGB16, imageInfo.EffectiveRect, outputSize, stream);
if (error == 0)
{
//make BGR from RGB (System.Drawing (i.e. GDI+) uses BGR)
byte[] buffer = new byte[datalength];
unsafe
{
System.Runtime.InteropServices.Marshal.Copy(stream, buffer, 0, datalength);
byte tmp;
fixed (byte* pix = buffer)
{
for (int 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
error = EDSDK.EdsGetPointer(stream, out streamPointer);
if (error == 0)
{
//Create bitmap with the data in the buffer
return new Bitmap(outputSize.width, outputSize.height, datalength, PixelFormat.Format24bppRgb, streamPointer);
}
}
}
}
}
return null;
}
finally
{
//Release all data
if (img_ref != IntPtr.Zero) error = EDSDK.EdsRelease(img_ref);
if (stream != IntPtr.Zero) error = EDSDK.EdsRelease(stream);
}
}
static Bitmap ReadCR2Image(string fileName)
{
IntPtr outStream = new IntPtr();
uint error = EDSDK.EdsInitializeSDK();
error += EDSDK.EdsCreateFileStream(fileName,
EDSDK.EdsFileCreateDisposition.OpenExisting,
EDSDK.EdsAccess.Read,
out outStream);
Bitmap bmp = null;
if (error == 0)
{
bmp = GetImage(outStream, EDSDK.EdsImageSource.FullView);
}
if (outStream != IntPtr.Zero)
{
error = EDSDK.EdsRelease(outStream);
}
EDSDK.EdsTerminateSDK();
return bmp;
}
static void Main(string[] args)
{
Bitmap bmp = ReadCR2Image("IMG_3113.CR2");
}
}
}
您使用了错误的 EdsImageSource
类型。
由于您正在加载 RAW 图像,因此您还必须使用 EdsImageSource.RAWFullView
。 EdsImageSource.FullView
适用于例如JPG 或 TIFF。
一旦你改变它,一切都会正常工作。
编辑: 刚刚看到您正在使用 RGB16
作为目标,但其余代码假定为正常的 8 位 RGB。您必须更改一大堆东西才能使其正常工作。我建议你使用 RGB
除非你真的需要 16 位。
编辑 2: 看起来图书馆在这方面有点过时(我真的应该更新它)。在任何情况下,您始终可以检查 SDK 的头文件以获取最新值。这是 EdsImageSource
的当前定义:
enum EdsImageSource
{
FullView = 0,
Thumbnail,
Preview,
RAWThumbnail,
RAWFullView,
}
至于 16 位所需的更改:
datalength
不正确- 您使用
byte
而不是ushort
来设置像素 - 你用
PixelFormat.Format24bppRgb
创建了 - 还有一点
Bitmap
不完全支持16Bit。有关详细信息,请参阅 this article。
Bitmap
根据您需要执行的操作,最好直接使用从 SDK 获取的原始像素数据或使用不同的图形库(例如 WPF、SkiaSharp、ImageSharp 等)