mirror of
https://github.com/librecaptcha/lc-core.git
synced 2025-01-13 06:53:19 -05:00
Merge pull request #96 from rr83019/image-dpi
Set Image DPI for captcha providers
This commit is contained in:
commit
8f606da92f
@ -1,6 +1,5 @@
|
|||||||
package lc.captchas;
|
package lc.captchas;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -10,6 +9,7 @@ import java.util.Map;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lc.captchas.interfaces.Challenge;
|
import lc.captchas.interfaces.Challenge;
|
||||||
import lc.captchas.interfaces.ChallengeProvider;
|
import lc.captchas.interfaces.ChallengeProvider;
|
||||||
|
import lc.misc.PngImageWriter;
|
||||||
import lc.misc.HelperFunctions;
|
import lc.misc.HelperFunctions;
|
||||||
|
|
||||||
public class FontFunCaptcha implements ChallengeProvider {
|
public class FontFunCaptcha implements ChallengeProvider {
|
||||||
@ -74,7 +74,7 @@ public class FontFunCaptcha implements ChallengeProvider {
|
|||||||
graphics2D.dispose();
|
graphics2D.dispose();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
ImageIO.write(img, "png", baos);
|
PngImageWriter.write(baos, img);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package lc.captchas;
|
package lc.captchas;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
@ -14,6 +13,7 @@ import java.util.Map;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import lc.misc.HelperFunctions;
|
import lc.misc.HelperFunctions;
|
||||||
|
import lc.misc.PngImageWriter;
|
||||||
import lc.captchas.interfaces.Challenge;
|
import lc.captchas.interfaces.Challenge;
|
||||||
import lc.captchas.interfaces.ChallengeProvider;
|
import lc.captchas.interfaces.ChallengeProvider;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ public class ShadowTextCaptcha implements ChallengeProvider {
|
|||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
ImageIO.write(img2, "png", baos);
|
PngImageWriter.write(baos, img2);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ public class HelperFunctions {
|
|||||||
|
|
||||||
private static Random random = new Random();
|
private static Random random = new Random();
|
||||||
|
|
||||||
synchronized public static void setSeed(long seed){
|
public static synchronized void setSeed(long seed) {
|
||||||
random.setSeed(seed);
|
random.setSeed(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,12 +38,11 @@ public class HelperFunctions {
|
|||||||
return stringBuilder.toString();
|
return stringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public static int randomNumber(int min, int max) {
|
public static synchronized int randomNumber(int min, int max) {
|
||||||
return random.nextInt((max - min) + 1) + min;
|
return random.nextInt((max - min) + 1) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized public static int randomNumber(int bound) {
|
public static synchronized int randomNumber(int bound) {
|
||||||
return random.nextInt(bound);
|
return random.nextInt(bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
68
src/main/java/lc/misc/PngImageWriter.java
Normal file
68
src/main/java/lc/misc/PngImageWriter.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package lc.misc;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.imageio.IIOImage;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.ImageWriteParam;
|
||||||
|
import javax.imageio.ImageWriter;
|
||||||
|
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public class PngImageWriter {
|
||||||
|
|
||||||
|
static final int DPI = 245;
|
||||||
|
static final double INCH_2_CM = 2.54;
|
||||||
|
|
||||||
|
public static void write(ByteArrayOutputStream boas, BufferedImage gridImage) throws IOException {
|
||||||
|
final String formatName = "png";
|
||||||
|
for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName);
|
||||||
|
iw.hasNext(); ) {
|
||||||
|
ImageWriter writer = iw.next();
|
||||||
|
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||||
|
ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
|
||||||
|
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
|
||||||
|
if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDPIMeta(metadata);
|
||||||
|
|
||||||
|
final ImageOutputStream stream = ImageIO.createImageOutputStream(boas);
|
||||||
|
try {
|
||||||
|
writer.setOutput(stream);
|
||||||
|
writer.write(metadata, new IIOImage(gridImage, null, metadata), writeParam);
|
||||||
|
} finally {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setDPIMeta(IIOMetadata metadata) throws IIOInvalidTreeException {
|
||||||
|
|
||||||
|
// for PNG, it's dots per millimeter
|
||||||
|
double dotsPerMilli = 1.0 * DPI / 10 / INCH_2_CM;
|
||||||
|
|
||||||
|
IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
|
||||||
|
horiz.setAttribute("value", Double.toString(dotsPerMilli));
|
||||||
|
|
||||||
|
IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
|
||||||
|
vert.setAttribute("value", Double.toString(dotsPerMilli));
|
||||||
|
|
||||||
|
IIOMetadataNode dim = new IIOMetadataNode("Dimension");
|
||||||
|
dim.appendChild(horiz);
|
||||||
|
dim.appendChild(vert);
|
||||||
|
|
||||||
|
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
|
||||||
|
root.appendChild(dim);
|
||||||
|
|
||||||
|
metadata.mergeTree("javax_imageio_1.0", root);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package lc.captchas
|
package lc.captchas
|
||||||
|
|
||||||
import javax.imageio.ImageIO
|
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
import java.awt.Font
|
import java.awt.Font
|
||||||
import java.awt.font.TextLayout
|
import java.awt.font.TextLayout
|
||||||
@ -12,6 +11,7 @@ import java.util.List
|
|||||||
import lc.misc.HelperFunctions
|
import lc.misc.HelperFunctions
|
||||||
import lc.captchas.interfaces.Challenge
|
import lc.captchas.interfaces.Challenge
|
||||||
import lc.captchas.interfaces.ChallengeProvider
|
import lc.captchas.interfaces.ChallengeProvider
|
||||||
|
import lc.misc.PngImageWriter
|
||||||
|
|
||||||
/** This captcha is only for debugging purposes. It creates very simple captchas that are deliberately easy to solve with OCR engines */
|
/** This captcha is only for debugging purposes. It creates very simple captchas that are deliberately easy to solve with OCR engines */
|
||||||
class DebugCaptcha extends ChallengeProvider {
|
class DebugCaptcha extends ChallengeProvider {
|
||||||
@ -53,7 +53,7 @@ class DebugCaptcha extends ChallengeProvider {
|
|||||||
graphics2D.dispose()
|
graphics2D.dispose()
|
||||||
val baos = new ByteArrayOutputStream()
|
val baos = new ByteArrayOutputStream()
|
||||||
try {
|
try {
|
||||||
ImageIO.write(img, "png", baos)
|
PngImageWriter.write(baos, img);
|
||||||
} catch {
|
} catch {
|
||||||
case e: Exception =>
|
case e: Exception =>
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -8,6 +8,8 @@ import java.awt.Color
|
|||||||
import lc.captchas.interfaces.ChallengeProvider
|
import lc.captchas.interfaces.ChallengeProvider
|
||||||
import lc.captchas.interfaces.Challenge
|
import lc.captchas.interfaces.Challenge
|
||||||
import java.util.{List => JavaList, Map => JavaMap}
|
import java.util.{List => JavaList, Map => JavaMap}
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import lc.misc.PngImageWriter
|
||||||
|
|
||||||
class FilterChallenge extends ChallengeProvider {
|
class FilterChallenge extends ChallengeProvider {
|
||||||
def getId = "FilterChallenge"
|
def getId = "FilterChallenge"
|
||||||
@ -41,7 +43,15 @@ class FilterChallenge extends ChallengeProvider {
|
|||||||
var image = ImmutableImage.fromAwt(canvas)
|
var image = ImmutableImage.fromAwt(canvas)
|
||||||
val s = scala.util.Random.nextInt(2)
|
val s = scala.util.Random.nextInt(2)
|
||||||
image = filterTypes(s).applyFilter(image)
|
image = filterTypes(s).applyFilter(image)
|
||||||
new Challenge(image.bytes(new nio.PngWriter()), "image/png", secret)
|
val img = image.awt()
|
||||||
|
val baos = new ByteArrayOutputStream()
|
||||||
|
try {
|
||||||
|
PngImageWriter.write(baos, img);
|
||||||
|
} catch {
|
||||||
|
case e: Exception =>
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
new Challenge(baos.toByteArray, "image/png", secret)
|
||||||
}
|
}
|
||||||
def checkAnswer(secret: String, answer: String): Boolean = {
|
def checkAnswer(secret: String, answer: String): Boolean = {
|
||||||
secret == answer
|
secret == answer
|
||||||
|
@ -10,6 +10,7 @@ import java.awt.Color
|
|||||||
import lc.captchas.interfaces.ChallengeProvider
|
import lc.captchas.interfaces.ChallengeProvider
|
||||||
import lc.captchas.interfaces.Challenge
|
import lc.captchas.interfaces.Challenge
|
||||||
import java.util.{List => JavaList, Map => JavaMap}
|
import java.util.{List => JavaList, Map => JavaMap}
|
||||||
|
import lc.misc.PngImageWriter
|
||||||
|
|
||||||
class LabelCaptcha extends ChallengeProvider {
|
class LabelCaptcha extends ChallengeProvider {
|
||||||
private var knownFiles = new File("known").list.toList
|
private var knownFiles = new File("known").list.toList
|
||||||
@ -49,7 +50,7 @@ class LabelCaptcha extends ChallengeProvider {
|
|||||||
|
|
||||||
val token = encrypt(knownImageFile + "," + unknownImageFile)
|
val token = encrypt(knownImageFile + "," + unknownImageFile)
|
||||||
val baos = new ByteArrayOutputStream()
|
val baos = new ByteArrayOutputStream()
|
||||||
ImageIO.write(mergedImage, "png", baos)
|
PngImageWriter.write(baos, mergedImage);
|
||||||
|
|
||||||
new Challenge(baos.toByteArray(), "image/png", token)
|
new Challenge(baos.toByteArray(), "image/png", token)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user