Пример #1
0
  private QrDecodingResult decodeQR(BufferedImage image, int filenumber) {
    // Create qr image from original for decoding

    BufferedImage qrcorner = extractTopRightCornerForQR(image);
    BufferedImage blackWhite =
        new BufferedImage(
            qrcorner.getWidth() / 2, qrcorner.getHeight() / 2, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = blackWhite.createGraphics();
    g2d.drawImage(qrcorner, 0, 0, qrcorner.getWidth() / 2, qrcorner.getHeight() / 2, null);
    g2d.dispose();
    qrcorner = blackWhite;

    QrDecodingResult decodingresult = new QrDecodingResult();

    try {

      // Decode QR
      Result result = null;
      Exception decodeException = null;

      // Try to decode at least three times
      int maxattempts = 3;
      int attempt = 1;
      while (attempt <= maxattempts) {
        logger.debug("Attempt " + attempt);
        try {
          BinaryBitmap bitmap = getBitmapFromBufferedImage(qrcorner);
          result = reader.decode(bitmap);
          decodeException = null;
          logger.debug("Success!");
          break;
        } catch (Exception e) {
          decodeException = e;
          if (debugcorners) {
            try {
              ImageIO.write(
                  (RenderedImage) qrcorner,
                  "jpg",
                  new File(
                      tempdir.getAbsolutePath() + "/corner" + filenumber + "_" + attempt + ".jpg"));
            } catch (IOException ex) {
              ex.printStackTrace();
            }
          }
        }
        attempt++;
        com.jhlabs.image.MedianFilter filter = new MedianFilter();
        BufferedImage newqrcorner =
            new BufferedImage(
                qrcorner.getWidth(), qrcorner.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        filter.filter(qrcorner, newqrcorner);
        qrcorner = newqrcorner;
      }

      if (decodeException != null) throw decodeException;

      // Clean the output from the QR
      decodingresult.setOutput(result.getText().replace(" ", "").trim());

      // The image filename will be the output
      decodingresult.setFilename(decodingresult.getOutput());

      // Consistency checking
      if (decodingresult.getFilename().length() == 0) {
        decodingresult.setFilename("ERROR-EMPTYQR-" + (filenumber + 1));
      } else {
        String[] parts = decodingresult.getFilename().split("-");

        // Now check if the QR string has five parts (which indicates it is an answer sheet)
        if (parts.length == 5 && parts[4].trim().contains("BB")) {
          decodingresult.setAttemptId(Integer.parseInt(parts[3]));
          decodingresult.setAnswersheet(true);
        }

        // Now check if the QR string has a fourth component (image is rotated)
        if (parts.length == 4 && parts[3].trim().contains("R")) {
          decodingresult.setRotated(true);
        }

        // If everything looks well, parse the numbers from the decoded QR info
        if (parts.length >= 3) {

          // Parse the parts (any exception will be caught as an error)
          decodingresult.setUserid(Integer.parseInt(parts[0]));
          decodingresult.setCourseid(Integer.parseInt(parts[1]));
          decodingresult.setExampage(Integer.parseInt(parts[2]));

          // Set filename with the corresponding IDs
          decodingresult.setFilename(
              decodingresult.getUserid()
                  + "-"
                  + decodingresult.getCourseid()
                  + "-"
                  + decodingresult.getExampage());

          // Processing was a success
          decodingresult.setSuccess(true);
        } else {
          logger.error("QR contains invalid information");
          decodingresult.setFilename("ERROR-INVALIDPARTSQR-" + (filenumber + 1));
        }
      }
    } catch (NotFoundException e) {
      decodingresult.setFilename("ERROR-NOTFOUND-" + (filenumber + 1));
    } catch (ChecksumException e) {
      decodingresult.setFilename("ERROR-CHECKSUM-" + (filenumber + 1));
    } catch (FormatException e) {
      decodingresult.setFilename("ERROR-CHECKSUM-" + (filenumber + 1));
    } catch (Exception e) {
      decodingresult.setFilename("ERROR-NULL-" + (filenumber + 1));
    }

    // Regardless of the result, the back-file name is the sames as the file with a b
    decodingresult.setBackfilename(decodingresult.getFilename() + "b");

    return decodingresult;
  }
Пример #2
0
  /* (non-Javadoc)
   * @see java.lang.Runnable#run()
   */
  @Override
  public void run() {

    // First decode the frontpage
    this.qrResult = decodeQR(image, filenumber);

    // If we couldn't find a code, but we have a backpage, we try processing it
    if (!qrResult.isSuccess() && this.doubleside) {
      QrDecodingResult qrresultback = decodeQR(backimage, filenumber);

      // If the backpage contains a valid QR then it was flipped, we flip the front and backpages
      if (qrresultback.isSuccess()) {
        // Flip front and backpages
        BufferedImage tmp = this.image;
        this.image = this.backimage;
        this.backimage = tmp;

        // Replace decoding info with the backpage
        qrResult = qrresultback;
      }
    }

    float factor = 1200f / this.image.getWidth();
    this.image = resizeImage(this.image, factor);
    if (this.backimage != null) {
      this.image = resizeImage(this.image, factor);
    }

    // If images were rotated, both are rotated
    if (qrResult.isSuccess() && qrResult.isRotated()) {
      this.image = rotateImage180(this.image);
      if (this.doubleside) {
        this.backimage = rotateImage180(this.backimage);
      }
    }

    // All numbers are ok, now create the anonymous version of the page
    this.anonymous = createAnonymousVersion(image);
    if (this.doubleside) {
      this.backanonymous = createAnonymousVersion(this.backimage);
    }

    this.success = qrResult.isSuccess();
    this.rotated = qrResult.isRotated();

    if (this.success && qrResult.isAnswersheet() && this.moodle.getOMRTemplate() != null) {
      TreeMap<String, String> answers = new TreeMap<String, String>();
      FormTemplate formTemplate = null;
      try {
        File omrtemplatefile = new File(this.moodle.getOMRTemplate());
        formTemplate = new FormTemplate(omrtemplatefile);
        FormTemplate filledForm = new FormTemplate(qrResult.getFilename(), formTemplate);
        filledForm.findCorners(
            anonymous, this.moodle.getOMRthreshold(), this.moodle.getOMRdensity());
        filledForm.findPoints(
            anonymous,
            this.moodle.getOMRthreshold(),
            this.moodle.getOMRdensity(),
            this.moodle.getOMRshapeSize());

        for (String key : filledForm.getFields().keySet()) {
          FormField ff = filledForm.getField(key);
          answers.put(key, ff.getValues());
        }

        qrResult.setAnswers(answers);
      } catch (Exception e) {
        logger.error("Problem with the OMR template");
        e.printStackTrace();
      }
    }

    // Now write images as files
    try {
      ImageIO.write(
          (RenderedImage) image,
          imageExtension,
          new File(
              tempdir.getAbsolutePath() + "/" + qrResult.getFilename() + "." + imageExtension));
      ImageIO.write(
          (RenderedImage) anonymous,
          imageExtension,
          new File(
              tempdir.getAbsolutePath() + "/" + qrResult.getFilename() + "_a." + imageExtension));
      if (doubleside) {
        ImageIO.write(
            (RenderedImage) backimage,
            imageExtension,
            new File(
                tempdir.getAbsolutePath()
                    + "/"
                    + qrResult.getBackfilename()
                    + "."
                    + imageExtension));
        ImageIO.write(
            (RenderedImage) backanonymous,
            imageExtension,
            new File(
                tempdir.getAbsolutePath()
                    + "/"
                    + qrResult.getBackfilename()
                    + "_a."
                    + imageExtension));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }