Friday, March 25, 2011

Aspect Ratio came to rescue

In my present assignment I had to deal with large JPEGs (2000px:3000px) images and wanted to store their scaled version (preferably of size 400px:500px).
If we randomly scale an image without considering its Aspect Ratio, the resized image looses clarity very quickly (depends upon how smaller you are trying to make it).

The solution is Aspect Ratio. So, you have the original width and height ratio (2000px:3000px) and need to find out scaled width and height. We need to keep either width or height fix. In my case, I kept the scale width fixed to "400px". Now, if we apply a simple mathematic equation-

width_original : height_original = width_scale : height_scale
height_scale = (width_scale * height_original) / width_original

So, height_scale will be 600px.

Above calculation will determine the scale width and height which will make sure your scaled image is keeping original Aspect Ratio intact and thus you'll get the best quality resized image!

I am using Java ImageIO package to handle Image resizing part. Following is the code snippet (file is the source of the original image)-
final int SCALE_WIDTH = 400;
// Read the original Image
BufferedImage srcImage = ImageIO.read(file.getInputStream());


// Get original Width and Height
int originalWidth = srcImage.getWidth();
int originalHeight = srcImage.getHeight();
// Scale width and height
int newWidth = originalWidth;
int newHeight = 0;

if(newWidth GREATER_THAN SCALE_WIDTH)
    newWidth = SCALE_WIDTH;
//Find out scaled Height
newHeight = (newWidth * originalHeight)/originalWidth;
// Save resized image
BufferedImage dest = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);  
Graphics2D g = dest.createGraphics(); 
AffineTransform at = AffineTransform.getScaleInstance(
(double) newWidth / srcImage.getWidth(),
(double) newHeight / srcImage.getHeight());  
g.drawRenderedImage(srcImage, at); 
ImageIO.write(dest, format, file); 


That's it. Hope it helps.         

Thursday, March 17, 2011

Regular Expression in JavaScript

I was struggling to get familiar with JavaScript's Regular expression handling and thought my learning might help others. Here I'll explain exec() function to parse/search matching regular expression in a given string.

Regular Expression is a special string in JavaScript which need to be inside of 2 "/" characters i.e. /REG_EXP/, you don't need to use ' or " characters. "i" and "g" followed by last "/" indicates whether you want to do ignore case and global search. REG_EXP can contain all standard regular expression syntax. Another important thing, we need to escape any Regular expression character if you put this in REG_EXP with "\" e.g. /\d{3}/. That's it! we are now almost ready to use Regular Expression. Following is a quick reference of mostly used RegEx Literals-

Position Matching: 
^ (Start of String), $(End of String), \b(Word Boundary) and \B(Non Word boundary)

RegEx Special Literals: w, W, d, D, s, S

Repetition:
{1}- One time. {1,}- One or more time, * (Zero or More), + (One or More) and ? (Zero or One). Repetition symbols are used along with RegEx Literals e.g. \w* (Zero or More Word Characters), \d{3}- (3 Numeric characters)
[]- matches any char. [a]- matches only "a". [^a] matches any character other than a. [^#]+ matches any sequence of string not having "#".

Logical OR and Grouping:
/(ab)/- any occurrence of "ab". /(ab)|(xy)/ matches either "ab" or "xy".

Now, lets start with some example scenarios. Following code snippet will find out occurrence of "ex" sub string-
var str = "some string example with expression"; // change this with HTML str
var rg = /ex/g; // replace this with your REG ExPression
var ma = null;
// I'm using Firebug
while((ma = rg.exec(str)) != null){
 console.log("Match Index="+ ma.index +" #"+ ma[0] );
 console.log("REG LastIndex="+ rg.lastIndex +" GL="+ rg.global +" Source="+ rg.source);
}
exec() method stores the next index to be used to resume search in the regiular expression variable i.e. "rg". Make sure you make it global search /g otherwise it will start from beginning and end up in a Infinite Loop!

Let's look into the Regular Expression to replace all width and height attributes of the HTML string. I'll replace all width and height values to 285 and 200 respectively and will try to keep postfix "px" (if there is any) as it is.
var html = '[div style="width: 400px; height: 500px"][iframe width="400" height="500"][/div]';

// Regular Expression for width and height attributes
// [Word Start]width="[One or More Digit]"
var wdrx = /\bwidth="\d+"/ig;
var htrx = /\bheight="\d+"/ig;
// Regular Expression for width and height within Style
// [Word Start]width:[Zero Or more space][One or more Digit]
var style_wdrx = /\bwidth:\s*\d+/ig;
var style_htrx = /\bheight:\s*\d+/ig;  

//Replace statements-
html = html.replace(wdrx, 'width="285"');
html = html.replace(htrx, 'height="200"');
html = html.replace(style_wdrx, 'width: 285');
html = html.replace(style_htrx, 'height: 200');


It seems it is going good...:-) Now let's try something different, say you want to replace all HREF ([a href=""]I'm a Link[/a]) links from your HTML code snippet.

