Image generation through a java agent

Does anyone have a sample code of image generation using a java agent. I dont; want to go thru servlet route . I am trying to build a captcha.will be good if anyone has a code that i can use to start with...
LVL 14
p_parthaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

VenabiliCommented:
Had you seen this http://www.codestore.net/store.nsf/unid/BLOG-20080617 ? It's a rant for a missing method basically but it also have the way to build a captcha in a  JSP (if you prefer to turn it into servlet, it is trivial when you have the JSP after all)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
p_parthaAuthor Commented:
Thanks , Yeah i did see it. I dont' want to save images on the disk and generate images on the fly.. So checking whether there are any other innovative approaches

Thanks again
0
VenabiliCommented:
Not that I know of - last time I looked at it, that was the only way.
Which version of the server?
0
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

mbonaciCommented:
You've seen this one?
http://chris.brandlehner.at/Brandlehner/cab_blog.nsf/d6plinks/CBRR-7EASVD

Also, if your requirement is to avoid disk I/O, there's a comment in the article Venabili posted:

    Jake White * Posted on Tue 17 Jun 2008 02:17 PM
0
p_parthaAuthor Commented:
Server version is 8.x.

Mbonaci..i cannot use recaptcha as it depends on a external server's response..which can be problematic, if the server is down or experiencing problems.. It has to be native. Forget abt captcha.. do you know of any sample code in java agent that can generate images , with that i can try building stuff... I am even ok with disk I/O after reading Jake's blog :(

Thanks both for your insights

- Partha
0
p_parthaAuthor Commented:
:)

Thanks... This assumes that the image is in the nsf as a resource ... any idea whether i can send a dynamically created image to the browser as printwriter handles only text :(
0
VenabiliCommented:
>whether i can send a dynamically created image to the browser as printwriter handles only text

Nope, you cannot as far as I know. That's why I gave you the first link
0
Emmanuel GleizerCommented:
Hi,
If I resume what you need: you want to send text only to the browser.
But you have to send an image (captcha): so this has to be base64/uuencoded (or what ever else).
Since you also need HTML form for the user to enter the code and submit it you may be abble to get the base64encoded in ajax, decode it and display it where you need (more detail see Picture.src = 'data:image/gif;base64,' + myBase64Data; in http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_22495132.html)

this is the canvas...
good luck
Emmanuel
0
p_parthaAuthor Commented:
Ok Guys , with help from codestore.net and with my rusty java skills, i am able to write a captcha that works... no spl servlet.. just a agent (no spl permissions too)..

If you guys are interested.. i will put the code and explain what i did...
0
mbonaciCommented:
By all means, post the code and you explanation...

You can post that on OpenNTF or on IBM's Lotus Notes and Domino Application Development wiki (http://www-10.lotus.com/ldd/ddwiki.nsf) also.
0
p_parthaAuthor Commented:
Ok Here we go...

First create a form and put the following passthru html in the following order:

<span id='filename'></span>
<img id='imagename' src='' alt='loading image'>

<script src='http://yoururltotheagent?openagent&someuniquevalue''></script>


Put the following code in a java agent.... Most of the stuff is self explanatory... I am hashing the filename with the image text using session.hashpassword .
This way i dont' need the document that gets created (coolest part)....so I have a scheduled agent that deletes the document immediately once it's created (agent runs when new documents are created or modified)...

Now when the verification part comes.. ALL i have to do is check the filename span tag with the value that is being entered using verifypassword in a simple lotusscript agent :)

Guys , i need comments on whether u see any risk in this approach...

- Partha

import lotus.domino.*;
import java.util.*;
import java.io.*;
import java.lang.*;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.geom.*;

public class JavaAgent extends AgentBase {

