Canon EDSDK.EdsGetImage error EDS_ERR_NOT_SUPPORTED when reading CR2 file - canon-sdk

I'm trying to read a CR2 file using the Canon EDSDKv0309W. I didn't found an example for this SDK version so I looked at several examples from older versions and created the code below. But I always get EDS_ERR_NOT_SUPPORTED in line EDSDK.EdsGetImage(..).
Using a 32Bit compilation under .Net4.6.1 I can read the correct with and height from images taken with EOS500D and M100. But I don't get the image. So my assumption is I get a wrong pointer from EdsCreateMemoryStream. But I don't see what is wrong and how to debug this.
Any help will be appreciated.
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");
}
}
}

You are using the wrong EdsImageSource type.
Since you are loading a RAW image you also have to use EdsImageSource.RAWFullView. EdsImageSource.FullView would be appropriate for e.g. a JPG or TIFF.
Once you change that, everything should work just fine.
Edit: just saw you are using RGB16 as target but the rest of the code assumes normal 8bit RGB. You'll have to change a whole bunch of stuff to get that working correctly. I'd advise you to use RGB unless you really need 16bit.
Edit 2: Looks like the library is a bit out of that in that regard (I should really update it). In any case, you can always check the header files of the SDK for up-to-date values. Here's the current definition for EdsImageSource:
enum EdsImageSource
{
FullView = 0,
Thumbnail,
Preview,
RAWThumbnail,
RAWFullView,
}
As for changes required for 16bit:
datalength is incorrect
you're using byte instead of ushort to set the pixels
you create the Bitmap with PixelFormat.Format24bppRgb
then there's another thing where Bitmap doesn't fully support 16Bit. See this article for some in-depth information.
Depending on what you need to do it's probably better to either use the raw pixel data directly as you get it from the SDK or use a different graphics library (e.g. WPF, SkiaSharp, ImageSharp, etc.)

Related

Saved joints from kinect skeleton track

