Rotating images based upon exif image data

My current project involves using tablets to take picture and upload them to the server.

Once we started testing we noticed that the images were of different orientations.

We wanted the images to display the same so I have created the following rotation information:

#region exif image processing
public enum ExifOrientations : byte
{
    Unknown = 0,
    TopLeft = 1,
    TopRight = 2,
    BottomRight = 3,
    BottomLeft = 4,
    LeftTop = 5,
    RightTop = 6,
    RightBottom = 7,
    LeftBottom = 8,
}
 
public static System.IO.Stream RotateImageStream(System.IO.Stream stream, string filename)
{
    System.IO.Stream return_stream = stream;
 
    var fi = new System.IO.FileInfo(filename);
 
    var image_file = true;
 
    var image_format = System.Drawing.Imaging.ImageFormat.Jpeg;
    switch (fi.Extension)
    {
        case ".jpg":
        case ".jpeg":
            image_format = System.Drawing.Imaging.ImageFormat.Jpeg;
            break;
        case ".png":
            image_format = System.Drawing.Imaging.ImageFormat.Png;
            break;
        case ".gif":
            image_format = System.Drawing.Imaging.ImageFormat.Gif;
            break;
        case ".bmp":
            image_format = System.Drawing.Imaging.ImageFormat.Bmp;
            break;
        default:
            image_file = false;
            break;
    }
 
    if (image_file)
    {
        var image = System.Drawing.Image.FromStream(stream);
        var rotated_image = RotateImageByExif(image);
        var ms = new System.IO.MemoryStream();
 
        rotated_image.Save(ms, image_format);
        return_stream = ms;
    }
 
    return_stream.Position = 0;
 
    return return_stream;
}
 
public static System.Drawing.Image RotateImageByExif(System.Drawing.Image image)
{
    var orientation_property_id = 274;
    var pi = image.PropertyItems.Where(x => x.Id == orientation_property_id).FirstOrDefault();
    if (pi != null)
    {
        var orientation = (ExifOrientations)BitConverter.ToInt16(pi.Value, 0);
        switch (orientation)
        {
            case ExifOrientations.Unknown:
            case ExifOrientations.TopLeft:
                break;
            case ExifOrientations.TopRight:
                image.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX);
                break;
            case ExifOrientations.BottomRight:
                image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
                break;
            case ExifOrientations.BottomLeft:
                image.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipY);
                break;
            case ExifOrientations.LeftTop:
                image.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipX);
                break;
            case ExifOrientations.RightTop:
                image.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
                break;
            case ExifOrientations.RightBottom:
                image.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipY);
                break;
            case ExifOrientations.LeftBottom:
                image.RotateFlip(System.Drawing.RotateFlipType.Rotate270FlipNone);
                break;
        }
    }
 
    return image;
}
 
#endregion

Setting up a Asp.net page for callback

On my current project I wanted to add simple callback functionally. After searching google for a while and finding various solutions that I couldn’t get to work I came across the following posting from Microsoft:

Implementing Client Callbacks Programmatically Without Postbacks in ASP.NET Web Pages

It was very straight forward and I was able to get my callback going.

The following is the code behind that I used to get it working:

  void Page_Load(object sender, EventArgs e) {
    PageCallbackSetup();
  }
 
  /// <summary>
  /// Setup for the callback for a page
  /// </summary>
  private void PageCallbackSetup() {
    var cm = Page.ClientScript;
 
    // Client side function that will be executed when callback is finished
    var cbReference = cm.GetCallbackEventReference(this, "arg", "ReceiveServerData", "");
 
    // Function that is called to start the callback to the server
    var callbackScript = "function CallServer(arg) {" + cbReference + "; }";
 
    // Register script with the page for the callback
    cm.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true);
  }
 
  #region ICallbackEventHandler Members
 
  /// <summary>
  /// Returns result to client
  /// </summary>
  /// <returns>string of results from the server</returns>
  public string GetCallbackResult() {
    return "This is the time from the callback: " + DateTime.Now.ToString();
  }
 
  /// <summary>
  /// Raised when the callback takes place
  /// </summary>
  public void RaiseCallbackEvent(string eventArgument) {
  }
 
  #endregion

The following is the HTML markup:

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
 
<!doctype html>
<html lang="en">
<head runat="server">
  <title></title>
  <script type="text/javascript">
    function ReceiveServerData(arg) {
      MessageFromServer.innerText = arg;
    }
  </script>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <input type="button" value="Callback" onclick="CallServer('CallSubmittedFrom')" />
    <br />
    <span id="MessageFromServer"></span>
  </div>
  </form>
