How to get current Session value of Captcha? - java

Please help me anyone! I'm stuck!
I'm trying to compare value inserted in textfield and value shown in Captcha (image), if they match it will show alert('Yes!') otherwise alert('No!'). But when I trying to get session value of Captcha (request.getSession().getAttribute("captcha")) it gets previous value of it!
How to make sure that value of Catcha if the same as user sees on image?
Captcha.jsp:
<%# page import="java.util.*"%>
<%# page import="java.io.*"%>
<%# page import="javax.servlet.*"%>
<%# page import="javax.servlet.http.*"%>
<%# page import="java.awt.*"%>
<%# page import="java.awt.image.*"%>
<%# page import="javax.imageio.*"%>
<%# page import="java.awt.geom.*"%>
<%
String imageFormat = "jpg";
response.setContentType("image/" + imageFormat);
try {
// 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, paramInt(request,
"fontSize", 24));
int charsToPrint = 6;
int width = paramInt(request, "width", 150);
int height = paramInt(request, "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);
}
writer.setOutput(ImageIO.createImageOutputStream(response.getOutputStream()));
IIOImage imageIO = new IIOImage(bufferedImage, null, null);
writer.write(null, imageIO, iwp);
} else {
throw new RuntimeException("no encoder found for jsp");
}
// set session
request.getSession().setAttribute("captcha", finalString.toString());
System.out.println("Captcha.jsp: "+request.getSession().getAttribute("captcha"));//for console output
out.clear();
out = pageContext.pushBody();
g.dispose();
} catch (IOException ioe) {
throw new RuntimeException("Unable to build image", ioe);
}
%>
<%!public static String paramString(HttpServletRequest request,
String paramName, String defaultString) {
return request.getParameter(paramName) != null ? request
.getParameter(paramName) : defaultString;
}
public static int paramInt(HttpServletRequest request, String paramName,
int defaultInt) {
return request.getParameter(paramName) != null ? Integer
.parseInt(request.getParameter(paramName)) : defaultInt;
}%>
To set sesion I'm using - request.getSession().setAttribute("captcha", finalString.toString());
ValidateCapture.jsp:
<html>
<head>
<script type="text/javascript">
function ValidateCaptcha(){
<%String captcha=(String)request.getSession().getAttribute("captcha");%>
var answer = document.getElementById("answer").value;
var captcha = '<%=captcha%>';
if(answer==captcha){
alert('Yes');
}
else{
alert('No');
}
}
</script>
</head>
<body>
<img src="Captcha.jsp"/>
<input id="answer" type="text">
<input type="button" value="Submit" onclick="ValidateCaptcha();">
<%System.out.println("ValidateCapture.jsp: "+request.getSession().getAttribute("captcha"));%> <!--for console output-->
</body>
To get session I'm using - request.getSession().getAttribute("captcha");
Console Output:

i saw the code. expecially about set session. i thought you shouldn't set attribute value. First, session invalid just when The browser closed or no-operation time up 30 mins in tomcat configuration file. however,you didn't close your browser,you will get the same captcha with previous value of it. so, we can do this,follow the code: request.setAttribute("captcha", finalString.toString());//set value and request.getAttribute("captcha");//get value
like this.we will get different captcha values when we click the pictures.Request Object also changed. why do this? because when "Request" to server and server responsed later,request Object invalid. next request will produce new request object.just this,good luck.

Related

How to add a text above a previous added image and center it above this image with pdfbox?

