Saturday, May 10, 2014

How to invoke the Adobe Bridge CC - Photo Downloader on any arbitrary folder

As you have seen in my post Digital photography workflow I use the photo downloader from Adobe bridge as the corner stone of my workflow.  Sometimes, I am in a rush and I need to take a copy of what is in the memory card and keep it somewhere for safekeeping until I have time to process it.  What I have to do then is once I am ready, copy the folder content that was stored for safekeeping into a new cleaned up memory card and start bridge to download the images.

Here is a technique so that you do not need this copy back (which can be slow if you are copying 32 GB of images back onto a memory card).

Let assume that you have copied the memory card content to a folder say

h:\backup\memory card from houston trip

what you need to do is to look into Windows Explorer for a drive letter not in use in your computer at the moment.  Lets say this is drive P:.  You type the following command at a command prompt:

subst p: "h:\backup\memory card from houston trip"

This will create a drive P: with the content of the original memory card.  Then you type the following long command line (for Adobe Bridge CC, not sure if older version work the same) where P: represent your newly created drive with the subst command above:

"C:\Program Files\Adobe\Adobe Bridge CC (64 Bit)\photodownloader\Photodownloader.exe" module=photodownloader params mode=direct devType=volume priDevId="P:"

And voila! You should then see the familiar Adobe Bridge CC - Photo Downloader window.  That's all folks.

Tuesday, March 4, 2014

Des élections au Québec, pourquoi?

Madame la première ministre Marois,

Je ne vous demanderai pas quelles sont vos motivations car elles sont trop évidentes.  La poursuite de l’opportunité prime avant tout autre chose malheureusement.  Je ne suis qu’un simple citoyen du Québec mais je vous demande une question au nom de tous les québécois et québécoises.  Comment justifiez-vous aux contribuables québécois la dépense de fonds publics (estimé par le directeur général des élections en 2012 à $78 millions) en considérant déclarer des élections générales au Québec seulement 18 mois après avoir été élue au gouvernement? N’est-il pas adéquat de s’en référer à un vote de non confiance lorsqu’on est situation de gouvernement minoritaire comme vous l’êtes présentement?

Je compte très fort sur le discernement de tous les québécois et québécoises à ne pas être dupes et de se souvenir de la leçon apprise par l’honorable David Peterson le 6 septembre 1990 en Ontario lorsqu’il crut de bon escient de déclarer des élections après moins de trois ans au gouvernement.

Je n’ai aucun espoir de recevoir une réponse de votre part car il m’est très clair que ce gaspillage ne vous importe pas le moindrement du monde.  Cependant devant un tel cynisme je me devais de poser la question au nom de tous ceux qui doivent toujours payer la note.

Mario François Jauvin,
Cantley, Québec

P.S. Il est malheureux que Mme Marois soit la seule député de l’Assemblée nationale qui pense ne pas être nécessaire d’afficher son courriel ici :http://www.assnat.qc.ca/fr/deputes/index.html . Heureusementpauline.marois@assnat.qc.ca n’est pas trop difficile à trouver. On verra bien si le bureau de la première ministre « permettra » aux québécois et québécoises de continuer à l’utiliser après sa publication ici.

CC;
Philippe Couillard, Chef de l'opposition officielle
François Legault, Chef de la Coalition avenir Québec
Françoise David, Québec solidaire
Téléjournal, Ici Radio-canada
Céline Galipeau, Chef d'antenne du Téléjournal de Radio-Canada
Bernier et cie, Ici Radio-Canada
Alexandre Poirier, journaliste Astral
Annabelle Caillou, Journaliste
Richard Martineau, Journaliste au Journal de Montréal
Jacques CHAGNON, Président de l'Assemblée nationale
Jean-Marc Fournier, Whip en chef de l'opposition officielle
Marjolain Dufour,  Whip en chef du gouvernement
Justin Trudeau, Chef du Parti libéral et député pour Papineau (Québec)

