RotateImage Flag no longer supported?

Hi!

In the past I occasionally used the RotateImage flag of the GenICam.ini file to rotate images by multiples of 90°. In CVB 14.0 I did not find any flag in the Device Discovery options that replaces this entry - is that option gone?

(see also https://forum.commonvisionblox.com/t/rotate-an-image/70?u=illusive and https://forum.commonvisionblox.com/t/set-image-rotation-from-api/1376/2?u=illusive…)

Hi @taserface,

:cvb: 14.0 does in principle still support the RotateImage flag, but as you mention Device Discovery, I guess you are using the 3rd generation acquisition stack. Here the image is opened without consulting the GenICam.ini file, therefore the flag from the file is not evaluated.

Furthermore, the 3rd generation stack has been designed for the possibility that the image dimension and location on the sensor is not fixed. In such a scenario, the use of the image rotation becomes less and less intuitive, therefore this feature has not been added to the 3rd generation stack.

However, there is a function in the CVCImg.dll that mimics the behaviour of the RotateImage flag: CreateRotatedImageMap. This function will not actually manipulate image data - it will just change the image size and VPAT parameters to create a rotated view on the image’s memory. In other words: Calling it will take less than a millisecond.

Unfortunately this method was so far not added to the object oriented APIs CVB.Net, CVB++ and CVBpy - but at least for CVB.Net and CVB++ it is not too hard to introduce it via a workaround. For C# for example you could add it as an extension method as follows:

  public enum RotationMap
  {
    By0Degrees = 0,
    By90Degrees = 1,
    By180Degrees = 2,
    By270Degrees = 3
  }

  public static class Workaround
  {
    [DllImport("CVCImg")]
    [return: MarshalAs(UnmanagedType.U1)]
    internal static extern bool CreateRotatedImageMap(IntPtr imgIn, int rotation, out IntPtr imgOut);

    public static MappedImage Map(this Image imgIn, RotationMap step)
    {
      if (imgIn.IsDisposed)
        throw new ObjectDisposedException(imgIn.GetType().Name);

      var links = imgIn.Planes.ToArray();
      IntPtr hImage = IntPtr.Zero;
      if (!CreateRotatedImageMap(imgIn.Handle, (int)step, out hImage))
        SystemInfo.ThrowLastError(true);

      // this looks a little dodgy because the ctor of MappedImage is internal,
      // so we can only invoke it with the aid of reflection...
      var ctor = typeof(MappedImage).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
        new Type[] { typeof(IntPtr), typeof(ShareObject), typeof(ImagePlane[]) }, null);
      return (MappedImage)ctor.Invoke(new object[] { hImage, ShareObject.No, imgIn.Planes.ToArray() });
    }
  }

You’d then call it as follows:

      var imgSrc = Image.FromFile($"{Environment.GetEnvironmentVariable("CVB")}\\Tutorial\\Clara.bmp");
      var img90deg = imgSrc.Map(RotationMap.By90Degrees);
2 Likes