I work with the kinect. My goal is to store the values ​​gives me the kinect for the location of the body (head,hand etc). I have written some code but I can not understand what values ​​should save and how.I want to store in the db or in a txt file the position of the head,hands and foots.I want the data to understand the movements of the person who stand in front of kinect.For example if someone move her hand the kinect will sent a value.I must store it and understand and to understand the move taken.Sorry for the few info
here is my code:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.Linq;
using System.IO;
namespace KinectSkeletonApplication1
{
public partial class MainWindow : Window
{
//Instantiate the Kinect runtime. Required to initialize the device.
//IMPORTANT NOTE: You can pass the device ID here, in case more than one Kinect device is connected.
KinectSensor sensor = KinectSensor.KinectSensors[0];
byte[] pixelData;
Skeleton[] skeletons;
public MainWindow()
{
InitializeComponent();
///////////////////////////////////
///////////////////////////////
//Runtime initialization is handled when the window is opened. When the window
//is closed, the runtime MUST be unitialized.
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded);
sensor.ColorStream.Enable();
sensor.SkeletonStream.Enable();
}
void runtime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
bool receivedData = false;
using (SkeletonFrame SFrame = e.OpenSkeletonFrame())
{
if (SFrame == null)
{
// The image processing took too long. More than 2 frames behind.
}
else
{
skeletons = new Skeleton[SFrame.SkeletonArrayLength];
SFrame.CopySkeletonDataTo(skeletons);
receivedData = true;
}
}
if (receivedData)
{
Skeleton currentSkeleton = (from s in skeletons
where s.TrackingState == SkeletonTrackingState.Tracked
select s).FirstOrDefault();
if (currentSkeleton != null)
{
SetEllipsePosition(head, currentSkeleton.Joints[JointType.Head]);
SetEllipsePosition(leftHand, currentSkeleton.Joints[JointType.HandLeft]);
SetEllipsePosition(rightHand, currentSkeleton.Joints[JointType.HandRight]);
SetEllipsePosition(shoulder_center, currentSkeleton.Joints[JointType.ShoulderCenter]);
}
}
}
//This method is used to position the ellipses on the canvas
//according to correct movements of the tracked joints.
//IMPORTANT NOTE: Code for vector scaling was imported from the Coding4Fun Kinect Toolkit
//available here: http://c4fkinect.codeplex.com/
//I only used this part to avoid adding an extra reference.
private void SetEllipsePosition(Ellipse ellipse, Joint joint)
{
Microsoft.Kinect.SkeletonPoint vector = new Microsoft.Kinect.SkeletonPoint();
vector.X = ScaleVector(640, joint.Position.X);
vector.Y = ScaleVector(480, -joint.Position.Y);
vector.Z = joint.Position.Z;
Joint updatedJoint = new Joint();
updatedJoint = joint;
updatedJoint.TrackingState = JointTrackingState.Tracked;
updatedJoint.Position = vector;
Canvas.SetLeft(ellipse, updatedJoint.Position.X);
Canvas.SetTop(ellipse, updatedJoint.Position.Y);
}
private float ScaleVector(int length, float position)
{
float value = (((((float)length) / 1f) / 2f) * position) + (length / 2);
if (value > length)
{
return (float)length;
}
if (value < 0f)
{
return 0f;
}
string r = Convert.ToString(value);
string path = #"C:\Test\MyTest.txt";
// This text is added only once to the file.
if (!File.Exists(path))
{
// Create a file to write to.
string createText = "Hello and Welcome" + Environment.NewLine;
File.WriteAllText(path, createText);
}
// This text is always added, making the file longer over time
// if it is not deleted.
//string appendText = "This is extra text" + Environment.NewLine;
File.AppendAllText(path, r);
// Open the file to read from.
string readText = File.ReadAllText(path);
return value;
}
void MainWindow_Unloaded(object sender, RoutedEventArgs e)
{
sensor.Stop();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
sensor.SkeletonFrameReady += runtime_SkeletonFrameReady;
sensor.ColorFrameReady += runtime_VideoFrameReady;
sensor.Start();
}
void runtime_VideoFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
bool receivedData = false;
using (ColorImageFrame CFrame = e.OpenColorImageFrame())
{
if (CFrame == null)
{
// The image processing took too long. More than 2 frames behind.
}
else
{
pixelData = new byte[CFrame.PixelDataLength];
CFrame.CopyPixelDataTo(pixelData);
receivedData = true;
}
}
if (receivedData)
{
BitmapSource source = BitmapSource.Create(640, 480, 96, 96,
PixelFormats.Bgr32, null, pixelData, 640 * 4);
videoImage.Source = source;
}
}
}
}
I think what you are looking for is getting the X, Y, Z coordiantes for certain Joints?
In this case add this code:
Vector3D ShoulderCenter = new Vector3D(skeleton.Joints[JointType.ShoulderCenter].Position.X, skeleton.Joints[JointType.ShoulderCenter].Position.Y, skeleton.Joints[JointType.ShoulderCenter].Position.Z);
Vector3D RightShoulder = new Vector3D(skeleton.Joints[JointType.ShoulderRight].Position.X, skeleton.Joints[JointType.ShoulderRight].Position.Y, skeleton.Joints[JointType.ShoulderRight].Position.Z);
Vector3D LeftShoulder = new Vector3D(skeleton.Joints[JointType.ShoulderLeft].Position.X, skeleton.Joints[JointType.ShoulderLeft].Position.Y, skeleton.Joints[JointType.ShoulderLeft].Position.Z);
Vector3D RightElbow = new Vector3D(skeleton.Joints[JointType.ElbowRight].Position.X, skeleton.Joints[JointType.ElbowRight].Position.Y, skeleton.Joints[JointType.ElbowRight].Position.Z);
Vector3D LeftElbow = new Vector3D(skeleton.Joints[JointType.ElbowLeft].Position.X, skeleton.Joints[JointType.ElbowLeft].Position.Y, skeleton.Joints[JointType.ElbowLeft].Position.Z);
Vector3D RightWrist = new Vector3D(skeleton.Joints[JointType.WristRight].Position.X, skeleton.Joints[JointType.WristRight].Position.Y, skeleton.Joints[JointType.WristRight].Position.Z);
Vector3D LeftWrist = new Vector3D(skeleton.Joints[JointType.WristLeft].Position.X, skeleton.Joints[JointType.WristLeft].Position.Y, skeleton.Joints[JointType.WristLeft].Position.Z);
This only defines the Vectors for the upper Body part as you can see. Just add the missing joints the way I did it.
You need following assemblies:
using System.Windows.Media;
using Microsoft.Kinect.Toolkit.Fusion;
using System.Windows.Media.Media3D;