Thursday, September 6, 2012

Ajuster les paramètres de confidentialité sur Facebook


·         Choisi l’option Paramètres de confidentialité

Clique sur modifier les paramètres dans l’option ici-bas:

Choisi l’option que tu désires dans la rubrique ici-bas (mois j’ai toujours choisi amis depuis le début):



Je recommande fortement à tout le monde de réviser avec soin tous les paramètres de confidentialité.

Wednesday, April 18, 2012

Agile programming on steroids

I was reading my posts from 2007 (Wow, 5 years ago, a lot has changed) about Agile programming and Ruby on Rails (RoR).  Although I used RoR on only 1 project, it seemed a great thing because at that time things such as Spring Roo did not exist. Now with a simple Roo script, followed by some Java code touch-ups one can achieve the same kind of flexibilities that RoR provides using an industry proven language on an set of industry proven platforms (WebSphere, Weblogic, Tomcat, JBoss, etc....) with little risk and reusing our existing farm of coders/developers.  Wow, long live Java.

Is there a real need for RoR, I don't think so.  Except perhaps for legacy reason!  HA HA HA! Please contradict me with your comments.  Just keep it civil.

When I have time, I shall write an entry illustrating the above Spring Roo example. In the meantime you can look at the example roo scripts in the Spring Roo distribution.

Thursday, February 23, 2012

Handling multipart form data in Spring 3.1

Introduction

Multipart mime encoded is a format used to transmit binary and arbitrary data in 1 single HTTP request transaction. In this post, I will describe how to create and process multipart form data using Spring 3.1, the leading industry standard java application framework for creating Java web application.  I will start the discussion from the user perspective by talking about two main use cases and will expand it by describing how these two use cases translate into 7 possible application system use cases.

Use Cases

Here are some use cases of this feature:

  1. A browser submits or uploads a file to a web server using an HTML page. This is by far the most common use case of the multipart form data feature. A multipart is required because the form data and the file are both included in the request body.
  2. A java program (a java application or servlet instance) sends multipart form data to a web server (most likely a web service).  This is a much less infrequent use case of multipart form data

System Use Cases


The two use case scenarios above create the following 7 system use cases.

  1. An HTTP servlet creates the multipart form data request and sends it to a web server
  2. An HTTP servlet receives a multipart form data in the response and processes it
  3. An HTTP servlet receives the multipart form data request and processes it
  4. An HTTP servlet creates a multipart form data response and sends it back
  5. A java application creates the multipart form data request and sends it to a web server
  6. A java application receives a multipart form data in the response and processes it
  7. An internet browser (Internet Explorer (IE) or Firefox) creates the multipart form data request and sends it to a web server

See “Figure 1: System user case scenarios” below for an illustration where the numbers represent the system use cases:

Please note that IE 6 and 8 and Firefox 6 (and to the best of my knowledge all other browsers) do not support the ability to process multipart form data in an HTTP response.

Figure 1: System user case scenarios

Of the previous 7 system use cases, number 1 and 5 are very similar and so are number 2 and 6.  The actual SPRING code is actually identical as will be illustrated below.

System use case 1 and 5 (including system use case 7 which is implemented by browsers) are the most common system use case.  Even though system use case 7 is more common than system use case 1 and 5, there is ample valid requirements and system use case 1 and 5 is very well implemented in the RestTemplate Spring class.

System use case 3 is implemented in Spring 3.1 with the help of Apache Commons IO and FILEUPLOAD libraries.  This support is not enabled by default in Spring and must be enabled. One way to do so is to add the following bean in the application context xml file:

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<beans:property name="maxUploadSize" value="10000000"/>
</beans:bean>

System use case 4, 2 and 6 represent system use cases that are not in use in the industry.  I could not find any published example of this.  I have seen people asking questions on this topic in forums like StackOverflow but I have not found a single published case of its use. If you know of such a case, please let me know.

