Preview PDF files as images on your website

by Damiaan Peeters 9. January 2017 20:41

We got a question, and said yes.  If we can do that?  Yes, we can! When you get back at the office you get a cold shiver along your spine when you discover there is no NuGet package available for you to install.

What was the question

The client regularly publishes articles in magazines and journals.  They repost the article on their own website.  Content marketing they told me.  On their old website they had to upload a PDF and a thumbnail of the pdf. 

But dear web builder, you can do better right? Umbraco is a CMS build for content editors and is easy to extent.  Please put the thumbnail automatically inside our website.

The search

There seem to be several products on the market for several thousands of dollars. But the client would not be willing to pay for licenses. The typical conversion could have been like this:

You are building on a large ecosystem of free and open software, right? Yes, dear client. And PDF is an open format right? Yes, dear client. I could not be the first ever to ask this, right? No, dear client.  Can't you ask your friendly colleagues of this friendly CMS?  Sure, dear client. (*)

I tried a few .net managed libraries which I found on the internet.  But most of the managed free PDF libraries you find online are

  1. not working,
  2. incomplete,
  3. in beta
  4. provide a very small subset of what you can do with PDF.
  5. Or simple do not support rendering a PDF to another digital format (like PNG or JPEG).
  6. Or are a wrapper around (some obscure) unmanaged DLL’s

The only way out would be to start a new managed library to read PDF files.  Which can’t be too hard, because it’s mostly PostScript, right?  But going down that path, took already several hours.  Precious time which we did not had.  It was Christmas holiday after all.

From the commercial pallet of products, I did tried Imazen’s Resizer.Net and it worked, but having 2 image processors was complete overkill, and was not playing along with ImageProcessor.  However that could have been me messing around with various dll’s.

Because I lost all hope at finding a complete managed (.net) solution, and because I already found several NuGet packages wrapping GhostScript, we decided to settle.  GhostScript is a pretty mature product after all.

The solution: using ImageProcessor and GhostScript(.net)

We choose GhostScript.Net to be our wrapper around GhostScript.  Mostly because the logo was very nice, certainly compared to the other wrappers available. 

Further we did a small POC proving it worked.  The code is pretty simple:

var rasterizer = new GhostscriptRasterizer();
rasterizer.Open(pdfUri, lastInstalledVersionOfGhostScript, false);
System.Drawing.Image img = _rasterizer.GetPage(_desiredXDpi, _desiredYDpi, pageNumber);
rasterizer.Close();

This very simple code did what we needed.  It converted the (first) page of a PDF to an image format.  It was very simple to create a .Net handler for this to create an image.  But we wanted to have a better dev experience.  And also be able to resize easier.

ImageProcessor to the rescue

The best advice from last year (2016) is: build on the shoulder of giants.  If you have not met James South, it’s a giant.  He is way over 2 meter big, and strong as an elephant. He knows to drink, like a real Scott, and moved to Australia a catch his own food with his bear hands.  Or not.  But he IS a craftsmen and builder of the marvelous ImageProcessor, used and distributed along with Umbraco.

So we wondered if Imageprocessor could support a different file format, like… PDF, we would have a solution.

It turns out that is not too hard.  Just create a new class inherited from FormatBase, override the appropriate members.  If you override the LOAD method of the base class, you could load a PDF, rasterize it, and pass the System.Drawing.Image object to ImageProcessor.  It will handle everything for you?

For example: /media/1234/myPublication.pdf?width=500

Let us serve other clients to!

We do have other clients uploading PDF’s from time to time.  I am pretty sure that we will be installing this plugin to avoid the next support request: “image not showing on website”.

The code is available on github: https://github.com/dampee/ImageProcessor.Plugins.Pdf/

A NuGet package is available too: https://www.nuget.org/packages/ImageProcessor.Plugins.PDF/

 

Let me know what you think of the package.

 

(*) this is fiction, they are actually very nice and polite.  It is only me, myself and I taking blame for the path we took.

 

 

 

 

Thread safety and adding items to dictionaries

by Damiaan Peeters 13. August 2013 14:52