</body>
</html>

visual studio 2010 becomes slow after saving on Windows 7

My Visual Studio 2010 has had an issue with running real slow. What I was doing was rebooting my machine to help with the issue. But I have several things loaded and it would get old loading the whole machine again. So finally I looked online and found the following post:

visual studio 2010 becomes slow after saving on Windows 7

By using the following 6 steps if fixed the issue for me:

  1. Right-click the Start button
  2. Choose Properties
  3. Uncheck both checkboxes under the Privacy group
  4. Click the Apply button
  5. Re-check both checkboxes
  6. Press OK

Force update DataGridView when editing new row

I was having an issue that a new row that I was editing was not being updated and saving. It would update if I moved to another row, but from a user friendly view this does not work. I don’t want to have the user move to another row so that the update will work.

I tried several things:

dataGridView1.EndEdit();

Didn’t work!

Tried:

bindingSource1.EndEdit();
dataGridView1.EndEdit();

Didn’t work!

Tried:

dataGridView1.EndEdit();
bindingSource1.EndEdit();

Didn’t Work!

After several google searches I came across a mention of useing the BindingContext.

Why is the default behavior for the DataGridView to not update the changes in a new row when save is done, I am at a total loss. I wonder how many developer hours are lost trying to get this to work!

I finally created an extension method as follows:

public static void EndCurrentEdit(this DataGridView dgv) {
  dgv.BindingContext[dgv.DataSource].EndCurrentEdit();
  dgv.EndEdit();
}

To call it I use the following:

dataGridView1.EndCurrentEdit();

In winforms getting a parent control of a given type

On my baseball scoring application I needed to get a parent control to share data between controls.

Because controls can have several levels between them it takes some recursion to get to the needed control.

The following generic method will get the first control of a given type.

public static T GetParent<T>(this Control ctl) where T : Control {
  var retVal = default(T);
  var parent = ctl;
  while (parent.Parent != null) {
    parent = parent.Parent;
    if (parent is T) {
      retVal = (T)parent;
      break;
    }
  }
  return retVal;
}

C# AppActivate

I wanted to be able to activate an application using C#.

By using the following it will activate the application:

[DllImportAttribute("User32.dll")]
private static extern int SetForegroundWindow(int hWnd);
 
private bool AppActivate(string titleName) {
  var success = true;
  var process = Process.GetProcesses()
                .Where(p => p.MainWindowTitle.StartsWith(titleName))
                .FirstOrDefault();
  if (process != null) {
    SetForegroundWindow(process.MainWindowHandle.ToInt32());
  }
  else {
    success = false;
  }
  return success;
}

First parts setups method for call to User32.dll so SetForegroundWindow can be called from it.

Next is a method that is called to first get the process that starts with the title name passed to it and if found then calls SetForegroundWindow.

To call the Calculator app call AppActivate method as following:

var success = AppActivate("Calc");

Getting a count of checked items in a CheckBoxList

The following function uses JQuery and will get the number of checked items in a CheckBoxList.

<script type="text/javascript">
    function checkBoxListCount() {
        var count = $('input[type=checkbox][id*=CheckBoxListId]:checked').length;
        if (count == 0) {
            return false;
        }
        else {
            return true;
        }            
    }
</script>

Where [id*=CheckBoxListId] is change CheckBoxListId to the name of CheckBoxList.

Adding a index for items in a linq query

It is possible to add a index to a linq query as follows:

var list = new List<string> { "Zero", "One", "Two", "Three", "Four", "Five" };
var indexed = list.Select((l, i) => new { Item = l, Index = i });

Getting a list of files from a ZipPackage

In my current project I needed to get a list of files that were in a zip file. In the past when I needed to do this I would have used J# and just added a reference. Since J# is not included I wanted to see if there was a different way to achieve this.

Microsoft has since added a System.IO.Packaging namespace that includes the ZipPackage class. I added a reference to WindowsBase.dll because that is where the ZipPackage class is.

As I researched about using the class I found that it does not provide a public method to get a list of the files. As I looked at the data I noticed a field named _zipArchive of the type MS.Internal.IO.Zip.ZipArchive. I looked further in the field and noticed a property named ZipFileInfoDictionary which is a System.Collections.Hashtable.