My aim is to add a image to a pdf and write a text above this image. I have centered the image and the text should be center above the image with a little margin to the image.
Currently the image will be added and centered but the text is not centered.
Here my current code. The interesting part is where the method drawTitleAtTop will be called. Here i have added the height of the newly added image to the y postion plus a margin of 3. The x coordinate I calculate depending on the incoming text but there is some miscalculation. Any advice?
private static void addScaledImage(ImageData imgData, PDDocument pdDocument, Dimension thePdfDimension) {
ImageHelper helper = Scalr::resize;
byte[] scaledImage = ImageUtils.resizeImageKeepAspectRatio(helper, imgData.getImageBinary(), thePdfDimension.width);
PDRectangle rectangle = pdDocument.getPage(0).getMediaBox();
PDPage page = new PDPage(rectangle);
pdDocument.addPage(page);
PDImageXObject pdImage = null;
try {
pdImage = PDImageXObject.createFromByteArray(pdDocument, scaledImage, null);
LOG.debug("size of scaled image is x: {0} y {1}", pdImage.getWidth(), pdImage.getHeight());
int xForImage = (thePdfDimension.width - pdImage.getWidth()) / 2 ;
int yForImage = (thePdfDimension.height - pdImage.getHeight()) / 2;
LOG.debug("new x {0} new y {1}", xForImage, yForImage);
try (PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, AppendMode.APPEND, true, true)) {
if (StringUtils.isNotBlank(imgData.getTitle())) {
yForImage = xForImage - 20;
contentStream.drawImage(pdImage, xForImage, yForImage, pdImage.getWidth(), pdImage.getHeight());
drawTitelAtTop(imgData, page, xForImage , yForImage + pdImage.getHeight() + 3, contentStream);
} else {
contentStream.drawImage(pdImage, xForImage, yForImage, pdImage.getWidth(), pdImage.getHeight());
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void drawTitelAtTop(ImageData imgData, PDPage page, int x, int y, PDPageContentStream contentStream) throws IOException {
PDFont font = PDType1Font.COURIER;
int fontSize = FONT_SIZE_FOR_TITLE;
float titleWidth = font.getStringWidth(imgData.getTitle()) / 1000 * fontSize;
LOG.debug("title width is " + titleWidth);
contentStream.setFont(font, fontSize);
contentStream.beginText();
float tx = ((x - titleWidth) / 2) + x;
//float tx = x;
//float ty = page.getMediaBox().getHeight() - marginTop + (marginTop / 4);
float ty = y;
LOG.debug("title offset x {0} y {1}", tx, ty);
contentStream.newLineAtOffset(tx,
ty);
contentStream.showText(imgData.getTitle());
contentStream.endText();
}

PDAnnotationTextMarkup missing when rendering a pdf page to image PDFBox Java

I have code written using PDFBox API that highlights the words in a PDF but when I convert highlighted PDF pages to images, then whatever I have highlighted gets disappeared from the image.
Below screenshot is with highlighted text, for highlighting I have used PDFBox's PDAnnotationTextMarkup class:
Highlighted PDF Page
Below is the image after converting the pdf page to image:
Highlighted PDF Page Image after converting
Below is the code I have used for converting PDF to Image:
PDDocument document = PDDocument.load(new File(pdfFilename));
PDFRenderer pdfRenderer = new PDFRenderer(document);
int pageCounter = 0;
for (PDPage page : document.getPages())
{
BufferedImage bim = pdfRenderer.renderImageWithDPI(pageCounter, 300, ImageType.RGB);
ImageIOUtil.writeImage(bim, pdfFilename + "-" + (pageCounter++) + ".png", 300);
}
document.close();
Please suggest what is wrong here, why PDFRenderer not able to take PDF page image along with the highlighted red box.
Below is the code I used to highlight the text in PDF:
private void highlightText(String pdfFilePath, String highlightedPdfFilePath) {
try {
// Loading an existing document
File file = new File(highlightedPdfFilePath);
if (!file.exists()) {
file = new File(pdfFilePath);
}
PDDocument document = PDDocument.load(file);
// extended PDFTextStripper class
PDFTextStripper stripper = new PDFTextHighlighter();
// Get number of pages
int number_of_pages = document.getDocumentCatalog().getPages().getCount();
// The method writeText will invoke an override version of
// writeString
Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
stripper.writeText(document, dummy);
// Print collected information
System.out.println("tokenStream:::"+tokenStream);
System.out.println("tokenStream size::"+tokenStream.size());
System.out.println("coordinates size::"+coordinates.size());
double page_height;
double page_width;
double width, height, minx, maxx, miny, maxy;
int rotation;
// scan each page and highlitht all the words inside them
for (int page_index = 0; page_index < number_of_pages; page_index++) {
// get current page
PDPage page = document.getPage(page_index);
// Get annotations for the selected page
List<PDAnnotation> annotations = page.getAnnotations();
// Define a color to use for highlighting text
PDColor red = new PDColor(new float[] { 1, 0, 0 }, PDDeviceRGB.INSTANCE);
// Page height and width
page_height = page.getMediaBox().getHeight();
page_width = page.getMediaBox().getWidth();
// Scan collected coordinates
for (int i = 0; i < coordinates.size(); i++) {
if (!differencePgaeNumber.contains(page_index)) {
differencePgaeNumber.add(page_index);
}
// if the current coordinates are not related to the current
// page, ignore them
if ((int) coordinates.get(i)[4] != (page_index + 1))
continue;
else {
// get rotation of the page...portrait..landscape..
rotation = (int) coordinates.get(i)[7];
// page rotated of 90degrees
if (rotation == 90) {
height = coordinates.get(i)[5];
width = coordinates.get(i)[6];
width = (page_height * width) / page_width;
// define coordinates of a rectangle
maxx = coordinates.get(i)[1];
minx = coordinates.get(i)[1] - height;
miny = coordinates.get(i)[0];
maxy = coordinates.get(i)[0] + width;
} else // i should add here the cases -90/-180 degrees
{
height = coordinates.get(i)[5];
minx = coordinates.get(i)[0];
maxx = coordinates.get(i)[2];
miny = page_height - coordinates.get(i)[1];
maxy = page_height - coordinates.get(i)[3] + height;
}
// Add an annotation for each scanned word
PDAnnotationTextMarkup txtMark = new PDAnnotationTextMarkup(
PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
txtMark.setColor(red);
txtMark.setConstantOpacity((float) 0.3); // 30%
// transparent
PDRectangle position = new PDRectangle();
position.setLowerLeftX((float) minx);
position.setLowerLeftY((float) miny);
position.setUpperRightX((float) maxx);
position.setUpperRightY((float) ((float) maxy + height));
txtMark.setRectangle(position);
float[] quads = new float[8];
quads[0] = position.getLowerLeftX(); // x1
quads[1] = position.getUpperRightY() - 2; // y1
quads[2] = position.getUpperRightX(); // x2
quads[3] = quads[1]; // y2
quads[4] = quads[0]; // x3
quads[5] = position.getLowerLeftY() - 2; // y3
quads[6] = quads[2]; // x4
quads[7] = quads[5]; // y5
txtMark.setQuadPoints(quads);
txtMark.setContents(tokenStream.get(i).toString());
annotations.add(txtMark);
}
}
}
// Saving the document in a new file
File highlighted_doc = new File(highlightedPdfFilePath);
document.save(highlighted_doc);
document.close();
} catch (IOException e) {
System.out.println(e);
}
}
You need to construct the visual appearance of the annotation with this call:
txtMark.constructAppearances(document);

Spring Boot convert (load image from jsp) to (load from html)

I got an old project which is using Strut1 framework. So it uses JSP to load captcha image from another JSP file. Source code below.
Now, I upgrade that project using Spring Boot and Thymeleaf layout. I don't know how to convert it into html. Please take a look and give ideas.
Thanks.
For login.jsp
<div id="captcha" style="cursor: pointer; height: 30px; width: 150px; display: inline-block; float: left"><img src="captcha.jsp"></div>
captcha.jsp
<%# page contentType="text/html;charset=UTF-8"%>
<%# page import="java.util.*"%>
<%# page import="java.io.*"%>
<%# page import="javax.servlet.*"%>
<%# page import="javax.servlet.http.*"%>
<%# page import="java.awt.*"%>
<%# page import="java.awt.image.*"%>
<%# page import="javax.imageio.*"%>
<%# page import="java.awt.geom.*"%>
<%# page import="vn.com.tivn.online.acquiring.util.ValueUtil"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>captcha</title>
</head>
<body>
<%
//========================================================
// Kick Ass Captcha JSP
//
// Michael Connor 2007
//
// I just couldn't handle the thought of downloading a
// big jar and configuring some servlet.xml and having
// little to no control of anything...
// You can send in height and width parameters.
// The captcha value will be placed in the session in
// a parameter called 'captcha'
//
// Feel free to use this code and do whatever the hell
// you want to it.
//========================================================
String imageFormat = "png";
response.setContentType("image/" + imageFormat);
try {
// you can pass in fontSize, width, height via the request
Color backgroundColor = Color.blue;
Color borderColor = Color.black;
Color textColor = Color.white;
Color circleColor = new Color(160,160,160);
Font textFont = new Font("Arial", Font.PLAIN, paramInt(request, "fontSize", 24));
int charsToPrint = 6;
int width = paramInt(request, "width", 150);
int height = paramInt(request, "height", 30);
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);
}
writer.setOutput(ImageIO.createImageOutputStream(response.getOutputStream()));
IIOImage imageIO = new IIOImage(bufferedImage, null, null);
writer.write(null, imageIO, iwp);
} else {
throw new RuntimeException("no encoder found for jsp");
}
// let's stick the final string in the session
request.getSession().setAttribute("wirecardmposcaptcha", finalString.toString());
System.out.print("----------"+g.dispose());
g.dispose();
} catch (IOException ioe) {
throw new RuntimeException("Unable to build image" , ioe);
}
%>
<%!
public static String paramString(HttpServletRequest request, String paramName, String defaultString) {
return request.getParameter(paramName) != null ? request.getParameter(paramName) : defaultString;
}
public static int paramInt(HttpServletRequest request, String paramName, int defaultInt) {
return request.getParameter(paramName) != null ? Integer.parseInt(request.getParameter(paramName)) : defaultInt;
}
%>
<%
if(ValueUtil.SUPPORT_SSL){
String sessionid = request.getSession().getId();
response.addHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; Secure; HttpOnly");
}
%>
</body>
</html>
As an inital approach:
Create a file under resources/templates folder called login.html and place the same code as in login.jsp. Replace <img src="captcha.jsp"> by something like <img th:src="${capchaUrl}"> If this is not an entire page you can also create a fragment and include it wherever you need.
In your template controller add the methods needed to create the captcha by refactoring captcha.jsp and, once you have the captcha, you can add it to the model like model.addAttribute("capchaUrl", the_generated_captcha); it should be populated in the template.

Not detecting height and width change for applet run via window.open()

I created a clock applet that resizes the text as the user stretches the window around. In Netbeans it works fine but running the jar on the web server it does not detect any changes in size. I initially was using getWidth() and getHeight() in the paint function to get the current window size. When I realized it wasn't detecting changes outside of Netbeans I switched/add a componentResized() listener but that also doesn't detect any resizing outside of Netbeans either.
On the web server index.html page I am using win=window.open(url, name, the_size) to open a window with the clock applet inside. Why is the listener not seeing any resizing as I stretch the window around? Is it because window.open() window is different from the Netbean pop up window somehow?
#Override
public void init() {
if (getParameter("verbose") != null)
{
try {
m_verboseLevel = Integer.parseInt(getParameter("verbose"));
} catch (NumberFormatException e) {
System.out.println(Thread.currentThread().getName() + " verbose: " + getParameter("verbose") + " is not 0->3");
m_verboseLevel = 0;
}
}
m_size = getParameter("size");
m_clock_color = getParameter("color");
// Add listener to update width and height as user changes it
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
m_w = getWidth();
m_h = getHeight();
System.out.println(m_w + " " + m_h);
}
});
try {
In paint the m_w and m_h are initially 0 since since nothing has moved. I call getWidth() and getHeight() and the output matches the html applet width and height values 600 and 800. But outside of Netbeans m_h/m_w never changes so the scale logic doesn't change anything.
#Override
public void paint(Graphics g) {
// first time?
if ((m_w == 0) && (m_h == 0)) {
m_w = getWidth(); // return the width of the applet
m_h = getHeight(); // return the height of the applet
}
// Use buffering for smooth update
BufferedImage bi = new BufferedImage(m_w, m_h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
super.paint(g2d);
String[] lines = new String[2];
lines[0] = "Acquisition of Signal";
lines[1] = "Loss of Signal";
// first time?
if (m_clockLine == 0) {
FontRenderContext frc = g2d.getFontRenderContext();
LineMetrics metrics = m_clock_font.getLineMetrics(lines[1], frc);
// Omitt the descent from the height variable.
String time = "00:00:00";
g2d.setFont(m_clock_font);
float height1 = metrics.getAscent() + metrics.getDescent();
m_width = m_clock_font.getStringBounds(time, frc).getWidth();
m_clockLine = (int) (metrics.getAscent() - 1);
metrics = m_label_font.getLineMetrics(lines[0], frc);
float height2 = metrics.getAscent() + metrics.getDescent();
m_labelLine = (int) (metrics.getAscent() - 1);
metrics = m_tk_font.getLineMetrics(lines[1], frc);
float height3 = metrics.getAscent() + metrics.getDescent();
m_titleLine = (int) (metrics.getAscent() - 1);
m_width += 22*2;
m_height = height1 + height2 + height3 + height1 + height2 + (m_padding*4);
}
System.out.println(m_w + " " + m_width + " " + m_h + " " + m_height);
g2d.scale(m_w/m_width, m_h/m_height);
/* Make background black */
g2d.setColor(Color.black);
g2d.fillRect(0, 0, (int)m_width, (int)m_height);
/* Draw individual clock labels */
g2d.setFont(m_label_font);
g2d.setColor(m_main_color);
g2d.drawString(lines[0], 145, m_clockLine+m_labelLine+m_padding);
g2d.drawString(lines[1], 220, m_clockLine+m_labelLine+m_titleLine+m_clockLine+m_labelLine+(m_padding*4));
// Write check clock timer lines
if (m_c != null) {
m_c.print(g2d, m_labelLine, m_clockLine, m_titleLine, m_padding, m_width, m_height);
}
g2d.dispose();
g.drawImage(bi, 0, 0, this);
} // end paint
Ok, after a lot of googling I found out what the problem is. When the applet is checking it's dimensions either using the addComponentListener componentResized or the getWidth/getHeight call it is reading the html width and height values for the applet/object. When using the Netbeans Applet Viewer these values are being changed as the viewer is being stretched. But in a html page the width and height are not changing as the browser is resized. This is why the applet size doesn't change when you stretch the browser. So the solution in the real environment is reset the width and height values via javascript so that the applet can see the new dimensions onLoad. Note: onResize doesn't seem to ever go off but I left it in anyway.
So I removed the componentResized logic and in the paint function just call getWidth/getHeight for the applet dimensions. This is the final paint function.
#Override
public void paint(Graphics g) {
// This makes the applet resizable
int w = getWidth(); // return the width of the applet
int h = getHeight(); // return the height of the applet
// Use buffering for smooth update
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
super.paint(g2d);
String[] lines = new String[2];
lines[0] = "Acquisition of Signal";
lines[1] = "Loss of Signal";
// first time?
if (m_clockLine == 0) {
FontRenderContext frc = g2d.getFontRenderContext();
LineMetrics metrics = m_clock_font.getLineMetrics(lines[1], frc);
// Omitt the descent from the height variable.
String time = "00:00:00";
g2d.setFont(m_clock_font);
float height1 = metrics.getAscent() + metrics.getDescent();
m_width = m_clock_font.getStringBounds(time, frc).getWidth();
m_clockLine = (int) (metrics.getAscent() - 1);
metrics = m_label_font.getLineMetrics(lines[0], frc);
float height2 = metrics.getAscent() + metrics.getDescent();
m_labelLine = (int) (metrics.getAscent() - 1);
metrics = m_tk_font.getLineMetrics(lines[1], frc);
float height3 = metrics.getAscent() + metrics.getDescent();
m_titleLine = (int) (metrics.getAscent() - 1);
m_width += 22*2;
m_height = height1 + height2 + height3 + height1 + height2 + (m_padding*4);
}
g2d.scale(w/m_width, h/m_height);
/* Make background black */
g2d.setColor(Color.black);
g2d.fillRect(0, 0, (int)m_width, (int)m_height);
/* Draw individual clock labels */
g2d.setFont(m_label_font);
g2d.setColor(m_main_color);
g2d.drawString(lines[0], 145, m_clockLine+m_labelLine+m_padding);
g2d.drawString(lines[1], 220, m_clockLine+m_labelLine+m_titleLine+m_clockLine+m_labelLine+(m_padding*4));
// Write check clock timer line
if (m_c != null) {
m_c.print(g2d, m_labelLine, m_clockLine, m_titleLine, m_padding, m_width, m_height);
}
g2d.dispose();
g.drawImage(bi, 0, 0, this);
} // end paint
In the html script I added the following logic:
<html>
<head>
<TITLE>Terra Small Clock</TITLE>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<meta content="IE=5.0000" http-equiv="X-UA-Compatible">
<meta name="GENERATOR" content="MSHTML 11.00.9600.17842">
</head>
<SCRIPT LANGUAGE="JavaScript">
/*
Description:
The re-size function job is to reset the applet width and height to the new dimensions as the
user stretches the browser window. The clock applet will then use the "current" width and
height to scale the clock.
*/
function resize()
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
// 100% works fine on object tag with IE
return;
}
var w_newWidth,w_newHeight;
var netscapeScrollWidth=0;
w_newWidth = window.innerWidth-netscapeScrollWidth;
w_newHeight = window.innerHeight-netscapeScrollWidth;
var appletDiv = document.getElementById('clockApp');
if (appletDiv != null) {
appletDiv.style.width = w_newWidth + "px";
appletDiv.style.height = w_newHeight + "px";
}
}
window.onResize = resize;
window.onLoad = resize;
</SCRIPT>
<body bgcolor="000000" leftmargin="0" rightmargin="0" topmargin="0" marginheight="0" marginwidth="0" onResize="resize()" onLoad="resize()">
<p style="text-align:center">
<object type="application/x-java-applet" id="clockApp" width="240" height="230">
<param name="codebase" value="https://<host stuff>.nasa.gov/java_clocks/classes/" />
<param name="code" value="aosClock.class" />
<param name="archive" value="clock.jar" />
<param name="verbose" value="0" />
<param name="color" value="green" />
<param name="input_file" value="https://<host stuff>.nasa.gov/java_clocks/terra/terra_aos_times" />
</object>
</p>
</body>
</html>
So when I stop stretching the browser window the onLoad goes off and the applet/object width and height are reset. The applet then scales the clock for the new dimensions.