	public void NotesMain() {

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
PrintWriter pw = getAgentOutput();
Database db = agentContext.getCurrentDatabase();
 Document doc = agentContext.getDocumentContext();

String imageFormat = "jpg";

   // you can pass in fontSize, width, height via the request
   
   Color backgroundColor = Color.red;
   Color borderColor = Color.black;
   Color textColor = Color.white;
   Color circleColor = new Color(160,160,160);
   Font textFont = new Font("Arial", Font.PLAIN, 24);
   int charsToPrint = 6;
   int width = 150;
   int height =  80;
   int circlesToDraw = 6;
   float horizMargin = 20.0f;
   float imageQuality = 0.95f; // max is 1.0 (this is for jpeg)
   double rotationRange = 0.7; // this is radians

   BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
   Graphics2D g = (Graphics2D) bufferedImage.getGraphics();

   g.setColor(backgroundColor);
   g.fillRect(0, 0, width, height);

   // lets make some noisey circles
   g.setColor(circleColor);
   for ( int i = 0; i < circlesToDraw; i++ ) {
     int circleRadius = (int) (Math.random() * height / 2.0);
     int circleX = (int) (Math.random() * width - circleRadius);
     int circleY = (int) (Math.random() * height - circleRadius);
     g.drawOval(circleX, circleY, circleRadius * 2, circleRadius * 2);
   }

   g.setColor(textColor);
   g.setFont(textFont);

   FontMetrics fontMetrics = g.getFontMetrics();
   int maxAdvance = fontMetrics.getMaxAdvance();
   int fontHeight = fontMetrics.getHeight();

   // i removed 1 and l and i because there are confusing to users...
   // Z, z, and N also get confusing when rotated
   // 0, O, and o are also confusing...
   // lowercase G looks a lot like a 9 so i killed it
   // this should ideally be done for every language...
   // i like controlling the characters though because it helps prevent confusion
   String elegibleChars = "ABCDEFGHJKLMPQRSTUVWXYabcdefhjkmnpqrstuvwxy23456789";
   char[] chars = elegibleChars.toCharArray();

   float spaceForLetters = -horizMargin * 2 + width;
   float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);

   AffineTransform transform = g.getTransform();
   StringBuffer finalString = new StringBuffer();

   for ( int i = 0; i < charsToPrint; i++ ) {
     double randomValue = Math.random();
     int randomIndex = (int) Math.round(randomValue * (chars.length - 1));
     char characterToShow = chars[randomIndex];
     finalString.append(characterToShow);

     // this is a separate canvas used for the character so that
     // we can rotate it independently
     int charImageWidth = maxAdvance * 2;
     int charImageHeight = fontHeight * 2;
     int charWidth = fontMetrics.charWidth(characterToShow);
     int charDim = Math.max(maxAdvance, fontHeight);
     int halfCharDim = (int) (charDim / 2);

     BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
     Graphics2D charGraphics = charImage.createGraphics();
     charGraphics.translate(halfCharDim, halfCharDim);
     double angle = (Math.random() - 0.5) * rotationRange;
     charGraphics.transform(AffineTransform.getRotateInstance(angle));
     charGraphics.translate(-halfCharDim,-halfCharDim);
     charGraphics.setColor(textColor);
     charGraphics.setFont(textFont);

     int charX = (int) (0.5 * charDim - 0.5 * charWidth);
     charGraphics.drawString("" + characterToShow, charX, 
                            (int) ((charDim - fontMetrics.getAscent()) 
                                   / 2 + fontMetrics.getAscent()));

     float x = horizMargin + spacePerChar * (i) - charDim / 2.0f;
     int y = (int) ((height - charDim) / 2);
//System.out.println("x=" + x + " height=" + height + " charDim=" + charDim + " y=" + y + " advance=" + maxAdvance + " fontHeight=" + fontHeight + " ascent=" + fontMetrics.getAscent());
     g.drawImage(charImage, (int) x, y, charDim, charDim, null, null);

     charGraphics.dispose();
   }

   // let's do the border
   g.setColor(borderColor);
   g.drawRect(0, 0, width - 1, height - 1);