I was looking at some code from Zack Owens “Multi Tenancy Sample”.  He has some clever code, a ThreadSafeDictionary with a GetOrAdd method. I love the idea!  (code below for my own reference)

The problem with a dictionary, is that – apparently - .Net puts somewhere a system wide lock to ensure thread safety on a dictionary anyway.  That’s the reason that, if you are working with huge dictionaries with lots of READS, you might bump into some performance issues.  In such cases, you could (and should) use the ConcurrentDictionary from the System.Collections.Concurrent namespace.  And if you are looking at this class, visit the BlockingCollection from the same namespace also, still trying to wrap my head around it, but it is ultra important.  You just feel it when reading through the MSDN article.

   /// DON’T USE THIS CODE – You probably want a System.Collections.Concurrent.ConcurrentDictionary

   using System;
   using System.Collections.Generic;
   using System.Threading;

   /// <summary>
   /// Dictionary that has a "GetOrAdd" method that is thread-safe
   /// </summary>
   /// <typeparam name="TKey">Dictionary key</typeparam>
   /// <typeparam name="TValue">Dictionary value</typeparam>
   public class ThreadSafeDictionary<TKey, TValue> : Dictionary<TKey, TValue>
   {
       /// <summary>
       /// Lock for adding values
       /// </summary>
       private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();

       /// <summary>
       /// Gets a value or adds the value in a thread-safe way
       /// </summary>
       /// <param name="key">Key in the dictionary</param>
       /// <param name="defaultValue">Delegate that will get the value</param>
       /// <returns>Value from the dictionary with given <paramref name="key"/></returns>
       public TValue GetOrAdd(TKey key, Func<TValue> defaultValue)
       {
           // enter read lock
           this.cacheLock.EnterReadLock();

           try
           {
               // test if value is in the dictionary
               if (this.ContainsKey(key))
                   return this[key];
           }
           finally
           {
               // exit read lock
               this.cacheLock.ExitReadLock();
           }

           // enter write lock
           this.cacheLock.EnterWriteLock();
           try
           {
               if (!ContainsKey(key))
                   this.Add(key, defaultValue());
               return this[key];
           }
           finally
           {
               // exit write lock
               this.cacheLock.ExitWriteLock();
           }
       }
   }

Converting a PHP API to a C# implementation

by Damiaan Peeters 11. January 2010 13:32

I have this web service I want to use. The supplier only provides a PHP example to use the API. It is not a standard SOAP or REST service, but a custom Http POST based command.  This means that you that you either have to write

http://www.asp.net/downloads/archived/migration-assistants/php-to-aspnet/

Because I had no Visual Studio installed, ready to be launched, i used the command line conversion. 

C:\Program Files\Microsoft Corporation\PHP to ASP.NET Migration Assistant>PHPConvert.exe "c:\source\PhpSource" /out "C:\source\AspDotNetVersion”

The port of the code was successful. Most of the code was converted to c#.  A lot of conversion warnings popped up, but most of them where not imposing any severe problems.

Code clean-up

