Chris Cavanagh’s Blog

WPF Photo Print (.NET 3.5 SP1)

July 29, 2008 · 18 Comments

UPDATE: Source code now available here and on CodePlex.

Here’s a small WPF utility to help make ad-hoc photo printing a little easier.

image

It borrows a couple of features from Picasa / iPhoto, but with a few notable differences:

  • No need to import your photos into a “walled” library (great if your photos are on a network share like mine, or just want an ad-hoc print from a memory card).
  • Never changes the source image and doesn’t require version history.
  • All operations are additive and vector-based.  Currently supports rotate (90° clockwise), crop (with aspect ratios) and straighten (up to 45° each way).
  • It’s fast (no need to “Apply” changes or undo them later).
  • Potential to add bitmap / shader effects (designed with it in mind, but not implemented yet)…

image

You should be able to get borderless prints out of it easily enough (or print to XPS for further processing).  It uses the standard print dialog and works fine on my HP Photosmart C7250 (haven’t tested elsewhere yet).  I plan to add extra options like “Save as…” and “Copy to clipboard” when time (and inclination) allows… :)

You can get the app here (only 45kb unzipped!).  Note: You’ll need .NET 3.5 SP1.  Later I’ll either post source code here or maybe put it on Codeplex (if any interest from you guys).

Enjoy!


Categories: .NET

18 responses so far ↓

  • Alvin Ashcraft // July 29, 2008 at 6:59 am | Reply

    Cool stuff! I would be interested in checking out the source. You should post to CodePlex.

  • Dew Drop - July 29, 2008 | Alvin Ashcraft's Morning Dew // July 29, 2008 at 7:32 am | Reply

    [...] WPF Photo Print (.NET 3.5 SP1) (Chris Cavanagh) [...]

  • Vijay // August 14, 2008 at 6:08 am | Reply

    Can you share the source code of print functionality?

  • Chris Cavanagh // August 19, 2008 at 11:09 pm | Reply

    Alvin, Vijay – I’ll get the source published as soon as I clean it up (need to remove some obsolete code). Until then, here’s a snip of the printing code:
    var image = new TransformedImage { Drawing = transformable.Drawing };

    var capabilities = dialog.PrintQueue.GetPrintCapabilities( dialog.PrintTicket );
    var pageAspect = capabilities.PageImageableArea.ExtentWidth / capabilities.PageImageableArea.ExtentHeight;

    if ( ( transformable.AspectRatio > 1 ) != ( pageAspect > 1 ) )
    {
    image.LayoutTransform = new RotateTransform( 90, 0.5, 0.5 );
    }

    var size = new Size( capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight );

    image.Measure( size );
    image.Arrange( new Rect(
    new Point( capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight ),
    size ) );

    dialog.PrintVisual( image, transformable.Name );

    The TransformedImage class is just a WPF control that renders a Drawing inside an image (using a DrawingBrush). All the photo composition is done with Drawing objects.

    The only other thing this code does is auto-rotate the final image before printing, to match the paper orientation (I’m not actually sure if it needs to do this; maybe the printer can handle that itself).

    Hope this helps!

  • WPF Photo Print - Source code « Chris Cavanagh’s Blog // August 22, 2008 at 1:12 am | Reply

    [...] 22, 2008 · No Comments You can get the source code for my WPF Photo Print utility here.  There are a couple obsolete files in there, but you can consider those my [...]

  • WiredPrairie - Some WPF stuff… // August 22, 2008 at 7:53 pm | Reply

    [...] From Chris, WPF Photo Print. [...]

  • Rick Engle // October 17, 2008 at 2:51 pm | Reply

    Hey Chris this is tremedous! Does your code also support resizing an image and saving it?

    Rick

  • Chris Cavanagh // October 17, 2008 at 2:56 pm | Reply

    Rick – It doesn’t yet, but it’d be very easy to implement. It’s on my todo list… :) (I’ll probably put it on CodePlex)

  • Rick Engle // October 27, 2008 at 8:12 pm | Reply

    Awesome, looking forward to it if you get a chance!
    Rick

  • Ashish // March 10, 2009 at 12:36 am | Reply

    Hi,
    I am new to Silverlight.
    Can anyone suggest how can I use this code with a silverlight application?

    Ashish

  • Chris Cavanagh // March 10, 2009 at 8:09 am | Reply

    Hi Ashish – Most of the code is built around WPF’s Drawing classes (DrawingGroup, GeometryDrawing etc). Often it’s possible to migrate classes from WPF to Silverlight with some help from Reflector (now maintained by Red Gate). Let me know if you plan to give that a try; I might be able to help a bit :)

  • Ashish // March 10, 2009 at 11:22 pm | Reply

    Hi Chris,

    Thanks for a quick reply. What i want is, the project which you have created in WPF i want to create same application using Silverlight. What I tried to do is copied all the classes to silverlight application. I’m getting an error while trying to add reference to the System.Printing. It says “You can’t add a reference to System.Printing.dll as it was not built against the Silverlight runtime. Silverlight projects will only work with Silverlight assemblies.”. Could you please tell me how can I resolve this issue.
    Thanks in advance.

    Ashish

  • ricardo // September 17, 2009 at 2:04 pm | Reply

    Hi
    I want to know how can separate the photo cropping (selection) part into a separate component, but everything is too much related, can you give me a hint

  • Chris Cavanagh // September 17, 2009 at 2:43 pm | Reply

    ricardo – You probably want to look in these places:

    Preview.xaml – Find the local:Crop DataTemplate. That renders the opaque area (as an OpacityMask). It databinds to the Crop transformation (Crop.cs)
    Preview.xaml.cs – Creates an instance of thhe CropAdorner (in cropSelect_Loaded) and attaches it to the preview. Also handles mouse events and adjusts the adorner to match.
    CropAdorner.cs – (based on darrelp’s project on CodeProject: http://www.codeproject.com/KB/WPF/CropAdorner.aspx) – Renders the drag handles.

    Hope this helps!

  • ricardo // September 17, 2009 at 3:13 pm | Reply

    mm it is getting really complicate to split it…
    because I need to create a crop adorner which I can supply an frameworkelement to be cropped, but it seems that you are passing a transform item, and this is related to various classes that dont need….
    any more hints?

  • ricardo // September 17, 2009 at 3:35 pm | Reply

    can you explain me this line

    its at main windows, I dont get where is the CurrentItem..Transformations.CurrentItem comes

  • Chris Cavanagh // September 21, 2009 at 1:31 pm | Reply

    Ashish – Sorry for my slow reply! Silverlight provides very little support for printing right now (but apparently this will improve in Silverlight 4). One option might be to send the image and transformation details to your server and let it return a rendered image; from there the user should be able to print using their browser…

  • Chris Cavanagh // September 21, 2009 at 1:34 pm | Reply

    Ricardo – Can you email me the details? (didn’t show up in blog comment)… (ricardo at chriscavanagh.com). CurrentItem.Transformations.CurrentItem is just referening the selected transformation in the UI (the first CurrentItem will be the image, Transformations.CurrentItem will be the selected transformation for that image).

Leave a Comment