Dev Direct Solution Center

For more information and to buy this product...

How to create a custom image from a Photoshop PSD template using Aurigma Graphics Mill 4.5 for .NET

  For a copy of the sample project please click here to download and install the product evaluation.

Introduction

This sample illustrates how we can combine user data, which in this case is input via an ASP.Net web form wrtten in C#.Net/VB.Net, with a predefined Photoshop template, to instantly generate and display a custom JPEG image.

Detail

Creating personalized graphics is a widespread task. Users sometimes want to create fancy greeting cards, booklets and business cards. All these graphics contain some common features like background, logos, pictures, as well the features that differ: names, photos, dates, descriptions, prices, etc.

Altering each card’s content manually is certainly cumbersome - so inserting content on-the-fly saves a lot of trouble. You can fetch content from a database (especially helpful for mass X-Mas greetings or for generating booklets with differing prices). Or, sometimes you might want your web site visitors to fill in the required fields via a web form. For example, your staff could appreciate a PSD template to generate personal business cards by merely typing their name. So, this is the task that we successfully solve today.

Setup

To access the source code for this project you need to register to receive a trial license key – this will take about 2 minutes. In the trial package you will find not only the PSD Add-on itself but the Graphics Mill imaging SDK. After the installation, all project files will be found in the following directory:
C:\Program Files\Aurigma\Program Files\Aurigma\Graphics Mill 4.5 for .NET 2.0\Web Demos Source Code

The code projects for this sample are located in the GraphicsMillAjaxCS and GraphicsMillAjaxVB directories for the C# and VB .Net versions respectively.

To run the sample, browse to:
http://localhost/GraphicsMill45Ajaxcs/BussinessCardEditor.aspx
for C#.Net, or
http://localhost/GraphicsMill45Ajaxcs/BussinessCardEditor.aspx
for VB.Net

Getting Started

First of all, we need to create a PSD template with high resolution (e.g. 300 DPI). Add the logo, captions and placeholders (i.e. text layers that are inserted during processing to be rendered into the final card). As a result we will get something like this:

This example is contained in the file "Sample files\businesscard.psd" located beneath the installation directory.