   //Write the image as a jpg
   Iterator iter = ImageIO.getImageWritersByFormatName(imageFormat);
   if( iter.hasNext() ) {
     ImageWriter writer = (ImageWriter)iter.next();
     ImageWriteParam iwp = writer.getDefaultWriteParam();
     if ( imageFormat.equalsIgnoreCase("jpg") || imageFormat.equalsIgnoreCase("jpeg") ) {
       iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
       iwp.setCompressionQuality(imageQuality);
     }
     
     ByteArrayOutputStream os = new ByteArrayOutputStream();
     
     writer.setOutput(ImageIO.createImageOutputStream(os));
	IIOImage imageIO = new IIOImage(bufferedImage, null, null);
	writer.write(null, imageIO, iwp);




/*
	Now we ned to put the generated byte code in to a Notes Stream!
*/

	Stream stream=session.createStream();
	stream.write( os.toByteArray() );




/*
	Now let's create a document to store the new image in
*/

	Document tmp = db.createDocument();
	tmp.replaceItemValue("Form", "Captcha");



/*
	doc refers to the request for the image (captcha.jpg?openagent&832jrnj3nrj32kn)
	finalString refers to a random string of characters generated by the omitted code.
*/

	String id = doc.getItemValueString("Query_String").replaceAll("openagent&", "");


	tmp.replaceItemValue("ID", id);
	tmp.replaceItemValue("Answer",session.hashPassword(finalString.toString()));
	String filename =session.hashPassword(finalString.toString())+".jpg";



/*
	Now for the clever bit. Let's attach the file to our new document
*/

	MIMEEntity Body = tmp.createMIMEEntity();

	MIMEHeader header = Body.createHeader("content-disposition");
	header.setHeaderVal("attachment;filename=\""+filename+"\"");

	Body.setContentFromBytes(stream, "image/jpeg", MIMEEntity.ENC_IDENTITY_BINARY);

	tmp.save();

pw.println("Content-Type: text/js");
pw.println("[document.getElementById(\"filename\").innerHTML='"+filename+"']");
pw.println("[document.getElementById(\"imagename\").src=' /"+db.getFilePath().replaceAll("\\\\", "/")+"/0/"+tmp.getUniversalID() + "/$file/"+filename+"']");



/*     writer.setOutput(ImageIO.createImageOutputStream());
     IIOImage imageIO = new IIOImage(bufferedImage, null, null);
     writer.write(null, imageIO, iwp);*/
     
   } else {
     throw new RuntimeException("no encoder found for jsp");
   }

   g.dispose();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

Open in new window

0
p_parthaAuthor Commented:
Also if any of the experts can test and see this, it will be great

thanks
Partha
0
VenabiliCommented:
So you just create it on the server and delete it immediatelly? Technically this is still not on the fly creation. Or am I missing something?
0
mbonaciCommented:
Great job!
Image generation is on the fly.
-GTwmaqGmAuZir8slg0m-.jpg
0
p_parthaAuthor Commented:
I dont' save anythign on the server. It's saved as a attachment for a document. the docucmnet gets deleted immediately, although the image url is sent to the browser..Hope i am clear.. if not pls do ask...

Mbonaci: thanks... cud u check whether are any loopholes in this approcah.. The only thing i am thiking is someone refreshing the page continuously.. and that leads to docs getting created in the backend.. Hopefuly my schedule agent can keep up with it...

Offtopic:  I am working on few things that are pretty challenging... I don't know whether i will be able to find out solution for those, but will the experts be interested in backing me up with pointers???, if yes then i will post, not sure whether i have enough points to post questions as i dont have time to answer questions nowadays...

Let me know guys.. and also am not sure why i posted this question under email server.. can this be moved to the lotus domino area, where experts like Sjef, qwal, maddy, crak,bill , and you guys can answer
0
p_parthaAuthor Commented:
Can i accept my solution itslef as answer?
0
mbonaciCommented:
We didn't help at all?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Lotus IBM

From novice to tech pro — start learning today.