iTextSharp Twisting CCITTFaxDecode extracted data with GetDrawingImage()

On certain images, when I call:
PdfImageObject pimg = new PdfImageObject(stream);
Image bmp = pimg.GetDrawingImage();
The Image that is returned is twisted. I've seen this before and it usually has to do with byte alignment but I'm not sure how to get around this.
The /DecodeParms for this object are /EndOfLine true /K 0 /Columns 3300.
I have tried using the GetStreamBytesRaw() with BitMiracle.LibTiff and with it I can get the data formatted properly although the image is rotated. I'd prefer for GetDrawingImage() to decode the data properly if possible, assuming that is the problem.
I could provide the PDF via email if requested.
Thanks,
Darren
For anyone else that runs across this scenario here is my solution. The key to this puzzle was understanding that /K 0 is G3, /K -1 (or anything less than 0) is G4 /K 1 (or anything greater than 0) is G3-2D.
The twisting happens when you try to make G3 compressed data fit into a G4 image which it appears that is what iTextSharp may be doing. I know it definitely does not work with how I have iTextSharp implemented in my project. I confess that I cannot decipher all the decoding stuff that iTextSharp is doing so it could be something I'm missing too.
EndOfLine didn't have any part in this puzzle but I still think putting line feeds in binary data is a strange practice.
99% of this code came from BitMiracle.LibTiff.Net - Thank you.
int nK = 0;// Default to 0 like the PDF Spec
PdfObject oDecodeParms = stream.Get(PdfName.DECODEPARMS);
if (oDecodeParms is PdfDictionary)
{
PdfObject oK0 = ((PdfDictionary)oDecodeParms).Get(PdfName.K);
if (oK0 != null)
nK = ((PdfNumber)oK0).IntValue;
}
using (MemoryStream ms = new MemoryStream())
{
using (Tiff tiff = Tiff.ClientOpen("custom", "w", ms, new TiffStream()))
{
tiff.SetField(TiffTag.IMAGEWIDTH, width);
tiff.SetField(TiffTag.IMAGELENGTH, height);
if (nK == 0 || nK > 0) // 0 = Group 3, > 0 = Group 3 2D
tiff.SetField(TiffTag.COMPRESSION, Compression.CCITTFAX3);
else if (nK < 0) // < 0 = Group 4
tiff.SetField(TiffTag.COMPRESSION, Compression.CCITTFAX4);
tiff.SetField(TiffTag.BITSPERSAMPLE, bpc);
tiff.SetField(TiffTag.SAMPLESPERPIXEL, 1);
tiff.WriteRawStrip(0, rawBytes, rawBytes.Length); //saving the tiff file using the raw bytes retrieved from the PDF.
tiff.Close();
}
TiffStreamForBytes byteStream = new TiffStreamForBytes(ms.ToArray());
using (Tiff input = Tiff.ClientOpen("bytes", "r", null, byteStream))
{
int stride = input.ScanlineSize();
Bitmap result = new Bitmap(width, height, pixelFormat);
ColorPalette palette = result.Palette;
palette.Entries[0] = System.Drawing.Color.White;
palette.Entries[1] = System.Drawing.Color.Black;
result.Palette = palette;
for (int i = 0; i < height; i++)
{
Rectangle imgRect = new Rectangle(0, i, width, 1);
BitmapData imgData = result.LockBits(imgRect, ImageLockMode.WriteOnly, pixelFormat);
byte[] buffer = new byte[stride];
input.ReadScanline(buffer, i);
System.Runtime.InteropServices.Marshal.Copy(buffer, 0, imgData.Scan0, buffer.Length);
result.UnlockBits(imgData);
}
}
}
/// <summary>
/// Custom read-only stream for byte buffer that can be used
/// with Tiff.ClientOpen method.
/// </summary>
public class TiffStreamForBytes : TiffStream
{
private byte[] m_bytes;
private int m_position;
public TiffStreamForBytes(byte[] bytes)
{
m_bytes = bytes;
m_position = 0;
}
public override int Read(object clientData, byte[] buffer, int offset, int count)
{
if ((m_position + count) > m_bytes.Length)
return -1;
Buffer.BlockCopy(m_bytes, m_position, buffer, offset, count);
m_position += count;
return count;
}
public override void Write(object clientData, byte[] buffer, int offset, int count)
{
throw new InvalidOperationException("This stream is read-only");
}
public override long Seek(object clientData, long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
if (offset > m_bytes.Length)
return -1;
m_position = (int)offset;
return m_position;
case SeekOrigin.Current:
if ((offset + m_position) > m_bytes.Length)
return -1;
m_position += (int)offset;
return m_position;
case SeekOrigin.End:
if ((m_bytes.Length - offset) < 0)
return -1;
m_position = (int)(m_bytes.Length - offset);
return m_position;
}
return -1;
}
public override void Close(object clientData)
{
// nothing to do
return;
}
public override long Size(object clientData)
{
return m_bytes.Length;
}
}