As far as Spring is concerned, system use case 4 is actually implemented but with a bug.  The created HTTP response does not include the Content-Length HTTP header which makes it difficult for (invalid) system use case 2 and 4 which find no support in Spring 3.1.  The consequence is that in order to implement them, one would have to refit the Apache commons fileupload code to handle an HTTP response instead of an HTTP request.  Based on my test implementation, this is not easy, not portable nor extensible. It is also not desirable as multipart form data was designed to transport series of data or parts between a user and an application[1], which implies an HTTP request.

Implementation of the system use case using Spring 3.1


Creating a multipart form data HTTP request (system use case 1 and 5)


The following code will both work in an HTTP servlet and a java application and uses Spring’s RestTemplate.  Please note that the HttpMessageConverter referred to as mhmc (MultipartHttpMessageConverter) below corresponds to a test implementation of a message converter that can read multipart form data so as to implement the invalid system use case 2 and 6 and fix the Content-Length bug when creating the HTTP response in system use case 4.  Please note that it is not recommended to write such an implementation for the reasons listed further down.  I did it just to test all 6 system use case. If you want to test without such an implementation the other system use cases then just omit the call to setMessageConverters on the restTemplate.

// Replace Spring’s XmlAwareFormHttpMessageConverter with
// the one fully supporting multipart form data
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> mc = restTemplate.getMessageConverters();
for (Iterator<HttpMessageConverter<?>> iterator = mc.iterator(); iterator.hasNext();) {
    HttpMessageConverter httpMessageConverter = (HttpMessageConverter<?>) iterator
          .next();
    if (httpMessageConverter instanceof XmlAwareFormHttpMessageConverter) iterator.remove();
}
mc.add(mhmc);
restTemplate.setMessageConverters(mc);
ResponseEntity<MultiValueMap<String, CommonsMultipartFile>> eresp = null;
MultiValueMap<String, HttpEntity<FileSystemResource>> parts = new LinkedMultiValueMap<String, HttpEntity<FileSystemResource>>();
HttpHeaders fileHeaders = new HttpHeaders();
fileHeaders.add("Content-type",
     MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileSystemResource r = new FileSystemResource(SAMPLE_REQUEST_FILE);
HttpEntity<FileSystemResource> sample_file = new HttpEntity<FileSystemResource>(
     r, fileHeaders);
parts.add("file1", sample_file);
HttpHeaders reqheaders = new HttpHeaders();
// Set any custom HTTP request headers you need here
Reqheaders.set("Custom-App-Header", "custome-value");
HttpEntity<MultiValueMap<String, HttpEntity<FileSystemResource>>> ereq = new HttpEntity<MultiValueMap<String, HttpEntity<FileSystemResource>>>(
                parts, reqheaders)
;

Receiving a multipart form data HTTP request (system use case 3)


The feature to receive multipart form data from an HTTP request in Spring comes in the form of a pluggable MultipartResolver object and is not enabled by default.  Spring provides two MultipartResolver implementations.  One makes use of the Commons FileUpload in Servlet 2.x containers and the other one for use with Servlet 3.0 multipart request parsing.  To enable the Servlet 2.x MultipartResolver, you follow the previously mentioned application context bean definition. On this has been done, all that is left is to use the request handler annotation below:

public ResponseEntity<MultiValueMap<String, Object>> processMultipart(@RequestPart("file1") ByteArrayResource inputfile, HttpServletRequest request) {

This is really quite simple and inputfile.getBtyeArray() will contain the binary data of the part encoded as file1 in the system use case 1 and 5 above. I will explain the ResponseEntity<MultiValueMap<String, Object>> return type in the next section.

Creating a multipart form data HTTP response (system use case 4)


As indicated, this use case is not valid but it is almost supported by Spring 3.1.  I say almost because the HTTP response created by this process does not have an HTTP Content-Length header which can make it inefficient to process this response. The code is very similar to the code for creating an HTTP request. This due to the fact that the building of either the HTTP request or the HTTP response is handled by Spring’s HttpMessageConverter interface.

Set<MediaType> mediaTypes = new HashSet<MediaType>();
mediaTypes.add(MediaType.MULTIPART_FORM_DATA);
// Tell SPRING to only support this media type, regardless
// of what the Accept header said
request.setAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE,
     mediaTypes);
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
HttpHeaders fileHeaders = new HttpHeaders();
fileHeaders.add("Content-type",
     MediaType.APPLICATION_OCTET_STREAM_VALUE);
ByteArrayResource r = new ByteArrayResource(BINARY_RESPONSE) {
    @Override
    public String getFilename() throws IllegalStateException {
     return "file2.txt";// this will create the filename=
                    // attribute on the content-disposition
                    // tag
    }
};
HttpEntity<ByteArrayResource> file = new HttpEntity<ByteArrayResource>(
     r, fileHeaders);
parts.add("file2", file);
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.add("Custom-Header1", "custom-value");
respHeaders.add("Content-type", MediaType.MULTIPART_FORM_DATA_VALUE);
ResponseEntity<MultiValueMap<String, Object>> eresp = new ResponseEntity<MultiValueMap<String, Object>>(
     parts, respHeaders, HttpStatus.CREATED);

Then, all that is left to do is for the servlet to return the eresp variable.  This is where the return type of ResponseEntity<MultiValueMap<String, Object>> in the previous section comes from.  Please remember that the HTTP response created by such a process will not contain the Content-Length HTTP header.  If you create a subclass of the XmlAwareFormHttpMessageConverter, modify the writeMultipart (see below) and wire this new class into Spring(see below) then you can add the Content-Length header.

ByteArrayOutputStream baos=new ByteArrayOutputStream();

… (existing code as is)

writeParts(baos, parts, boundary);
writeEnd(boundary, baos);
byte[] baosba=baos.toByteArray();
outputMessage.getHeaders().setContentLength(baosba.length);
outputMessage.getBody().write(baosba);

Receiving multipart form data in an HTTP response(system use case 2 or 6)

As previously indicated, there is no support in Spring to perform this at all.  One has to take the existing code in org.springframework.web.multipart.commons.CommonsFileUploadSupport and adapt it to a message converter.  This make the code both non portable and non extensible and I do not advise it.


[1] See RFC 2388, section 2 and 3

Saturday, April 11, 2009

Jauvin Digital Photography Workflow

What is a workflow? Basically, it is a series of steps to follow in order to achieve a given result. My digital photography workflow is what I recommend any digital photographer (novice or expert) follow to go from taking the shots all the way to having them in your photo library. Why come up with instructions like that? With digital photography if you do not follow a well thought out recipe you find yourself soon (very soon indeed) with a humongous mess due to the number of shots one can take using this technology. Shots are absolutely free, are they not?

This workflow assumes that you have a good digital camera capable of shooting in raw mode (or see wikipedia on this topic). It also assumes that you have Photoshop to do the post processing. That's it. No hidden clause, no long list. Just those two requirements and the will to learn and use this workflow religiously for all of your digital photography experience. Well, I assume you have Photoshop CS4 but this should mostly work with Photoshop CS3 or CS2. I also must say that this will work either on the Mac or PC version of Photoshop. Thanks to Ben Long for pointing this out to me. I would love to hear your comments and or suggestions using the comment feature at the bottom of the article.

One last note, I made liberal use of screen shots in this article which have all been reduced and centered for the benefit of the reader. Note however that if you click on them you will go to a new window where you can see the original screen shot in all its splendor! All you have to do once you are finished admiring them is to click the back button on your browser to return to the article just where you had left (at least on modern browsers).

So lets start and enjoy.

Access photos from digital camera

My first advice is to never connect your camera to your PC to transfer images. This is both clumsy, slow, often requires use of special camera vendor software with mixed and varied results and uses the battery in your camera for no purposes whatsoever. Instead, invest in a economical memory card reader. These device cost between 20-50 dollars and are well worth their price. I suggest a model that support multiple card format so that you can use it in other contexts (such as memory cards in your phone, other digital cameras). Once you have plugged your memory card into the card reader and connected it to the PC using the USB port, you will get a screen similar to this:


Remember the drive letter where your memory card appeared as (drive D: in my case) as you will use it later.

Initiate transfer of photos to your PC

Then you should start the Adobe Bridge (from your Photoshop installation). Once running, you can select the menu "Get Photos from Camera" as show below:


If you are using Photoshop CS4 as is my case, you also have this little icon in the top left area of the Bridge window:



Select memory card for download

Since this is most likely the first time you have use the photo downloader (this is the program invoked when doing the previous step) from Bridge, you will be using the standard window layout. You should then select the drive corresponding to the memory card that was accessed previously using the drop down menu under "Get Photos from:". In my case it was drive D: as in the picture below:



You will see a dialog box searching for media. Once finished, you should click on the advanced button to view the window with thumbnails for all of the photos on the memory card. This will help you make decisions in the next steps.



Select destination folder

Here is the advanced view of the photo downloader window below. Make sure that you leave all thumbnails selected as we want to always select and process all images on the memory card. I will get back to why we do this later under the advanced options step so for now, please bear with me. You should click on the browse button to locate the folder where you want to copy your images to.


In my case, I selected folder "J:\My Pictures". I would like to make a parenthesis on this very important point. As an amateur photographer and I also believe as a professional one too, it is very important to have two very important attributes for your photo library:

  1. Mobility: you want to be able to look at your pictures wherever you are in different context so that you can show case them in front of a client or simply refer to them when on the road.
  2. Backup: you must always make backup copies of your photos and although I do not yet have this builtin the workflow, I will be making hints to this.
To achieve these attributes (especially the first one) I strongly advise you to acquire a small USB powered external drive (as for example the Western Digital Passport which now comes in 500GB size). I say USB powered because they are much smaller and not having to look for a wall plug is extremely handy especially in a rush or using a laptop. This is what my J: drive is in this workflow.

Destination subfolder settings

You will see under location the mention [6 subfolders] appended to the selected folder. This is due to the default selection of "Shot Date (yyyymmdd)" for the subfolder option and means that with the images in the selected memory devices, 6 different subfolders would be created. Instead I recommend to select the "Custom Name" option from the "Create Subfolder(s):" drop down as below:


Once selected, a text box below will appear with the words "Enter custome name here" already selected:



Destination subfolder name

Do not click in the text box. This will deselect the text and you will have to erase it manually. Simply start typing the name of the subfolder you want to create for this operation. But before you start typing, let me give you my blurb first.

Inside the memory card, I could have pictures from either one shoot or multiple shoots as is the case here. When you have multiple shoots (even on the same day) here is my suggestions on how to proceed. First pick one particular shoot in your list of images. This is where the thumbnails view in the advanced settings is useful. This could be the most important one or the one with the largest number of images but it does not really matter. In my case, I decided that the shoot I selected was the one with pictures of my mother-in-law's birthday party and hence I picked the subfolder name "Cumpleaños de mi suegra" (spanish version of Mother-in-law birthday) and then I prefixed YYYYMM which is the year and two letter month number when the pictures were taken followed by a space so that the full subfolder name is:

"200903 Cumpleaños de mi suegra"

Please note the 0 (zero) prefix in the month number when there is only 1 digit in the month number. This is important for sorting folder names in Windows Explorer or Bridge.

Destination filenames

When copying files from the memory card, names such as IMG_2574.CR2 are meaningless. Therefore, you should select the option "Shot Date (yyyymmdd)" from the "Rename Files:" drop down menu:


Once selected, a text box below the drop down will appear with a number. This number will increment for each image and will be kept and maintained by this instance of Adobe Bridge.

Advanced options

The remaining options should be selected as follow. "Open Adobe Bridge" should be selected and will cause a new windows with Bridge to be opened once all of the processing is completed. "Convert To DNG" should be selected to convert the camera RAW proprietary format (Canon RAW in my case) to the Adobe digital negative format (DNG). This will create smaller files and will store different camera RAW files in one consistent format. Please note that there is no difference in the information stored by a DNG file and the camera RAW file, i.e. the image quality is identical. One major distinction is that metadata is kept within the DNG file as opposed to side XMP files as in camera RAW formats. This makes it easier to handle and move raw files around. "Delete Original Files" should be selected as this will guaranty that once you have processed a file you will never be confused and process it again. This is a new option in Bridge CS4.

When I started in this business of processing images on my memory card, I was trying to be purist and make sure I processed images 1-107 as shoot xyz then images 108-256 as shoot abc etc. Invariably, I would always get confused and go nuts trying to figure out whethere I had or not processed this image and I either missed some files or had duplicates. In order to avoid this I humbly ask all men and women of the earth doing digital photography to adopt the following brain dead and hence, error free, paradigm:

  • If a file resides on your memory card, it has not been processed
  • If a file has been processed, it will not be on your memory card
This means that at any time, you pick up your camera, your memory card and off you go. You don't have to worry whether these files on your card have been processed and hence can be erased when you are on site and doing the shoot. You know they have not been processed so if you are out of space, get your backup memory card. We all have one, don't we? I personally have a 16GB main card for all my shootings and a backup 8GB for when I am either really lazy or I am extremely zealous taking pictures.

Metadata option

If you are like me, you are not into spending hours post processing images and in order to save work after, I have some advice. In the "Template to Use:" drop down, I suggest you to select "Basic Metadata". This will create two text boxes, one for "Creator:" and one for "Copyright:". You should put your name in the first and a copyright notice in the next one. To get the © symbol in windows you can press and hold the ALT key, then using the numeric keypad with the Num Lock turned on, type 0169 then release the ALT key. You can find out other codes by typing charmap at the run command. This will bring the character map windows utility.

If you want to add more metadata, then before invoking photo downloader, you should go to the Bridge and select the appropriate command from the Tools menu. Once created, your metadata template will appear in the "Template to Use:" drop down.

This is it, most of the "hard" work is done. This is how your photo downloader window should look like before you press the "Get Photos" button:


And then the usual progress dialog box. One when copying a file and the second when converting the file to DNG format.


If you have CS4 and have, as I sermonized you for the last while, the option to delete the files turned on you should get the following two prompts. Make sure that nothing went wrong during the copy process and then confirm the deletion as below:



Moving images to appropriate folders (optional)

We are almost there. At the beginning, I mentioned that my memory card had several photo shoots on it. You should select the beginning photo of each shoot and then navigate to the ending photo of the shoot and then select Stack/Group as Stack menu option as in the screen shot below:




You should see as many stacks in the Bridge window as there were shoots. The number in the upper left corner of each stack is the number of images included. You should create as many folders (create them inside the subfolder selected earlier as it is far simpler to do it that way) as you have stacks. Remember to use the YYYYMM space naming convention.



You should be left with a screen looking something like that:


What you need to do is click the number in the upper left corner of a stack that you want to process. This will open the stack and select all pictures inside the stack. You should then simply drag any picture from the stack into the corresponding folder which should be in view as in the screen shot below:


And the usual progress dialog box:



Once you have move all of the images into their corresponding folders, you should simply move each folder in their appropriate location and that should be all.

I hope this was instructive and useful.

Performance Visualization

Just a quick note to tell people that I/we have been running a blog/group site on performance visualization which you can see by clicking here.

If you are not already a member you should see a link on the right side that says "Apply for group membership". Just click on this and you could become a happy member.