A manual code clean-up is advised.  For example, this code comes clearly from an unmanaged environment:

  1. dpublic virtual void  useSecure(bool val)
  2.         {
  3.             if ((val == true) && (val.GetType() == true.GetType()))
  4.             {
  5.                 this.Secure = true;
  6.             }

Why should you check the type of “val” at runtime?  This is already done by the compiler.  A simple “ if (val== true) “  would be sufficient.  Or in this case even shorter:

  1. d        public virtual void useSecure(bool val)
  2.         {
  3.                 this.Secure = val;
  4.         }

Other things to clean up are links to magic-quotes, cURL and other specific PHP stuff.

Calling the API

Calling the API means in PHP that you do a socket write and read. For example, in PHP one would do:

$sock = fsockopen("ssl://".$this->ApiUrl["host"], 443, $errno, $errstr);

Because every effort is done to maintain the original architecture by the conversion tool.  The convertor tool added a PHP namespace containing extra support classes for duplicating the original (php) functionality. The previous line of code is thus converted to:

sock = PHP.NetworkSupport.OpenSocket("ssl://" + this.ApiUrl["host"], 443, errstr);

The OpenSocket function is a wrapper function with one line (with some additional simple error handling):

returnValue = (System.Net.HttpWebRequest)System.Net.WebRequest.Create((System.String)Target); // + ":" + System.Convert.ToInt32(Port));

Although this is neat, I like the native .Net HttpWebRequest and HttpWebResponse Classes.  So I took the code from my previous blog post: Http Post using C#, adapted it a bit and removed almost 80 lines of the converted code.

My problem with the wrapper functions created by the convertor tool, is that they use System.Object parameters and also return a System.Object.  So for readability and maintenance reasons, I started immediately converting this to some strongly typed code.

Conclusion

I was very pleased with this tool.  I saved literally hours typing, and it took me (only) a few hours of refactoring.   Refactoring meant:

  • removing unused functionality (magicQuotes, cURL, …)
  • removing unnecessary type checks using Relfection
  • removing calls to wrapper functions when I had decent managed .Net code available in my library

And just now I started thinking that it may have been faster implementing a custom WCF implementation. 

Famous .Net websites found on the web (Part 2)

by Damiaan Peeters 1. September 2009 10:30

Ok, I admit.  I know my blogging rhythm is very low this year, it's about the opposite of my 'normal' day-to-day life rhythm. But I prepared in the past months this blog post…

From time to time I stumble upon famous web sites using .Net (part 1).  I would like to add some sites to the list.

Let me know if know any other big web sites using .Net technology, so I can complete the list.

TeamViewer – Desktop Sharing over the internet
image
Intel Download Center
image
Hardrock Café’s Memorablia  using Silverlight technology, Deepzoom.
image

Have you ever tried zooming really deep?  Look at this post: How to really show of with deepzoom

CRDC.Be - Official Belgium Database for Number Portability
image

Stanford Engineering – Sub site of university

image

Rabobank.be – online bank (and know sponsor of cycling)
image
DoubleClick – online advertising
image
International Telecommunication Union
image

Tags:

.Net

How to really show off Deepzoom technology

by Damiaan Peeters 31. August 2009 11:57

What is Deepzoom

Deepzoom is a product build on Silverlight technology.  It gives you the ability to smoothly zoom and pan on images.  The loading time is incredibly short because only parts of images are send over the network. This type of browsing can be compared with viewing imagery on google maps, live earth.

A nice example is the Memorablia of the HardRock café.  I searched for a guide on the internet, on how to get as deep as possible on the pictures.  This examples goes even a few levels deep.

If you search on the web for Deepzoom, you will find much more details and explanation.

Where to start

Go to http://memorabilia.hardrock.com/

and look for “Paul McCartney – The Beatles Letter from Paul and Beatles autographs”.  (Item number: 043311).

Finding this item, can be easily done by:

  • be clicking on “The Beatles” on the left side, or
  • use the search on the top right of the screen like this:
    image   or image

The item you are looking for is this one: 
 image

Go deeper

Have you already noticed the stamp on the left top of the envelop?  That is where you should go.  Use your mouse scroll wheel to enlarge this item.

As you will see this is not a normal stamp.  These are pictures of various buildings.  (Does anyone know which buildings these are?)

image

Zoom into the picture of the 3th row, 2nd column.  If I’am not mistaken, this is the Seattle hardrock Café.

image

If you thought this is cool, go to left below the middle of the image, you will see some white suites

image

image

Then zoom in on “The Beatles” Doll's image in the middle.

image

This last doll’s are available as a separate item  in Memorablilia: The Beatles “Bobb’n Head” dolls, and is available under Item number 051228.  The cool thing is, this contains some embedded video as shown below (click More Info – Video).

Do it yourself

You can make yourself Deepzoom content by using deepzoom composer.  Try it out, and let me know if you archived something spectacular.

Managed Extensibility Framework Introduced By Bart

by Damiaan Peeters 19. August 2009 17:54

I have been thinking several years about how to implement Extensibility in a decent manner for one of my applications.  The problem is that as a sole freelance developer, implementing extensibility is not something you NEED.  It is more a ‘nice to have’.  At the end of 2008, I found the MEF (Managed Extensibility Framework).  But due to a lack of time and lack of articles about it, never started investigating into it.  I admit, I do not always jump on the newest beta technologies right away.

Unfortunately, when you search for some information on the MEF CodePlex website on how it exactly works, it doesn’t really encourage you to read further…  Try to dive in the first to links on the topic “Where to go next”

  • First there is:  Learn more about MEF .  Completely correct, but a 100% cryptic message for dummies.  Telling someone you have to start with a container or a catalog without explaining what a catalog or container is, is not very convincing.
  • Or take the programming guide, just a few steps to do very complex things.  My problem was not “how to”, but I wanted to understand what I was doing.  Adding references adding class or method attributes can be done by my little sister, but would she know what she has done?  I Guess not, I even bet she doesn’t understand these terms.

So, I watch out for months about articles covering the Managed Extensibility Framework (MEF).  Articles explaining the basics. Telling me what it exactly is, or what the basics are.  Some sort of “Hello World” for advanced programmers, but “MEF dummies”.

Earlier this week I found the article an article, written by a Belgian fellow, now working in Microsoft Redmond.
His blog posts tend to be very technical material for advanced LINQ adepts or Expression Tree lovers. This time he covered “MEF for Dummies”, just what I needed.  I’ve written before about the mouse-hating code-lover called Bart De Smet. (See a previous post “Bart De Smet gone mad about extension methods”.) 

Bart proved his excellent writing capabilities in his blog post written earlier this month. If you are interested in MEF, then read  A Whirlwind Tour through the Managed Extensibility Framework.  I highly recommend it.

Congratulations Bart, it was easy to read, even humorous. And most of all it was very understandable.  Thank you very much!

Tags: ,

.Net

Dependency Matrix & Application metrics

by Damiaan Peeters 29. December 2008 00:44

I got today back on an old controls assembly.  I am using DevExpress controls for more than a year.  But there are still some forms using my old control library.  It would have been a mess cleaning up this old directory, until i realized that this could be done very easily using NDepend.

I loaded the assemblies and used the dependency matrix to find out where the controls are used.

image

Especially the “Remove Empty… Rows and columns” image  gave me a quick overview of controls which still where used on some forms and should have been replaced by other ones.

Furtermore i looked – just for fun – at the “abstractness versus instability” graph created by NDepend.  I took a screenshot:

image 

As you can see, it ain’t looking good.  When i started developing this application, i never heard of abstractions and instability was my middlename. Well… None of my assemblies are in “zone of uselessness” (upper right corner), but i know the “zone of pain” very well.

The numbers aren’t lying:

Application Metrics

Number of IL instructions: 1006520
Number of lines of code: 121799
Number of lines of comment: 22251
Percentage comment: 15
Number of assemblies: 11
Number of classes: 849
Number of types: 896
Number of abstract classes: 2
Number of interfaces: 10
Number of value types: 4
Number of exception classes: 0
Number of attribute classes: 0
Number of delegate classes: 0
Number of enumerations classes: 33
Number of generic type definitions: 36
Number of generic method definitions: 5
Percentage of public types: 86,27%
Percentage of public methods: 80,31%
Percentage of classes with at least one public field: 2,23%

I know i can do better  :-)