Uploading large files to dropbox in chunks using dropnet

I recently tried Dropnet API to connect dropbox app in my C# project. Everything works fine, but I want to upload large files through chunkupload request.
public void FileUpload()
{
string file = #"E:\threading.pdf";
int chunkSize = 1 * 1024 * 1024;
var buffer = new byte[chunkSize];
int bytesRead;
int chunkCount = 0;
ChunkedUpload chunkupload = null;
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
chunkCount++;
if (chunkCount == 1)
{
chunkupload = client.StartChunkedUpload(buffer);
}
else
{
chunkupload = client.AppendChunkedUpload(chunkupload, buffer);
}
}
}
var metadata = client.CommitChunkedUpload(chunkupload, "/threading.pdf", true);
}
The file size is 1.6 MB. When i Checked, first chunk contains 1 MB and second one contains 0.6MB but only 13 bytes data gets uploaded in each chunk. Could anyone point out problem here.
Update RestSharp to 104.4.0 to resolve this issue.
There's a problem with RestSharper that is used by Dropnet.
Each uploaded chunk uploads exactly 13 bytes
'System.Byte[]'
The problem is that array of bytes is converted to string using method 'AddParameter'.
I didn't dig too much. I'm trying to use UploadFile method.

How to create a single-color Bitmap to display a given hue?

