diff --git a/jd/captcha/GifDecoder.java b/jd/captcha/GifDecoder.java new file mode 100644 index 0000000000..39a3839875 --- /dev/null +++ b/jd/captcha/GifDecoder.java @@ -0,0 +1,819 @@ +package jd.captcha; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; + +/** + * Form:http://www.java2s.com/Code/Java/2D-Graphics-GUI/GiffileEncoder.htm + * Class GifDecoder - Decodes a GIF file into one or more frames.
+ * + *
+ *  Example:
+ *     GifDecoder d = new GifDecoder();
+ *     d.read("sample.gif");
+ *     int n = d.getFrameCount();
+ *     for (int i = 0; i < n; i++) {
+ *        BufferedImage frame = d.getFrame(i);  // frame i
+ *        int t = d.getDelay(i);  // display duration of frame in milliseconds
+ *        // do something with frame
+ *     }
+ * 
+ * + * No copyright asserted on the source code of this class. May be used for any + * purpose, however, refer to the Unisys LZW patent for any additional + * restrictions. Please forward any corrections to kweiner@fmsware.com. + * + * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's + * ImageMagick. + * @version 1.03 November 2003 + * + */ + +public class GifDecoder { + + /** + * File read status: No errors. + */ + public static final int STATUS_OK = 0; + + /** + * File read status: Error decoding file (may be partially decoded) + */ + public static final int STATUS_FORMAT_ERROR = 1; + + /** + * File read status: Unable to open source. + */ + public static final int STATUS_OPEN_ERROR = 2; + + protected BufferedInputStream in; + + protected int status; + + protected int width; // full image width + + protected int height; // full image height + + protected boolean gctFlag; // global color table used + + protected int gctSize; // size of global color table + + protected int loopCount = 1; // iterations; 0 = repeat forever + + protected int[] gct; // global color table + + protected int[] lct; // local color table + + protected int[] act; // active color table + + protected int bgIndex; // background color index + + protected int bgColor; // background color + + protected int lastBgColor; // previous bg color + + protected int pixelAspect; // pixel aspect ratio + + protected boolean lctFlag; // local color table flag + + protected boolean interlace; // interlace flag + + protected int lctSize; // local color table size + + protected int ix, iy, iw, ih; // current image rectangle + + protected Rectangle lastRect; // last image rect + + protected BufferedImage image; // current frame + + protected BufferedImage lastImage; // previous frame + + protected byte[] block = new byte[256]; // current data block + + protected int blockSize = 0; // block size + + // last graphic control extension info + protected int dispose = 0; + + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + protected int lastDispose = 0; + + protected boolean transparency = false; // use transparent color + + protected int delay = 0; // delay in milliseconds + + protected int transIndex; // transparent color index + + protected static final int MaxStackSize = 4096; + + // max decoder pixel stack size + + // LZW decoder working arrays + protected short[] prefix; + + protected byte[] suffix; + + protected byte[] pixelStack; + + protected byte[] pixels; + + protected ArrayList frames; // frames read from current file + + protected int frameCount; + + static class GifFrame { + /** + * @param im + * @param del + */ + public GifFrame(BufferedImage im, int del) { + image = im; + delay = del; + } + + /** + * + */ + public BufferedImage image; + + /** + * + */ + public int delay; + } + + /** + * Gets display duration for specified frame. + * + * @param n + * int index of frame + * @return delay in milliseconds + */ + public int getDelay(int n) { + // + delay = -1; + if ((n >= 0) && (n < frameCount)) { + delay = ((GifFrame) frames.get(n)).delay; + } + return delay; + } + + /** + * Gets the number of frames read from file. + * + * @return frame count + */ + public int getFrameCount() { + return frameCount; + } + + /** + * Gets the first (or only) image read. + * + * @return BufferedImage containing first frame, or null if none. + */ + public BufferedImage getImage() { + return getFrame(0); + } + + /** + * Gets the "Netscape" iteration count, if any. A count of 0 means repeat + * indefinitiely. + * + * @return iteration count if one was specified, else 1. + */ + public int getLoopCount() { + return loopCount; + } + + /** + * Creates new frame image from current data (and previous frames as specified + * by their disposition codes). + */ + protected void setPixels() { + // expose destination image's pixels as int array + int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) { + if (lastDispose == 3) { + // use image before last + int n = frameCount - 2; + if (n > 0) { + lastImage = getFrame(n - 1); + } else { + lastImage = null; + } + } + + if (lastImage != null) { + int[] prev = ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); + System.arraycopy(prev, 0, dest, 0, width * height); + // copy pixels + + if (lastDispose == 2) { + // fill last image rect area with background color + Graphics2D g = image.createGraphics(); + Color c = null; + if (transparency) { + c = new Color(0, 0, 0, 0); // assume background is transparent + } else { + c = new Color(lastBgColor); // use given background color + } + g.setColor(c); + g.setComposite(AlphaComposite.Src); // replace area + g.fill(lastRect); + g.dispose(); + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) { + int line = i; + if (interlace) { + if (iline >= ih) { + pass++; + switch (pass) { + case 2: + iline = 4; + break; + case 3: + iline = 2; + inc = 4; + break; + case 4: + iline = 1; + inc = 2; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) { + // map color and insert in destination + int index = ((int) pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) { + dest[dx] = c; + } + dx++; + } + } + } + } + + /** + * Gets the image contents of frame n. + * @param n + * + * @return BufferedImage representation of frame, or null if n is invalid. + */ + public BufferedImage getFrame(int n) { + BufferedImage im = null; + if ((n >= 0) && (n < frameCount)) { + im = ((GifFrame) frames.get(n)).image; + } + return im; + } + + /** + * Gets image size. + * + * @return GIF image dimensions + */ + public Dimension getFrameSize() { + return new Dimension(width, height); + } + + /** + * Reads GIF image from stream + * + * @param is + * containing GIF file. + * @return read status code (0 = no errors) + */ + public int read(BufferedInputStream is) { + init(); + if (is != null) { + in = is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** + * Reads GIF image from stream + * + * @param is + * containing GIF file. + * @return read status code (0 = no errors) + */ + public int read(InputStream is) { + init(); + if (is != null) { + if (!(is instanceof BufferedInputStream)) + is = new BufferedInputStream(is); + in = (BufferedInputStream) is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** + * Reads GIF file from specified file/URL source (URL assumed if name contains + * ":/" or "file:") + * + * @param name + * String containing source + * @return read status code (0 = no errors) + */ + public int read(String name) { + status = STATUS_OK; + try { + name = name.trim().toLowerCase(); + if ((name.indexOf("file:") >= 0) || (name.indexOf(":/") > 0)) { + URL url = new URL(name); + in = new BufferedInputStream(url.openStream()); + } else { + in = new BufferedInputStream(new FileInputStream(name)); + } + status = read(in); + } catch (IOException e) { + status = STATUS_OPEN_ERROR; + } + + return status; + } + + /** + * Decodes LZW image data into pixel array. Adapted from John Cristy's + * ImageMagick. + */ + protected void decodeImageData() { + int NullCode = -1; + int npix = iw * ih; + int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi; + + if ((pixels == null) || (pixels.length < npix)) { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) + prefix = new short[MaxStackSize]; + if (suffix == null) + suffix = new byte[MaxStackSize]; + if (pixelStack == null) + pixelStack = new byte[MaxStackSize + 1]; + + // Initialize GIF data stream decoder. + + data_size = read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) { + prefix[code] = 0; + suffix[code] = (byte) code; + } + + // Decode GIF pixel stream. + + datum = bits = count = first = top = pi = bi = 0; + + for (i = 0; i < npix;) { + if (top == 0) { + if (bits < code_size) { + // Load bytes until there are enough bits for a code. + if (count == 0) { + // Read a new data block. + count = readBlock(); + if (count <= 0) + break; + bi = 0; + } + datum += (((int) block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + + // Get the next code. + + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + + if ((code > available) || (code == end_of_information)) + break; + if (code == clear) { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) { + pixelStack[top++] = (byte) first; + code = old_code; + } + while (code > clear) { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = ((int) suffix[code]) & 0xff; + + // Add a new string to the string table, + + if (available >= MaxStackSize) + break; + pixelStack[top++] = (byte) first; + prefix[available] = (short) old_code; + suffix[available] = (byte) first; + available++; + if (((available & code_mask) == 0) && (available < MaxStackSize)) { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + + for (i = pi; i < npix; i++) { + pixels[i] = 0; // clear missing pixels + } + + } + + /** + * Returns true if an error was encountered during reading/decoding + */ + protected boolean err() { + return status != STATUS_OK; + } + + /** + * Initializes or re-initializes reader + */ + protected void init() { + status = STATUS_OK; + frameCount = 0; + frames = new ArrayList(); + gct = null; + lct = null; + } + + /** + * Reads a single byte from the input stream. + */ + protected int read() { + int curByte = 0; + try { + curByte = in.read(); + } catch (IOException e) { + status = STATUS_FORMAT_ERROR; + } + return curByte; + } + + /** + * Reads next variable length block from input. + * + * @return number of bytes stored in "buffer" + */ + protected int readBlock() { + blockSize = read(); + int n = 0; + if (blockSize > 0) { + try { + int count = 0; + while (n < blockSize) { + count = in.read(block, n, blockSize - n); + if (count == -1) + break; + n += count; + } + } catch (IOException e) { + } + + if (n < blockSize) { + status = STATUS_FORMAT_ERROR; + } + } + return n; + } + + /** + * Reads color table as 256 RGB integer values + * + * @param ncolors + * int number of colors to read + * @return int array containing 256 colors (packed ARGB with full alpha) + */ + protected int[] readColorTable(int ncolors) { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try { + n = in.read(c); + } catch (IOException e) { + } + if (n < nbytes) { + status = STATUS_FORMAT_ERROR; + } else { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) { + int r = ((int) c[j++]) & 0xff; + int g = ((int) c[j++]) & 0xff; + int b = ((int) c[j++]) & 0xff; + tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; + } + } + return tab; + } + + /** + * Main file parser. Reads GIF content blocks. + */ + protected void readContents() { + // read GIF file content blocks + boolean done = false; + while (!(done || err())) { + int code = read(); + switch (code) { + + case 0x2C: // image separator + readImage(); + break; + + case 0x21: // extension + code = read(); + switch (code) { + case 0xf9: // graphics control extension + readGraphicControlExt(); + break; + + case 0xff: // application extension + readBlock(); + String app = ""; + for (int i = 0; i < 11; i++) { + app += (char) block[i]; + } + if (app.equals("NETSCAPE2.0")) { + readNetscapeExt(); + } else + skip(); // don't care + break; + + default: // uninteresting extension + skip(); + } + break; + + case 0x3b: // terminator + done = true; + break; + + case 0x00: // bad byte, but keep going and see what happens + break; + + default: + status = STATUS_FORMAT_ERROR; + } + } + } + + /** + * Reads Graphics Control Extension values + */ + protected void readGraphicControlExt() { + read(); // block size + int packed = read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = readShort() * 10; // delay in milliseconds + transIndex = read(); // transparent color index + read(); // block terminator + } + + /** + * Reads GIF file header information. + */ + protected void readHeader() { + String id = ""; + for (int i = 0; i < 6; i++) { + id += (char) read(); + } + if (!id.startsWith("GIF")) { + status = STATUS_FORMAT_ERROR; + return; + } + + readLSD(); + if (gctFlag && !err()) { + gct = readColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + /** + * Reads next frame image + */ + @SuppressWarnings("unchecked") +protected void readImage() { + ix = readShort(); // (sub)image position & size + iy = readShort(); + iw = readShort(); + ih = readShort(); + + int packed = read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + + if (lctFlag) { + lct = readColorTable(lctSize); // read table + act = lct; // make local table active + } else { + act = gct; // make global table active + if (bgIndex == transIndex) + bgColor = 0; + } + int save = 0; + if (transparency) { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + + if (act == null) { + status = STATUS_FORMAT_ERROR; // no color table defined + } + + if (err()) + return; + + decodeImageData(); // decode pixel data + skip(); + + if (err()) + return; + + frameCount++; + + // create new image to receive frame data + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + + setPixels(); // transfer pixel data to image + + frames.add(new GifFrame(image, delay)); // add image to frame list + + if (transparency) { + act[transIndex] = save; + } + resetFrame(); + + } + + /** + * Reads Logical Screen Descriptor + */ + protected void readLSD() { + + // logical screen size + width = readShort(); + height = readShort(); + + // packed fields + int packed = read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + + bgIndex = read(); // background color index + pixelAspect = read(); // pixel aspect ratio + } + + /** + * Reads Netscape extenstion to obtain iteration count + */ + protected void readNetscapeExt() { + do { + readBlock(); + if (block[0] == 1) { + // loop count sub-block + int b1 = ((int) block[1]) & 0xff; + int b2 = ((int) block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !err()); + } + + /** + * Reads next 16-bit value, LSB first + */ + protected int readShort() { + // read 16-bit value, LSB first + return read() | (read() << 8); + } + + /** + * Resets frame state for reading next image. + */ + protected void resetFrame() { + lastDispose = dispose; + lastRect = new Rectangle(ix, iy, iw, ih); + lastImage = image; + lastBgColor = bgColor; + @SuppressWarnings("unused") + int dispose = 0; + @SuppressWarnings("unused") + boolean transparency = false; + @SuppressWarnings("unused") + int delay = 0; + lct = null; + } + + /** + * Skips variable length blocks up to and including next zero length block. + */ + protected void skip() { + do { + readBlock(); + } while ((blockSize > 0) && !err()); + } +} \ No newline at end of file diff --git a/jd/captcha/JACScript.java b/jd/captcha/JACScript.java new file mode 100644 index 0000000000..77b1c471e5 --- /dev/null +++ b/jd/captcha/JACScript.java @@ -0,0 +1,1032 @@ +package jd.captcha; + +import java.io.File; +import java.util.Vector; +import java.util.logging.Logger; + +import jd.plugins.Plugin; + + +/** + * Diese Klasse parsed das JAC Script + * + * + * + * @author coalado + */ +public class JACScript { + /** + * Logger + */ + private Logger logger = Plugin.getLogger(); + + /** + * Prozentwert. Ab dieser Schwelle an Korektheit wird ein Letter als 100% + * richtig gewertet + */ + private double letterSearchLimitValue = 0.15; + + + + /** + * Kontrastwert für die Erkennung ob ein Pixel Farblich zu einem objekt passt (Kontrast Objektdurchschnitt/pixel) + */ + private double objectColorContrast=0.3; + /** + * Kontrastwert zur erkennung eines ObjektPixels (Kontrast Objekt/hintergrund) + */ + private double objectDetectionContrast=0.5; + /** + * Minimale Objektfläche für die Objekterkennung + */ + private int minimumObjectArea=200; + + /** + * GIbt an Ob die langsammere Object Detection anstelle der sonst Üblichen Reihen Detection verwendet werden soll + */ + private boolean useObjectDetection =false; + + + + /** + * Vector für die Befehle die für die Vorverarbeitung des Captchas verwendet + * werden. (script.jas) + */ + private Vector captchaPrepareCommands; + + /** + * Vector für die Befehle die für die Ekennung allgemein gelten (script.jas) + */ + private Vector jacCommands; + + private Vector letterCommands; +/** + * Maximaler Drehwinkel nach links + */ + private int leftAngle=-10; + /** + * Maximaler drehwinkel nach rechts + */ + private int rightAngle=10; + /** + * Parameter: Gibt die Anzahl der Reihen(Pixel) an die zur peak detection + * verwendet werden sollen + */ + private int gapWidthPeak = 1; + + /** + * Gibt die Verwendete Farbkombination an. Siehe JAC Script Docu für + * genauere Infos + */ + private String ColorType = "h"; + + /** + * Parameter: Gibt die Anzahl der reihen an die zur Average Detection + * verwendet werden sollen + */ + private int gapWidthAverage = 1; + + /** + * Parameter: gapAndAverageLogic=true: Es werden Lücken verwendet bei denen + * Peak und Average detection zusammenfallen (AND) gapAndAverageLogic=false: + * Es werden sowohl peak als Auch Average Lücken verwendet (nur in + * Ausnahmefällen) (OR) + */ + private boolean gapAndAverageLogic = true; + + /** + * Parameter: Der Kontrastwert für die Average Detection. ~1 + */ + private double gapDetectionAverageContrast = 1.3; + + /** + * Parameter: Der Kontrastwert für die Peak Detection. ~0.25 + */ + private double gapDetectionPeakContrast = 0.25; + + /** + * Parameter: Average Detection verwenden + */ + private boolean useAverageGapDetection = false; + + /** + * Parameter: Peak Detection verwenden + */ + private boolean usePeakGapdetection = true; + + /** + * Parameter: Kontrollwert über die minimale Buchstabenbreite + */ + private int minimumLetterWidth = 10; + + /** + * Parameter: Wert gibt an um welchen faktor die Fingerprints verkleinert + * werden. So groß wie möglich, so klein wie nötig Wenn dieser Wert + * verändert wird, wrd die MTH File unbrauchbar und muss neu trainiert + * werden + */ + private int simplifyFaktor = 1; + + + + + /** + * Parameter: Allgemeiner Bildkontrastparameter ~0.8 bis 1.2 + */ + private double relativeContrast = 0.85; + + /** + * Parameter: Gibt die Tolleranz beim Säubern des Hintergrunds an ~0.05-0.5 + */ + private double backgroundSampleCleanContrast = 0.1; + + /** + * Parameter: Gibt für dieverse SW Umwandlungen den Schwellwert an + */ + private double blackPercent = 0.1; + + /** + * Werte-Array Wird gaps != null, so werden die Werte als Trennpositionen + * für die letter detection verwendet. Alle anderen Erkennungen werden dann + * ignoriert + */ + private int[] gaps; + + + /** + * Gibt an ob beim Training nur falscherkannte Buchstaben gespeichert werden + * (true) oder alle (False) + */ + private boolean trainOnlyUnknown = true; + + + + /** + * Parameter: Scan-Parameter. Gibt an um wieviele Pixel sich Letter und + * Vergleichsletter unterscheiden dürfen um verglichen zu werden. Hohe Werte + * machen das ganze Langsam + */ + private int borderVariance = 0; + + /** + * Parameter: Scan-Parameter. Gibt an um wieviele Pixel Letter und + * Vergleichsletter gegeneinander verschoben werden um die beste + * Übereinstimung zu finden. Hohe werte verlangemmen die Erkennung deutlich + */ + private int scanVariance = 0; +/** + * Internes Farbarray. Hier werden die Eingaben über setColorFormat abgelegt + */ + private int[] colorComponents = { 3, 3, 3 }; +/** + * Internet Umrechnungsfaktor. Jenach verwendetem farbmodell. Wird automatisch gesetzt + */ + private int colorFaktor; +/** + * Farbwert für den verwendeten Farbraum. 0: hsb 1: RGB + */ + private int color; + + private JAntiCaptcha owner; + private File scriptFile; + private String method; + + + /** + * @param owner + * @param script + */ + public JACScript(JAntiCaptcha owner, File script) { + + this.owner=owner; + this.method=script.getParentFile().getName(); + this.scriptFile=script; + this.parseScriptFile(); + this.executeParameterCommands(); + + } + + + /** + * Diese Methode führt die zuvor eingelesenen JAC Script Befehle aus + */ + private void executeParameterCommands() { + if (jacCommands == null || jacCommands.size() == 0) { + logger.info("KEINE JAC COMMANDS"); + return; + } + logger.info("Execute Script.jas Parameter scripts"); + try { + for (int i = 0; i < jacCommands.size(); i++) { + String[] cmd = jacCommands.elementAt(i); + + if (cmd[0].equals("parameter")) { + if (cmd[1].equalsIgnoreCase("lettersearchlimitvalue")) + this.setLetterSearchLimitValue(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("trainonlyunknown")) + this.setTrainOnlyUnknown(cmd[2].equals("true")); + else if (cmd[1].equalsIgnoreCase("scanvariance")) + this.setScanVariance(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("bordervariance")) + this.setBorderVariance(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("simplifyfaktor")) { + this.setSimplifyFaktor(Integer.parseInt(cmd[2])); + } + else if (cmd[1].equalsIgnoreCase("gapwidthpeak")) + this.setGapWidthPeak(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("gapwidthaverage")) + this.setGapWidthAverage(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("ColorType")) + this.setColorType(cmd[2]); + else if (cmd[1].equalsIgnoreCase("gapandaveragelogic")) + this.setGapAndAverageLogic(cmd[2].equals("true")); + else if (cmd[1].equalsIgnoreCase("gapdetectionaveragecontrast")) + this.setGapDetectionAverageContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("gapdetectionpeakcontrast")) + this.setGapDetectionPeakContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("useaveragegapdetection")) + this.setUseAverageGapDetection(cmd[2].equals("true")); + else if (cmd[1].equalsIgnoreCase("usepeakgapdetection")) + this.setUsePeakGapdetection(cmd[2].equals("true")); + else if (cmd[1].equalsIgnoreCase("minimumletterwidth")) + this.setMinimumLetterWidth(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("leftAngle")) + this.setLeftAngle(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("rightAngle")) + this.setRightAngle(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("relativecontrast")) + this.setRelativeContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("backgroundsamplecleancontrast")) + this.setBackgroundSampleCleanContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("blackpercent")) + this.setBlackPercent(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("objectColorContrast")) + this.setObjectColorContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("objectDetectionContrast")) + this.setObjectDetectionContrast(Double.parseDouble(cmd[2])); + else if (cmd[1].equalsIgnoreCase("minimumObjectArea")) + this.setMinimumObjectArea(Integer.parseInt(cmd[2])); + else if (cmd[1].equalsIgnoreCase("useObjectDetection")) + this.setUseObjectDetection(cmd[2].equals("true")); + else if (cmd[1].equalsIgnoreCase("gaps")) { + + cmd[2] = cmd[2].substring(1, cmd[2].length() - 1); + String[] gaps = cmd[2].split("\\,"); + int[] newGaps = new int[gaps.length]; + for (int ii = 0; ii < gaps.length; ii++){ + + newGaps[ii] = Integer.parseInt(gaps[ii]); + } + this.setGaps(newGaps); + + + + } else { + logger.severe("Error in " + method + "/+script.jas : Parameter not valid: " + cmd[1] + " = " + cmd[2]); + } + + } else { + logger.severe("Syntax Error in " + method + "/+script.jas"); + } + } + } catch (Exception e) { + logger.severe("Syntax Error in " + method + "/+script.jas"); + } + + } + + /** + * Diese Methode führt die zuvor eingelesenen JAc Script Prepare Befehle aus + * @param captcha + */ + public void executePrepareCommands(Captcha captcha) { + if (captcha.isPrepared()) { + // ISt schon prepared + return; + } + + logger.info("Execute Script.jas Prepare scripts"); + captcha.setPrepared(true); + String[] params; + try { + for (int i = 0; i < this.captchaPrepareCommands.size(); i++) { + String[] cmd = captchaPrepareCommands.elementAt(i); + logger.info("Execute Function: " + cmd[1] + "(" + cmd[2] + ")"); + + if (cmd[0].equals("parameter")) { + logger.severe("Syntax Error in " + method + "/+script.jas"); + // captchaPrepareCommands + + } else if (cmd[0].equals("function") && cmd[2] == null) { + + if (cmd[1].equalsIgnoreCase("invert")) { + captcha.invert(); + continue; + } else if (cmd[1].equalsIgnoreCase("toBlackAndWhite")) { + captcha.toBlackAndWhite(); + continue; + } else if (cmd[1].equalsIgnoreCase("clean")) { + captcha.clean(); + continue; + } else { + logger.severe("Error in " + method + "/+script.jas : Function not valid: " + cmd[1] + "(" + cmd[2] + ")"); + } + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 1) { + + if (cmd[1].equalsIgnoreCase("toBlackAndWhite")) { + captcha.toBlackAndWhite(Double.parseDouble(params[0].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("reduceWhiteNoise")) { + captcha.reduceWhiteNoise(Integer.parseInt(params[0].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("convertPixel")) { + captcha.convertPixel(params[0].trim()); + continue; + } else if (cmd[1].equalsIgnoreCase("reduceBlackNoise")) { + captcha.reduceBlackNoise(Integer.parseInt(params[0].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("blurIt")) { + captcha.blurIt(Integer.parseInt(params[0].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("sampleDown")) { + captcha.sampleDown(Integer.parseInt(params[0].trim())); + continue; + }else if (cmd[1].equalsIgnoreCase("cleanBackgroundByColor")) { + captcha.cleanBackgroundByColor(Integer.parseInt(params[0].trim())); + continue; + } + + else if (cmd[1].equalsIgnoreCase("saveImageasJpg")) { + + captcha.saveImageasJpg(new File(params[0].trim())); + continue; + } else { + logger.severe("Error in " + method + "/+script.jas : Function not valid: " + cmd[1] + "(" + cmd[2] + ")"); + } + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 2) { + if (cmd[1].equalsIgnoreCase("reduceWhiteNoise")) { + captcha.reduceWhiteNoise(Integer.parseInt(params[0].trim()), Double.parseDouble(params[1].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("reduceBlackNoise")) { + captcha.reduceBlackNoise(Integer.parseInt(params[0].trim()), Double.parseDouble(params[1].trim())); + continue; + } else { + logger.severe("Error in " + method + "/+script.jas : Function not valid: " + cmd[1] + "(" + cmd[2] + ")"); + } + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 3) { + if (cmd[1].equalsIgnoreCase("cleanWithMask")) { + captcha.cleanWithMask(owner.createCaptcha(UTILITIES.loadImage(new File(params[0].trim()))), Integer.parseInt(params[1].trim()), Integer.parseInt(params[2].trim())); + continue; + }else if (cmd[1].equalsIgnoreCase("removeSmallObjects")) { + captcha.removeSmallObjects(Double.parseDouble(params[0].trim()), Double.parseDouble(params[1].trim()), Integer.parseInt(params[2].trim())); + continue; + }else { + logger.severe("Error in " + method + "/+script.jas : Function not valid: " + cmd[1] + "(" + cmd[2] + ")"); + } + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 4) { + + if (cmd[1].equalsIgnoreCase("cleanBackgroundBySample")) { + captcha.cleanBackgroundBySample(Integer.parseInt(params[0].trim()), Integer.parseInt(params[1].trim()), Integer.parseInt(params[2].trim()), Integer.parseInt(params[3].trim())); + continue; + } else if (cmd[1].equalsIgnoreCase("crop")) { + captcha.crop(Integer.parseInt(params[0].trim()), Integer.parseInt(params[1].trim()), Integer.parseInt(params[2].trim()), Integer.parseInt(params[3].trim())); + + continue; + } + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 5) { + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 6) { + + } + + } + } catch (Exception e) { + logger.severe("Syntax Error in " + method + "/script.jas"); + + } + // BasicWindow.showImage(captcha.getImage(),120,80); + } + + /** + * @param letter + */ + public void executeLetterPrepareCommands(Letter letter) { + + + logger.info("Execute Script.jas Letter Prepare scripts"); + + String[] params; + try { + for (int i = 0; i < this.letterCommands.size(); i++) { + String[] cmd = letterCommands.elementAt(i); + logger.info("Execute Function: " + cmd[1] + "(" + cmd[2] + ")"); + + if (cmd[0].equals("parameter")) { + logger.severe("Syntax Error in " + method + "/+script.jas"); + // captchaPrepareCommands + + } else if (cmd[0].equals("function") && cmd[2] == null) { + + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 1) { + + + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 2) { + + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 3) { + if (cmd[1].equalsIgnoreCase("removeSmallObjects")) { + + letter.removeSmallObjects(Double.parseDouble(params[0].trim()), Double.parseDouble(params[1].trim()), Integer.parseInt(params[2].trim())); + continue; + }else { + logger.severe("Error in " + method + "/+script.jas : Function not valid: " + cmd[1] + "(" + cmd[2] + ")"); + } + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 4) { + + + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 5) { + + } else if (cmd[0].equals("function") && (params = cmd[2].split("\\,")).length == 6) { + + } + + } + } catch (Exception e) { + logger.severe("Syntax Error in " + method + "/script.jas"); + + } + // BasicWindow.showImage(captcha.getImage(),120,80); + } + /** + * Diese Methode liest das script.jas ein. und parsed es + */ + private void parseScriptFile() { + logger.info("parsing Script.jas"); + + String script = UTILITIES.getLocalFile(scriptFile); + String[] lines = script.split("\r\n"); + if (lines.length == 1) + lines = script.split("\n\r"); + if (lines.length == 1) + lines = script.split("\n"); + if (lines.length == 1) + lines = script.split("\r"); + Vector localCaptchaPrepareCommands = new Vector(); + Vector localJacCommands = new Vector(); + Vector localLetterCommands = new Vector(); + int startAt; + String[] pcmd; + for (int i = 0; i < lines.length; i++) { + + lines[i] = lines[i].trim(); + + if (lines[i].indexOf("#") == 0 || lines[i].trim().length() < 3) { + // leere Zeile, oder Comment + continue; + } + if (!lines[i].substring(lines[i].length() - 1).equals(";")) { + logger.severe(method + "/script.jas: Syntax error (; missing?) near line " + i + ": " + lines[i]); + return; + } + lines[i] = lines[i].substring(0, lines[i].length() - 1); + if ((startAt = lines[i].indexOf("captcha.prepare.")) == 0) { + pcmd = parseCommand(lines[i].substring(startAt + 16)); + + localCaptchaPrepareCommands.add(pcmd); + } else if ((startAt = lines[i].indexOf("param.")) == 0) { + pcmd = parseCommand(lines[i].substring(startAt + 6)); + if (!pcmd[0].equals("parameter")) { + logger.severe(method + "/script.jas: Syntax (parameter1) error near line " + i + ": " + lines[i]); + } + + localJacCommands.add(pcmd); + } else if ((startAt = lines[i].indexOf("letter.prepare.")) == 0) { + pcmd = parseCommand(lines[i].substring(startAt + 15)); + UTILITIES.trace(pcmd); + + localLetterCommands.add(pcmd); + + } else { + logger.severe(method + "/script.jas: Syntax error near line " + i + ": " + lines[i]); + } + } + this.captchaPrepareCommands=localCaptchaPrepareCommands; + this.jacCommands=localJacCommands; + this.letterCommands=localLetterCommands; + + } + + /** + * Diese methode nimmt eine zeile der script.jas entgegen und parsed sie + * + * @param cmd + * Zeile eines *.jas scripts + * @return Array:{Befehltyp, befehl,parameter} + */ + private String[] parseCommand(String cmd) { + String[] ret = new String[3]; + String[] matches; + cmd = "#" + cmd + "#"; + if ((matches = UTILITIES.getMatches(cmd, "#°=°#")) != null) { + + ret[0] = "parameter"; + ret[1] = matches[0].trim(); + ret[2] = matches[1].replaceAll("\\\"", "").trim(); + + } else if ((matches = UTILITIES.getMatches(cmd, "#°(°)#")) != null) { + ret[0] = "function"; + ret[1] = matches[0].trim(); + ret[2] = matches[1].replaceAll("\\\"", "").trim(); + if (ret[2].length() == 0) + ret[2] = null; + } else if ((matches = UTILITIES.getMatches(cmd, "#°()#")) != null) { + ret[0] = "function"; + ret[1] = matches[0].trim(); + ret[2] = null; + } + return ret; + } + + + + + + + /** + * @return the captchaPrepareCommands + */ + public Vector getCaptchaPrepareCommands() { + return captchaPrepareCommands; + } + + + + /** + * @return the jacCommands + */ + public Vector getJacCommands() { + return jacCommands; + } + + + + + + /** + * @return the gapAndAverageLogic + */ + public boolean getGapAndAverageLogic() { + return gapAndAverageLogic; + } + + /** + * @param gapAndAverageLogic + * the gapAndAverageLogic to set + */ + public void setGapAndAverageLogic(boolean gapAndAverageLogic) { + logger.info("SET PARAMETER: [gapAndAverageLogic] = " + gapAndAverageLogic); + this.gapAndAverageLogic = gapAndAverageLogic; + } + + /** + * @return the gapDetectionAverageContrast + */ + public double getGapDetectionAverageContrast() { + return gapDetectionAverageContrast; + } + + /** + * @param gapDetectionAverageContrast + * the gapDetectionAverageContrast to set + */ + public void setGapDetectionAverageContrast(double gapDetectionAverageContrast) { + logger.info("SET PARAMETER: [gapDetectionAverageContrast] = " + gapDetectionAverageContrast); + this.gapDetectionAverageContrast = gapDetectionAverageContrast; + } + + /** + * @return the gapDetectionPeakContrast + */ + public double getGapDetectionPeakContrast() { + return gapDetectionPeakContrast; + } + + /** + * @param gapDetectionPeakContrast + * the gapDetectionPeakContrast to set + */ + public void setGapDetectionPeakContrast(double gapDetectionPeakContrast) { + logger.info("SET PARAMETER: [gapDetectionPeakContrast] = " + gapDetectionPeakContrast); + this.gapDetectionPeakContrast = gapDetectionPeakContrast; + } + + /** + * @return the gaps + */ + public int[] getGaps() { + return gaps; + } + + /** + * @param gaps + * the gaps to set + */ + public void setGaps(int[] gaps) { + logger.info("SET PARAMETER: [gaps] = "+gaps.toString()); + + this.gaps = gaps; + } + + /** + * @return the gapWidthAverage + */ + public int getGapWidthAverage() { + return gapWidthAverage; + } + + /** + * @param gapWidthAverage + * the gapWidthAverage to set + */ + public void setGapWidthAverage(int gapWidthAverage) { + logger.info("SET PARAMETER: [gapWidthAverage] = " + gapWidthAverage); + this.gapWidthAverage = gapWidthAverage; + } + + /** + * @return the gapWidthPeak + */ + public int getGapWidthPeak() { + return gapWidthPeak; + } + + /** + * @param gapWidthPeak + * the gapWidthPeak to set + */ + public void setGapWidthPeak(int gapWidthPeak) { + logger.info("SET PARAMETER: [gapWidthPeak] = " + gapWidthPeak); + this.gapWidthPeak = gapWidthPeak; + } + + + + + + /** + * @return the letterSearchLimitValue + */ + public double getLetterSearchLimitValue() { + return letterSearchLimitValue; + } + + /** + * @param letterSearchLimitValue + * the letterSearchLimitValue to set + */ + public void setLetterSearchLimitValue(double letterSearchLimitValue) { + logger.info("SET PARAMETER: [letterSearchLimitValue] = " + letterSearchLimitValue); + this.letterSearchLimitValue = letterSearchLimitValue; + } + + /** + * @return the minimumLetterWidth + */ + public int getMinimumLetterWidth() { + return minimumLetterWidth; + } + + /** + * @param minimumLetterWidth + * the minimumLetterWidth to set + */ + public void setMinimumLetterWidth(int minimumLetterWidth) { + logger.info("SET PARAMETER: [minimumLetterWidth] = " + minimumLetterWidth); + this.minimumLetterWidth = minimumLetterWidth; + } + + /** + * @return the useAverageGapDetection + */ + public boolean isUseAverageGapDetection() { + return useAverageGapDetection; + } + + /** + * @param useAverageGapDetection + * the useAverageGapDetection to set + */ + public void setUseAverageGapDetection(boolean useAverageGapDetection) { + logger.info("SET PARAMETER: [useAverageGapDetection] = " + useAverageGapDetection); + this.useAverageGapDetection = useAverageGapDetection; + } + + /** + * @return the usePeakGapdetection + */ + public boolean isUsePeakGapdetection() { + + return usePeakGapdetection; + } + + /** + * @param usePeakGapdetection + * the usePeakGapdetection to set + */ + public void setUsePeakGapdetection(boolean usePeakGapdetection) { + logger.info("SET PARAMETER: [usePeakGapdetection] = " + usePeakGapdetection); + this.usePeakGapdetection = usePeakGapdetection; + } + + /** + * @return the backgroundSampleCleanContrast + */ + public double getBackgroundSampleCleanContrast() { + return backgroundSampleCleanContrast; + } + + /** + * @param backgroundSampleCleanContrast + * the backgroundSampleCleanContrast to set + */ + public void setBackgroundSampleCleanContrast(double backgroundSampleCleanContrast) { + logger.info("SET PARAMETER: [backgroundSampleCleanContrast] = " + backgroundSampleCleanContrast); + this.backgroundSampleCleanContrast = backgroundSampleCleanContrast; + } + + /** + * @return the blackPercent + */ + public double getBlackPercent() { + return blackPercent; + } + + /** + * @param blackPercent + * the blackPercent to set + */ + public void setBlackPercent(double blackPercent) { + logger.info("SET PARAMETER: [blackPercent] = " + blackPercent); + this.blackPercent = blackPercent; + } + + + + /** + * @return the relativeContrast + */ + public double getRelativeContrast() { + return relativeContrast; + } + + /** + * @param relativeContrast + * the relativeContrast to set + */ + public void setRelativeContrast(double relativeContrast) { + logger.info("SET PARAMETER: [relativeContrast] = " + relativeContrast); + this.relativeContrast = relativeContrast; + } + + /** + * @return the simplifyFaktor + */ + public int getSimplifyFaktor() { + return simplifyFaktor; + } + + /** + * @param simplifyFaktor + * the simplifyFaktor to set + */ + public void setSimplifyFaktor(int simplifyFaktor) { + logger.info("SET PARAMETER: [simplifyFaktor] = " + simplifyFaktor); + this.simplifyFaktor = simplifyFaktor; + } + + /** + * @return the borderVariance + */ + public int getBorderVariance() { + return borderVariance; + } + + /** + * @param borderVariance + * the borderVariance to set + */ + public void setBorderVariance(int borderVariance) { + logger.info("SET PARAMETER: [borderVariance] = " + borderVariance); + this.borderVariance = borderVariance; + } + + /** + * @return the scanVariance + */ + public int getScanVariance() { + return scanVariance; + } + + /** + * @param scanVariance + * the scanVariance to set + */ + public void setScanVariance(int scanVariance) { + logger.info("SET PARAMETER: [scanVariance] = " + scanVariance); + this.scanVariance = scanVariance; + } + + /** + * @return the trainOnlyUnknown + */ + public boolean isTrainOnlyUnknown() { + return trainOnlyUnknown; + } + + /** + * @param trainOnlyUnknown + * the trainOnlyUnknown to set + */ + public void setTrainOnlyUnknown(boolean trainOnlyUnknown) { + this.trainOnlyUnknown = trainOnlyUnknown; + } + + /** + * @return the ColorType + */ + public String getColorType() { + return ColorType; + } + + + /** + * @param type + * the ColorType to set + */ + public void setColorType(String type) { + ColorType = type; + int[] components = { 3, 3, 3 }; + colorFaktor = 1; + + for (int i = type.length() - 1; i >= 0; i--) { + if (type.charAt(i) == 'h') { + components[i + 3 - type.length()] = 0; + colorFaktor *= 256; + color = 0; + } + if (type.charAt(i) == 's') { + components[i + 3 - type.length()] = 1; + colorFaktor *= 256; + color = 0; + } + if (type.charAt(i) == 'b') { + components[i + 3 - type.length()] = 2; + colorFaktor *= 256; + color = 0; + } + if (type.charAt(i) == 'R') { + components[i + 3 - type.length()] = 0; + colorFaktor *= 256; + color = 1; + } + if (type.charAt(i) == 'G') { + components[i + 3 - type.length()] = 1; + colorFaktor *= 256; + color = 1; + } + if (type.charAt(i) == 'B') { + components[i + 3 - type.length()] = 2; + colorFaktor *= 256; + color = 1; + } + } + + colorComponents = components; + } + + /** + * @return Aktueller Colorfaktor (255^verwendete farbkomponenten) + */ + public int getColorFaktor() { + return colorFaktor; + } + + /** + * Gibt die Farbkomponente für die 255^i Gewcihtung zurück + * @param i + * @return FarbKomponente an i + */ + public int getColorComponent(int i) { + + return colorComponents[i]; + } + + /** + * @return the color + */ + public int getColorFormat() { + return color; + } + + /** + * @return the minimumObjectArea + */ + public int getMinimumObjectArea() { + return minimumObjectArea; + } + + /** + * @param minimumObjectArea the minimumObjectArea to set + */ + public void setMinimumObjectArea(int minimumObjectArea) { + logger.info("SET PARAMETER: [minimumObjectArea] = " + minimumObjectArea); + this.minimumObjectArea = minimumObjectArea; + } + + /** + * @return the objectColorContrast + */ + public double getObjectColorContrast() { + return objectColorContrast; + } + + /** + * @param objectColorContrast the objectColorContrast to set + */ + public void setObjectColorContrast(double objectColorContrast) { + logger.info("SET PARAMETER: [objectColorContrast] = " + objectColorContrast); + this.objectColorContrast = objectColorContrast; + } + + /** + * @return the objectDetectionContrast + */ + public double getObjectDetectionContrast() { + return objectDetectionContrast; + } + + /** + * @param objectDetectionContrast the objectDetectionContrast to set + */ + public void setObjectDetectionContrast(double objectDetectionContrast) { + logger.info("SET PARAMETER: [objectDetectionContrast] = " + objectDetectionContrast); + this.objectDetectionContrast = objectDetectionContrast; + } + + /** + * @return the useObjectDetection + */ + public boolean isUseObjectDetection() { + + return useObjectDetection; + } + + /** + * @param useObjectDetection the useObjectDetection to set + */ + public void setUseObjectDetection(boolean useObjectDetection) { + logger.info("SET PARAMETER: [useObjectDetection] = " + useObjectDetection); + this.useObjectDetection = useObjectDetection; + } + + + /** + * @return the leftAngle + */ + public int getLeftAngle() { + return leftAngle; + } + + + /** + * @param leftAngle the leftAngle to set + */ + public void setLeftAngle(int leftAngle) { + this.leftAngle = leftAngle; + } + + + /** + * @return the rightAngle + */ + public int getRightAngle() { + return rightAngle; + } + + + /** + * @param rightAngle the rightAngle to set + */ + public void setRightAngle(int rightAngle) { + this.rightAngle = rightAngle; + } + +} \ No newline at end of file