Tags:

.Net

Big companies discovered .Net

by Damiaan Peeters 8. September 2008 17:27

I was surfing today and I noticed that some web sites of big companies where using .Net.
This doesn't mean that .Net is there main technology, but the extension is at least used in the URL...

McAfee

They use it in the FAQ's... here

image

 

Fabricom GTI (Suez)

image

At their main page: http://www.fabricom-gti.com

Dell

image

At their main site...  http://www.dell.com

Yahoo

image

Probably they are not really using .Net, but it is a .Net file on there domain anyway...
On this survey link: http://surveylink.yahoo.com/wix/p0473306.aspx

Tags:

.Net

NDepend

by Damiaan Peeters 21. June 2008 08:58

A few days ago I received my NDepend license. 

What is NDepend

On their web site (http://www.ndepend.com), it states that :

NDepend is a tool that simplifies managing a complex .NET code base.

So in other words, (also on the web site)

Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code.

Out of my experience, I know - I really know - that bad designed software is a nightmare to maintain.  Worsted of all is that most of the time is it horribly coded and badly documented.  I've done seen in the past, and I am still struggling today.  It's easy to guess where the problems are, or how you could make the application better.  Because guessing is most of the time not the proven to be good, scientists created something like "metrics". 

Metrics measure your software, code base or even your software design.  NDepend uses these metrics and also the dependencies between your assemblies to tell you more about your application.

More about NDepend later!

Eval Statement and .Net Runtime Compilation (retry)

by Damiaan Peeters 9. May 2008 11:44

Yes I come from a VBA environment.  Microsoft Access all the way.  Last years I am into .Net but I was still missing my "good old" Eval statement.  A colleague triggered my curiosity and I started digging for a solution.

We dive into 2 methods.  The first is using the Microsoft Script Control, the second is the Runtime Compilation.

[more]

The easiest solution is probably to take the "Good Old" eval method from where it is available.  This means that you will need to set a reference to: COM Microsoft Script Control 1.0

MSScriptControl.ScriptControlClass mScriptControl; mScriptControl = new MSScriptControl.ScriptControlClass(); mScriptControl.Language = "VBScript"; mScriptControl.AllowUI = false;  mScriptControl.Reset(); try {    retval = mScriptControl.Eval(s);     } catch{ /* ... */ } 

You have to admit, this isn't to difficult.
This is well described on vb-tips.com

Another solution would be Compilation at Runtime. 

The simplest example I found was at EggheadCafe: Build a Custom .NET "EVAL" Provider.  It is created for VB, but can easily be changed to C#.

For archiving purposes, here is the code...

VBCodeProvider c = new VBCodeProvider();ICodeCompiler icc = c.CreateCompiler();CompilerParameters cp = new CompilerParameters();cp.ReferencedAssemblies.Add("system.dll");cp.ReferencedAssemblies.Add("system.xml.dll");cp.ReferencedAssemblies.Add("system.data.dll");cp.CompilerOptions = "/t:library";cp.GenerateInMemory = true;StringBuilder sb = new StringBuilder("");Debug.WriteLine(sb.ToString());// look at this to debug your eval stringCompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());System.Reflection.Assembly a = cr.CompiledAssembly;object o;MethodInfo mi;o = a.CreateInstance("PAB.PABLib");Type t = o.GetType();mi = t.GetMethod("EvalCode");object s;s = mi.Invoke(o, null);return s;

To compile some c# code at runtime I found the Runtime Compilation (A .NET eval statement) article on CodeProject.  This is a library which cuts out the compiler references etc. If you use this 'Evaluator' class, you can call a e.g. a StringChanger method as described below.  This code is also available on the mentioned page as example.

string myCode = "s =+ \" TEST\"; return s";

MethodResults stringChanger = null;StringBuilder source = new StringBuilder();source.Append("public string StringChanger(string s)");source.Append(Environment.NewLine);source.Append("{");source.Append(Environment.NewLine);source.Append(myCode);source.Append(Environment.NewLine);source.Append("}");try{ stringChanger = Eval.CreateVirtualMethod( new CSharpCodeProvider().CreateCompiler(), source.ToString(), "StringChanger", new CSharpLanguage(), false);}catch(CompilationException ce){ MessageBox.Show(this, "Compilation Errors: " + Environment.NewLine + ce.ToString()); return;}try{ output.Text = (string)stringChanger.Invoke(inputString.Text);}catch(System.Reflection.TargetInvocationException tie){ MessageBox.Show(this, "Method-Thrown Exception: " + Environment.NewLine + tie.InnerException.ToString()); return;}

We learned today that there are many possibilities with the System.Reflection and the System.CodeDom.Compiler namespaces.

Who.I.am

Certified Umbraco Master, Part of Umbraco Certified partner comm-it, .Net and Azure developer, seo lover. Magician in my spare time.

Month List