By using reflection I was able to access the _zipArchive and the ZipFileInfoDictionary to retrieve the file list.

I have created the following extension method called GetFileList to return the list of files in the zip file.

public static List<string> GetFileList(this ZipPackage zp)
{
    List<string> list = null;
 
    try
    {
        var zipArchiveProperty = zp.GetType().GetField("_zipArchive", 
                                    BindingFlags.Static 
                                    | BindingFlags.NonPublic 
                                    | BindingFlags.Instance);
 
        var zipArchive = zipArchiveProperty.GetValue(zp);
 
        var zipFileInfoDictionaryProperty = 
            zipArchive.GetType().GetProperty("ZipFileInfoDictionary", 
                                            BindingFlags.Static 
                                            | BindingFlags.NonPublic 
                                            | BindingFlags.Instance);
 
        var zipFileInfoDictionary = 
            zipFileInfoDictionaryProperty.GetValue(zipArchive, null) as Hashtable;
 
        var query = from System.Collections.DictionaryEntry de in zipFileInfoDictionary
                    select de.Key.ToString();
 
        list = query.ToList();
    }
    catch (NotSupportedException nse)
    {
        throw;
    }
    return list;
}

To call the method I used the following:

private List<string> GetFileListFromZipFile(FileInfo zipFileName)
{
    List<string> list = null;
 
    try
    {
        var zp = ZipPackage.Open(zipFileName.FullName, 
                                 FileMode.Open, 
                                 FileAccess.Read, 
                                 FileShare.Read) as ZipPackage;
        list = zp.GetFileList();
    }
    catch (NotSupportedException nse)
    {
        throw;
    }
    return list;
}

I ended up having to use the FileShare.Read because I was getting a file in use exception.

C# version of VB.Net DateAdd

I have been working on a application that is dealing with dates. I wanted to use a function like DateAdd but that is part of VB.Net.

I created a function that is the same as the DateAdd:

public enum DateInterval
{
    Day,
    DayOfYear,
    Hour,
    Minute,
    Month,
    Quarter,
    Second,
    Weekday,
    WeekOfYear,
    Year,
}
 
private DateTime DateAdd(DateInterval interval, double number, DateTime dateValue)
{
    DateTime dtm = dateValue;
    // DateInterval.DayOfYear and DateInterval.Weekday appear the same
    // as DateInterval.Day.
    // Looking at http://msdn.microsoft.com/en-us/library/hcxe65wz(v=vs.71).aspx 
    // also seems to indicate they are the same as DateInterval.Day.
    switch (interval)
    {
        case DateInterval.Day:
        case DateInterval.DayOfYear:
        case DateInterval.Weekday:
            dtm = dateValue.AddDays(number);
            break;
        case DateInterval.Hour:
            dtm = dateValue.AddHours(number);
            break;
        case DateInterval.Minute:
            dtm = dateValue.AddMinutes(number);
            break;
        case DateInterval.Month:
            int months = Convert.ToInt32(number);
            dtm = dateValue.AddMonths(months);
            break;
        case DateInterval.Quarter:
            int quarters = Convert.ToInt32(number);
            dtm = dateValue.AddMonths(quarters * 3);
            break;
        case DateInterval.Second:
            dtm = dateValue.AddSeconds(number);
            break;
        case DateInterval.WeekOfYear:
            int weekOfYear = Convert.ToInt32(number);
            dtm = dateValue.AddDays(weekOfYear * 7);
            break;
        case DateInterval.Year:
            int years = Convert.ToInt32(number);
            dtm = dateValue.AddYears(years);
            break;
    }
    return dtm;
}
 
private DateTime DateAdd(string interval, double number, DateTime dateValue)
{
    Dictionary<string, DateInterval> dct = new Dictionary<string, DateInterval>
    {
        {"d", DateInterval.Day},
        {"y", DateInterval.DayOfYear},
        {"h", DateInterval.Hour},
        {"n", DateInterval.Minute},
        {"m", DateInterval.Month},
        {"q", DateInterval.Quarter},
        {"s", DateInterval.Second},
        {"w", DateInterval.Weekday},
        {"ww", DateInterval.WeekOfYear},
        {"yyyy", DateInterval.Year},
    };
    DateInterval di = DateInterval.Day;
    if (dct.ContainsKey(interval))
    {
        di = dct[interval];
    }
    else
    {
        throw new ArgumentException("Argument 'interval' is not a valid value.");
    }
    return DateAdd(di, number, dateValue);
}