DCT2 of png using jTransforms

What I'm trying to do is to compute 2D DCT of an image in Java and then save the result back to file.
Read file:
coverImage = readImg(coverPath);
private BufferedImage readImg(String path) {
BufferedImage destination = null;
try {
destination = ImageIO.read(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
return destination;
}
Convert to float array:
cover = convertToFloatArray(coverImage);
private float[] convertToFloatArray(BufferedImage source) {
securedImage = (WritableRaster) source.getData();
float[] floatArray = new float[source.getHeight() * source.getWidth()];
floatArray = securedImage.getPixels(0, 0, source.getWidth(), source.getHeight(), floatArray);
return floatArray;
}
Run the DCT:
runDCT(cover, coverImage.getHeight(), coverImage.getWidth());
private void runDCT(float[] floatArray, int rows, int cols) {
dct = new FloatDCT_2D(rows, cols);
dct.forward(floatArray, false);
securedImage.setPixels(0, 0, cols, rows, floatArray);
}
And then save it as image:
convertDctToImage(securedImage, coverImage.getHeight(), coverImage.getWidth());
private void convertDctToImage(WritableRaster secured, int rows, int cols) {
coverImage.setData(secured);
File file = new File(securedPath);
try {
ImageIO.write(coverImage, "png", file);
} catch (IOException ex) {
Logger.getLogger(DCT2D.class.getName()).log(Level.SEVERE, null, ex);
}
}
But what I get is: http://kyle.pl/up/2012/05/29/dct_stack.png
Can anyone tell me what I'm doing wrong? Or maybe I don't understand something here?
This is a piece of code, that works for me:
//reading image
BufferedImage image = javax.imageio.ImageIO.read(new File(filename));
//width * 2, because DoubleFFT_2D needs 2x more space - for Real and Imaginary parts of complex numbers
double[][] brightness = new double[img.getHeight()][img.getWidth() * 2];
//convert colored image to grayscale (brightness of each pixel)
for ( int y = 0; y < image.getHeight(); y++ ) {
raster.getDataElements( 0, y, image.getWidth(), 1, dataElements );
for ( int x = 0; x < image.getWidth(); x++ ) {
//notice x and y swapped - it's JTransforms format of arrays
brightness[y][x] = brightnessRGB(dataElements[x]);
}
}
//do FT (not FFT, because FFT is only* for images with width and height being 2**N)
//DoubleFFT_2D writes data to the same array - to brightness
new DoubleFFT_2D(img.getHeight(), img.getWidth()).realForwardFull(brightness);
//visualising frequency domain
BufferedImage fd = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
outRaster = fd.getRaster();
for ( int y = 0; y < img.getHeight(); y++ ) {
for ( int x = 0; x < img.getWidth(); x++ ) {
//we calculate complex number vector length (sqrt(Re**2 + Im**2)). But these lengths are to big to
//fit in 0 - 255 scale of colors. So I divide it on 223. Instead of "223", you may want to choose
//another factor, wich would make you frequency domain look best
int power = (int) (Math.sqrt(Math.pow(brightness[y][2 * x], 2) + Math.pow(brightness[y][2 * x + 1], 2)) / 223);
power = power > 255 ? 255 : power;
//draw a grayscale color on image "fd"
fd.setRGB(x, y, new Color(c, c, c).getRGB());
}
}
draw(fd);
Resulting image should look like big black space in the middle and white spots in all four corners. Usually people visualise FD so, that zero frequency appears in the center of the image. So, if you need classical FD (one, that looks like star for reallife images), you need to upgrade "fd.setRGB(x, y..." a bit:
int w2 = img.getWidth() / 2;
int h2 = img.getHeight() / 2;
int newX = x + w2 >= img.getWidth() ? x - w2 : x + w2;
int newY = y + h2 >= img.getHeight() ? y - h2 : y + h2;
fd.setRGB(newX, newY, new Color(power, power, power).getRGB());
brightnessRGB and draw methods for the lazy:
public static int brightnessRGB(int rgb) {
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
return (r+g+b)/3;
}
private static void draw(BufferedImage img) {
JLabel picLabel = new JLabel(new ImageIcon(img));
JPanel jPanelMain = new JPanel();
jPanelMain.add(picLabel);
JFrame jFrame = new JFrame();
jFrame.add(jPanelMain);
jFrame.pack();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
I know, I'm a bit late, but I just did all that for my program. So, let it be here for those, who'll get here from googling.

Categories

Resources