In our example we use 6 text layers as placeholders (they are enclosed in square brackets in the above figure). It is important to distinguish these layers during processing, which is why we assign each layer an individual name:

  • FullName
  • Position
  • PhoneFax
  • Mobile
  • Email
  • Website

    The Layers window in Photoshop should look like this:

    Warning
    When creating any artwork in Adobe Photoshop, remember that Advanced PSD Add-on does not provide 100% PSD format support and that if a Photoshop feature is not listed in the Advanced PSD Add-on overview, it will most likely be disregarded when you process your PSD file. That is why it is strongly recommended that you do not use vector masks, adjustment layers, etc. If you cannot avoid using some of PSD features, feel free to contact us to discuss possible solutions.

    Creating an Editor Page

    After we have prepared one or more PSD templates, it is time to start building our web application. The first step is to design the user interface.

    Create new ASP.NET page, and add a reference to the Graphics Mill controls like this:

    ASPX
    <%@ Register Assembly="Aurigma.GraphicsMill.AjaxControls" Namespace="Aurigma.GraphicsMill.AjaxControls" TagPrefix="cc1" %>

    Next add the BitmapViewer control which will be used to display a business card preview. Set the parameters of BitmapViewer as follows:

    ASPX
    <cc1:BitmapViewer ID="BitmapViewer1" runat="server" BitmapStateEnabled="False" BorderColor="Gray" ScrollBarsStyle="Auto" BorderStyle="Solid" BorderWidth="0px" BrowserJpegQuality="80" PreviewImageEnabled="False" Width="335px" Height="200px" Zoom="0.3" ZoomQuality="High"> </cc1:BitmapViewer>
    • As our original template has high resolution it will be too large to be displayed. To make it load faster and to reduce traffic, we will shrink the image displayed in the control. To do this, set the Zoom property to 0.35 (35%) value.
    • To provide the highest quality during the zoom operation, set the ZoomQuality property to High value.
    • One more trick to improve loading speed - disable the low-resolution preview image. Set the PreviewImageEnabled property to false.
    • To avoid calculating and hardcoding width and height of the control (to display the image without scrollbars), let's have the control to get these values automatically. It can be easily done using the ZoomMode. Just set it to the ZoomControl value.
    • To optimize the performance, set the BitmapStateEnabled property to false. It will switch off bitmap state maintenance which is unnecessary in our case (since we re-generate the bitmap during each page load).

    Now add 6 server Input (Text) controls which will be used to input user's personal details. Let's name our Input (Text) controls as follows: TextFullName, TextPosition, TextPhoneFax, TextMobile, TextEmail, and TextWebsite.

    The layout of this page should be something like this:

    Processing Placeholders in the Template

    The code which processes the PSD template and replaces placeholders with user data reuses the RasterizePsd method described in the Merging Layers topic in our online documentation.

    To process the template add the following code into the Page_Load event handler:

    VB.Net
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not Page.IsPostBack Then Dim updatedLayers As New System.Collections.Specialized.NameValueCollection updatedLayers.Add("FullName", TextFullName.Value) updatedLayers.Add("Position", TextPosition.Value) updatedLayers.Add("PhoneFax", TextPhoneFax.Value) updatedLayers.Add("Mobile", TextMobile.Value) updatedLayers.Add("Email", TextEmail.Value) updatedLayers.Add("Website", TextWebsite.Value) BitmapViewer1.Bitmap = RasterizePsd(Server.MapPath("TestImages/BusinessCard.psd"), updatedLayers) End If End Sub
    C#.Net
    protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { System.Collections.Hashtable updatedLayers = new System.Collections.Hashtable(); updatedLayers.Add("FullName", TextFullName.Value); updatedLayers.Add("Position", TextPosition.Value); updatedLayers.Add("PhoneFax", TextPhoneFax.Value); updatedLayers.Add("Mobile", TextMobile.Value); updatedLayers.Add("Email", TextEmail.Value); updatedLayers.Add("Website", TextWebsite.Value); BitmapViewer1.Bitmap = RasterizePsd(Server.MapPath("TestImages/BusinessCard.psd"), updatedLayers); } }

    After the page is loaded into browser, you will see the customized business card.

    Using Remote Scripting: Updating Business Card Without Roundtrips

    For better interactivity, we can have the business card updated on each text field change. To do it, we need to use the remote scripting approach (an AJAX-like technique which enables data acquisition from server without roundtrips). This is done in two steps:
    1. Add a server-side method marked with the RemoteScriptingMethodAttribute attribute. In this method, we will just fill the texFields collection with updated text values and render the business card template again.
    2. Call this method from the JavaScript using the invokeRemoteMethod function (see the Remote Scripting Approach (Web Controls) topic for more details on this).

    Here is the code for the remote method:

    VB.Net
    <Aurigma.GraphicsMill.WebControls.RemoteScriptingMethod()> _ Public Sub Refresh() Dim updatedLayers As New System.Collections.Hashtable updatedLayers.Add("FullName", Request.Form("TextFullName")) updatedLayers.Add("Position", Request.Form("TextPosition")) updatedLayers.Add("PhoneFax", Request.Form("TextPhoneFax")) updatedLayers.Add("Mobile", Request.Form("TextMobile")) updatedLayers.Add("Email", Request.Form("TextEmail")) updatedLayers.Add("Website", Request.Form("TextWebsite")) BitmapViewer1.Bitmap = RasterizePsd(Server.MapPath("TestImages/BusinessCard.psd"), updatedLayers) End Sub
    C#.Net
    [Aurigma.GraphicsMill.WebControls.RemoteScriptingMethod()] public void Refresh() { System.Collections.Hashtable updatedLayers = new System.Collections.Hashtable(); updatedLayers.Add("FullName", Request.Form["TextFullName"]); updatedLayers.Add("Position", Request.Form["TextPosition"]); updatedLayers.Add("PhoneFax", Request.Form["TextPhoneFax"]); updatedLayers.Add("Mobile", Request.Form["TextMobile"]); updatedLayers.Add("Email", Request.Form["TextEmail"]); updatedLayers.Add("Website", Request.Form["TextWebsite"]); BitmapViewer1.Bitmap = RasterizePsd(Server.MapPath("TestImages/BusinessCard.psd"), updatedLayers); }

    Note: You may have noticed that text fields are accessed via the form rather than through the Value property of Input (Text) control (as it is implemented in the Page_Load). It is caused by the fact that the remote method is called before the initialization of these controls. Such behavior is stipulated for optimization purposes to process the callback before the initialization of all controls. It eliminates full page initialization.

    We will call this remote method on each modification of our text fields. In other words, text fields should have onChange=refresh(); event handlers, for example:

    ASPX
    <input id="TextPosition" style="width: 160px" type="text" runat="server" value="Your Position" onchange="refresh();" onkeyup="refresh();" />

    And the refresh function should be defined as follows:

    Javascript
    var bitmapViewer1; window.onload=function(){ bitmapViewer1 = document.getElementById("<%=BitmapViewer1.ClientID%>"); bitmapViewer1.addStatusChanged(bitmapViewer1_StatusChanged); } var needToRefresh = false; function refresh(){ if (!needToRefresh){ needToRefresh = true; window.setTimeout("delayedRefresh()", 2000) } } function delayedRefresh(){ if (bitmapViewer1.getStatus() != "Busy"){ needToRefresh = false; bitmapViewer1.invokeRemoteMethod("Refresh", null); } } function bitmapViewer1_StatusChanged(){ if (needToRefresh){ window.setTimeout("delayedRefresh()", 1000) } }

    This code may appear a bit tricky. Here, we avoid executing our remote method too often. We restrict the method to be called not sooner than 2 seconds after the previous call, and not sooner than 1 second since the previous refresh.

    Conclusion

    This project has demonstrated how we can populate a predefined Photoshop template from our code and generate an output graphic for display on the page.

    We could add many advanced features to this page including uploading graphics files for addition to the generated image and the applicaiton of special effects to the graphic.

    Product

    In this solution we used Advanced PSD Add-on, which is soon to be renamed to Aurigma PSD Reader.

    Actually, this PSD Add-on is a small part of this powerful SDK.

    Visit Aurigma Inc. for more information and more samples.