Thursday, March 10, 2011

JSON- Parsing Apache Lib

I'm back again, last few months I was busy with my own Web 2.0 project and trying to build a platform which will use advance JavaScript and once that is done will write a JSON based Web API which can be accessed from Mobiles. So, thought lets share few exploration on Javascript and JSON. Here I'll explain how we can efficiently parse JSON to Java Object and vice verse. So if you are looking for similar stuff, keep reading following sections...
 
JSON (JavaScript Object Notation) is an wonderful and light weight piece of Object notation for data exchange. If you compare this with XML, you can easily make out that this representation is pretty compact compared to XML which need to use extra piece of information (XML Node name, start and end tags) to distinguish each node. Moreover JSON is closer to Object representation of your programming language Java or it is very easily supported in JavaScript (eval()). So if you are using
AJAX, this is the best fit.

So, next time you are planning to develope a data exchange system probably you can choose JSON instead of XML.

I will demonstrate 2 important portions of data exchange modules- 
Convert data from your native Objects (Java Objects) to JSON and get data back from JSON to your native Objects (Java Objects).
This conversion should be generic enough and easy to do, so that you can seemlessly add this exchange module without worrying too much about your present Object model.

Pre-requisites:
I am using Apache JSON-Lib (JDK1.5). The library is wonderfull, but the document doesn't indicate all dependent libraraies. So, make sure you download below Apache JARs as well-

commons-beanutils-1.8.3-bin.zipcommons-lang-2.6-bin.zipezmorph-1.0.6.jarcommons-collections-3.1.jar and commons-io-2.0.1.jar

The reason I am writting this is, there is no straight forward answer on Apache site which explains how to convert JSON to Java and vice verse for Complex Objects.

Lets start with the Object structure that we'll use to do JSON to Java and Java to JSON.


Note:
Please make sure your create Java Bean compatible Get and Set methods.

Java code to convert Bean object to JSON String-
Message m = new Message()
// Steps to fill in data into Message object
// Now, convert Java object to JSON
JSON json = JSONSerializer.toJSON(m);
String jsonString = json.toString();

Thats it! The Libraray it self is awesome, but need some more document, otherwise it takes time to figure out its features.

Now, lets do things in reverse i.e. convert JSON string to Java object. For this I'll use the String that I have just converted from my message Class-
{
    "ads" : {
        "lat" : 23.789,
        "lng" : 56.89,
        "location" : "out of the world"
    },
    "arrayAds" : [{
            "lat" : 23.567,
            "lng" : 45.678,
            "location" : "A1"
        }, {
            "lat" : 23.567,
            "lng" : 45.678,
            "location" : "A2"
        }
    ],
    "id" : 1,
    "msg" : "Hi, its me",
    "recipents" : ["u123 thy", "u234"],
    "sender" : "Alan"
}

Java code to convert JSON string to Java Bean Object-
Declare the type of Custom Object ArrayList you are going to use. In my example class, Message has a member variable arrayAds, an ArrayList of Address class (Custom Object)

Map classMap = new HashMap();
classMap.put("arrayAds", Address.class);

Declare your base class i.e. Message.class. toBean() method does the parsing using Java refactor technology.

Message m = (Message)JSONObject.toBean(
JSONObject.fromObject(json), Message.class, classMap);

Thats it! Now you can access the Message object "m". How good is that ? :-)

Update:
If you want to skip any field, say you don't want to parse lat and lng values from JSON stream. To do this we have to use JsonConfig class.

// Define your Configuration
JsonConfig config = new JsonConfig();
config.setClassMap(classMap);
// Exclude "lat" and "lng" from parsing
config.setExcludes(new String[] {"lat", "lng"});
config.setRootClass(Message.class);
Message m = (Message)JSONObject.toBean(JSONObject.fromObject(json, config), config);