I have a requirement to create an image based on a certain color. The color will vary and so will the size of the output image. I want to create the Bitmap and save it to the app's temporary folder. How do I do this?
My initial requirement came from a list of colors, and providing a sample of the color in the UI. If the size of the image is variable then I can create them for certain scenarios like result suggestions in the search pane.
This isn't easy. But it's all wrapped in this single method for you to use. I hope it helps. ANyway, here's the code to create a Bitmap based on a given color & size:
private async System.Threading.Tasks.Task<Windows.Storage.StorageFile> CreateThumb(Windows.UI.Color color, Windows.Foundation.Size size)
{
// create colored bitmap
var _Bitmap = new Windows.UI.Xaml.Media.Imaging.WriteableBitmap((int)size.Width, (int)size.Height);
byte[] _Pixels = new byte[4 * _Bitmap.PixelWidth * _Bitmap.PixelHeight];
for (int i = 0; i < _Pixels.Length; i += 4)
{
_Pixels[i + 0] = color.B;
_Pixels[i + 1] = color.G;
_Pixels[i + 2] = color.R;
_Pixels[i + 3] = color.A;
}
// update bitmap data
// using System.Runtime.InteropServices.WindowsRuntime;
using (var _Stream = _Bitmap.PixelBuffer.AsStream())
{
_Stream.Seek(0, SeekOrigin.Begin);
_Stream.Write(_Pixels, 0, _Pixels.Length);
_Bitmap.Invalidate();
}
// determine destination
var _Folder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
var _Name = color.ToString().TrimStart('#') + ".png";
// use existing if already
Windows.Storage.StorageFile _File;
try { return await _Folder.GetFileAsync(_Name); }
catch { /* do nothing; not found */ }
_File = await _Folder.CreateFileAsync(_Name, Windows.Storage.CreationCollisionOption.ReplaceExisting);
// extract stream to write
// using System.Runtime.InteropServices.WindowsRuntime;
using (var _Stream = _Bitmap.PixelBuffer.AsStream())
{
_Pixels = new byte[(uint)_Stream.Length];
await _Stream.ReadAsync(_Pixels, 0, _Pixels.Length);
}
// write file
using (var _WriteStream = await _File.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
var _Encoder = await Windows.Graphics.Imaging.BitmapEncoder
.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId, _WriteStream);
_Encoder.SetPixelData(Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
Windows.Graphics.Imaging.BitmapAlphaMode.Premultiplied,
(uint)_Bitmap.PixelWidth, (uint)_Bitmap.PixelHeight, 96, 96, _Pixels);
await _Encoder.FlushAsync();
using (var outputStream = _WriteStream.GetOutputStreamAt(0))
await outputStream.FlushAsync();
}
return _File;
}
Best of luck!

Downloading an Azure blob in chunks using WCF

I have been asked to provide a WCF service that allows a blob (potentially 1GB) to be downloaded in chunks as an offset byte[] for consumption by a Silverlight application. Essentially, the operation will have a parameter for number of bytes to offset and the max number of bytes to return, nothing complex I think.
The code I have so far is:
[OperationContract]
public byte[] Download(String url, int blobOffset, int bufferSize)
{
var blob = new CloudBlob(url);
using(var blobStream = blob.OpenRead())
{
var buffer = new byte[bufferSize];
blobStream.Seek(blobOffset, SeekOrigin.Begin);
int numBytesRead = blobStream.Read(buffer, 0, bufferSize);
if (numBytesRead != bufferSize)
{
var trimmedBuffer = new byte[numBytesRead];
Array.Copy(buffer, trimmedBuffer, numBytesRead);
return trimmedBuffer;
}
return buffer;
}
}
I have tested this (albeit with relatively small files < 2MB) and it does work, but my questions are:
Can someone suggest improvements to the code?
Is there a better approach given the requirement?
using (BlobStream blobStream = blob.OpenRead())
{
bool getSuccess = false;
int getTries = 0;
rawBytes = new byte[blobStream.Length];
blobStream.Seek(0, SeekOrigin.Begin);
int blockSize = 4194304; //Start at 4 mb per batch
int index = 0;
int documentSize = rawBytes.Length;
while (getTries <= 10 && !getSuccess)
{
try
{
int batchSize = blockSize;
while (index < documentSize)
{
if ((index + batchSize) > documentSize)
batchSize = documentSize - index;
blobStream.Read(rawBytes, index, batchSize);
index += batchSize;
}
getSuccess = true;
}
catch (Exception e)
{
if (getTries > 9)
throw e;
else
blockSize = blockSize / 2; // Reduce by half for each attempt
}
finally
{ getTries++; }
}
}
You could return the blob as a stream instead of a byte array. There is a code sample in a related question here: Returning Azure BLOB from WCF service as a Stream - Do we need to close it?
Note there are some restrictions on which bindings you can use when you return a stream.