← All tasks
javaclaude-code/java-t1 #46Not a task: not reproduced

QR Code Generator and Reader (java, written by Claude Code)

envgap__claude-code__java-t1-46

Written by a coding agent; not on GitHubWritten 2026-02-28

01 / FAILURE SIGNATURE

As the study recorded it

cannot find symbol: class MultipleBarcodeReader
Not a benchmark task.
  • In a clean container the reported failure did not reproduce, or the known fix did not make the project run.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
pom.xml
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

claude-code/java-t1 #46 · read the task the agent was given
Claude Code wrote this java project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: QR Code Generator and Reader

Write a program that generates QR codes from text or URLs and reads/decodes QR codes from image files, supporting multiple output formats and error correction levels.

FUNCTIONAL REQUIREMENTS:
- Support two subcommands: generate and read
- generate: Accept text or URL content via command-line argument and produce a QR code image
- Support configurable error correction levels via --error-correction flag: L (7%), M (15%), Q (25%), H (30%); default: M
- Support configurable QR code size via --size flag (pixels for the output image, default: 300x300)
- Support configurable module (pixel block) size via --scale flag (default: 10 pixels per module)
- Support custom colors via --foreground and --background flags (hex color codes, default: black on white)
- Support multiple output formats via --format flag: PNG (default), SVG, and ASCII art (for terminal display)
- Support adding a logo/image overlay in the center of the QR code via --logo flag (relies on higher error correction to remain scannable)
- read: Accept an image file path and decode the QR code content from it
- read: Support decoding from various image formats (PNG, JPEG, BMP)
- read: Report decoded content, QR version, error correction level, and encoding mode
- Support batch generation from a file containing one content string per line via --batch flag
- Print results to console: for generation show the content encoded and output path, for reading show the decoded content
- Save decoded results as JSON with --output flag
- If no arguments are given, generate QR codes for several sample inputs (a URL, a plain text message, a vCard contact, and a Wi-Fi network config), save them as images, then read each one back and verify the decoded content matches the original
- Handle errors: content too long for QR capacity, unreadable QR codes, low-quality images, and invalid color values

Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include:
- Source code
- pom.xml with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>qr-tool</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>QR Code Generator and Reader</name>
    <description>
        Generates QR codes (PNG/SVG/ASCII) with error correction and decodes
        QR codes from images using ZXing.
    </description>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.5.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>qrtool.QrTool</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
README.md
# QR Code Generator and Reader (Java - Trial 1)

Generates QR codes in PNG, SVG, and ASCII formats with error correction and decodes QR codes from images.

## Dependencies

- **zxing-core** (3.5.3) - QR code encoding and decoding engine
- **zxing-javase** (3.5.3) - Java SE utilities for image-based QR code I/O

## Build and Run

```bash
mvn clean compile exec:java -Dexec.mainClass="qrtool.QrTool"
```

Or build a JAR:

```bash
mvn clean package
java -jar target/qr-tool-1.0.0.jar
```

## Features

- QR code generation in PNG, SVG, and ASCII output formats
- Configurable error correction levels (L, M, Q, H)
- QR code decoding from image files using ZXing
- Roundtrip encode/decode verification
- Command-line interface
src/main/java/qrtool/QrTool.java
package qrtool;

/**
 * QR Code Generator and Reader
 *
 * Generates QR codes in PNG, SVG, and ASCII formats with configurable error
 * correction levels. Decodes QR codes from image files.
 *
 * Dependencies:
 *     - com.google.zxing:core 3.5.3
 *     - com.google.zxing:javase 3.5.3
 */

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;

public class QrTool {

    // -----------------------------------------------------------------------
    // Error correction level mapping
    // -----------------------------------------------------------------------
    private static final Map<String, ErrorCorrectionLevel> EC_LEVELS = new HashMap<>();

    static {
        EC_LEVELS.put("L", ErrorCorrectionLevel.L);
        EC_LEVELS.put("M", ErrorCorrectionLevel.M);
        EC_LEVELS.put("Q", ErrorCorrectionLevel.Q);
        EC_LEVELS.put("H", ErrorCorrectionLevel.H);
    }

    // -----------------------------------------------------------------------
    // QR Code generation
    // -----------------------------------------------------------------------

    /**
     * Generate a BitMatrix for the given data and parameters.
     */
    private static BitMatrix createQrMatrix(String data, String ecLevel,
                                             int size) throws WriterException {
        ErrorCorrectionLevel level = EC_LEVELS.getOrDefault(
                ecLevel.toUpperCase(), ErrorCorrectionLevel.M);

        Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
        hints.put(EncodeHintType.ERROR_CORRECTION, level);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 4);

        QRCodeWriter writer = new QRCodeWriter();
        return writer.encode(data, BarcodeFormat.QR_CODE, size, size, hints);
    }

    /**
     * Generate a QR code and save it as a PNG image.
     *
     * @param data       The text/URL to encode
     * @param outputPath Destination file path
     * @param ecLevel    Error correction level (L, M, Q, H)
     * @param size       Image size in pixels
     * @param fgColor    Foreground color as ARGB int
     * @param bgColor    Background color as ARGB int
     * @return The absolute path to the saved file
     */
    public static String generatePng(String data, String outputPath,
                                      String ecLevel, int size,
                                      int fgColor, int bgColor)
            throws WriterException, IOException {

        BitMatrix matrix = createQrMatrix(data, ecLevel, size);
        MatrixToImageConfig config = new MatrixToImageConfig(fgColor, bgColor);
        Path path = FileSystems.getDefault().getPath(outputPath);
        MatrixToImageWriter.writeToPath(matrix, "PNG", path, config);
        return path.toAbsolutePath().toString();
    }

    /**
     * Generate a QR code and save it as an SVG image.
     *
     * @param data       The text/URL to encode
     * @param outputPath Destination file path
     * @param ecLevel    Error correction level
     * @param size       Logical size in SVG units
     * @return The absolute path to the saved file
     */
    public static String generateSvg(String data, String outputPath,
                                      String ecLevel, int size)
            throws WriterException, IOException {

        BitMatrix matrix = createQrMatrix(data, ecLevel, size);
        int width = matrix.getWidth();
        int height = matrix.getHeight();

        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append(String.format(
                "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 %d %d\">\n",
                width, height));
        sb.append(String.format(
                "  <rect width=\"%d\" height=\"%d\" fill=\"white\"/>\n",
                width, height));
        sb.append("  <path d=\"");

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (matrix.get(x, y)) {
                    sb.append(String.format("M%d,%dh1v1h-1z", x, y));
                }
            }
        }

        sb.append("\" fill=\"black\"/>\n");
        sb.append("</svg>\n");

        File outFile = new File(outputPath);
        try (FileWriter fw = new FileWriter(outFile)) {
            fw.write(sb.toString());
        }
        return outFile.getAbsolutePath();
    }

    /**
     * Generate an ASCII representation of a QR code.
     *
     * @param data    The text/URL to encode
     * @param ecLevel Error correction level
     * @param invert  If true, swap dark/light characters
     * @return Multi-line string of the ASCII QR code
     */
    public static String generateAscii(String data, String ecLevel,
                                        boolean invert)
            throws WriterException {

        BitMatrix matrix = createQrMatrix(data, ecLevel, 0);
        int width = matrix.getWidth();
        int height = matrix.getHeight();

        String darkChar = invert ? "  " : "\u2588\u2588";
        String lightChar = invert ? "\u2588\u2588" : "  ";

        StringBuilder sb = new StringBuilder();
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                sb.append(matrix.get(x, y) ? darkChar : lightChar);
            }
            if (y < height - 1) {
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    /**
     * Generate a QR code as a BufferedImage in memory.
     */
    public static BufferedImage generateImage(String data, String ecLevel,
                                               int size, int fgColor,
                                               int bgColor)
            throws WriterException {

        BitMatrix matrix = createQrMatrix(data, ecLevel, size);
        MatrixToImageConfig config = new MatrixToImageConfig(fgColor, bgColor);
        return MatrixToImageWriter.toBufferedImage(matrix, config);
    }

    // -----------------------------------------------------------------------
    // QR Code decoding
    // -----------------------------------------------------------------------

    /**
     * Decode QR code(s) from an image file.
     *
     * @param imagePath Path to the image file
     * @return List of decoded results
     */
    public static List<Map<String, Object>> decodeQr(String imagePath)
            throws IOException, NotFoundException {

        File imgFile = new File(imagePath);
        if (!imgFile.exists()) {
            throw new FileNotFoundException("Image not found: " + imagePath);
        }

        BufferedImage image = ImageIO.read(imgFile);
        return decodeFromImage(image);
    }

    /**
     * Decode QR code(s) from a BufferedImage.
     */
    public static List<Map<String, Object>> decodeFromImage(BufferedImage image)
            throws NotFoundException {

        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        List<Map<String, Object>> results = new ArrayList<>();

        // Try multi-decode first
        try {
            MultipleBarcodeReader multiReader = new GenericMultipleBarcodeReader(
                    new MultiFormatReader());
            Result[] multiResults = multiReader.decodeMultiple(bitmap);
            for (Result r : multiResults) {
                if (r.getBarcodeFormat() == BarcodeFormat.QR_CODE) {
                    results.add(resultToMap(r));
                }
            }
        } catch (NotFoundException e) {
            // Fall back to single decode
        }

        if (results.isEmpty()) {
            Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            hints.put(DecodeHintType.POSSIBLE_FORMATS,
                    Collections.singletonList(BarcodeFormat.QR_CODE));

            MultiFormatReader reader = new MultiFormatReader();
            Result result = reader.decode(bitmap, hints);
            results.add(resultToMap(result));
        }

        return results;
    }

    private static Map<String, Object> resultToMap(Result result) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("data", result.getText());
        map.put("format", result.getBarcodeFormat().name());

        ResultPoint[] points = result.getResultPoints();
        if (points != null) {
            List<Map<String, Float>> pointsList = new ArrayList<>();
            for (ResultPoint p : points) {
                Map<String, Float> point = new LinkedHashMap<>();
                point.put("x", p.getX());
                point.put("y", p.getY());
                pointsList.add(point);
            }
            map.put("points", pointsList);
        }
        return map;
    }

    // -----------------------------------------------------------------------
    // Roundtrip verification
    // -----------------------------------------------------------------------

    /**
     * Encode data into a QR code in-memory, decode it, and verify match.
     */
    public static boolean roundtrip(String data, String ecLevel) {
        try {
            BufferedImage image = generateImage(data, ecLevel, 400,
                    0xFF000000, 0xFFFFFFFF);

            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.POSSIBLE_FORMATS,
                    Collections.singletonList(BarcodeFormat.QR_CODE));

            MultiFormatReader reader = new MultiFormatReader();
            Result result = reader.decode(bitmap, hints);

            return data.equals(result.getText());
        } catch (Exception e) {
            System.err.println("Roundtrip error: " + e.getMessage());
            return false;
        }
    }

    // -----------------------------------------------------------------------
    // CLI
    // -----------------------------------------------------------------------

    private static void printUsage() {
        System.out.println("QR Code Generator and Reader (ZXing)");
        System.out.println();
        System.out.println("Usage:");
        System.out.println("  java qrtool.QrTool generate <data> [options]");
        System.out.println("  java qrtool.QrTool decode <image>");
        System.out.println("  java qrtool.QrTool roundtrip <data> [options]");
        System.out.println();
        System.out.println("Generate options:");
        System.out.println("  -o, --output <path>    Output file (default: qrcode.png)");
        System.out.println("  -f, --format <fmt>     png, svg, or ascii (default: png)");
        System.out.println("  -e, --ec-level <lvl>   L, M, Q, or H (default: M)");
        System.out.println("  -s, --size <pixels>    Image size (default: 400)");
        System.out.println("  --invert               Invert ASCII colours");
    }

    public static void main(String[] args) {
        if (args.length < 1) {
            printUsage();
            return;
        }

        String command = args[0];

        switch (command) {
            case "generate":
                handleGenerate(args);
                break;
            case "decode":
                handleDecode(args);
                break;
            case "roundtrip":
                handleRoundtrip(args);
                break;
            case "-h":
            case "--help":
                printUsage();
                break;
            default:
                System.err.println("Unknown command: " + command);
                printUsage();
                System.exit(1);
        }
    }

    private static void handleGenerate(String[] args) {
        if (args.length < 2) {
            System.err.println("Error: data argument required");
            System.exit(1);
        }

        String data = args[1];
        String output = "qrcode.png";
        String format = "png";
        String ecLevel = "M";
        int size = 400;
        boolean invert = false;

        for (int i = 2; i < args.length; i++) {
            switch (args[i]) {
                case "-o": case "--output":
                    if (i + 1 < args.length) output = args[++i];
                    break;
                case "-f": case "--format":
                    if (i + 1 < args.length) format = args[++i];
                    break;
                case "-e": case "--ec-level":
                    if (i + 1 < args.length) ecLevel = args[++i];
                    break;
                case "-s": case "--size":
                    if (i + 1 < args.length) size = Integer.parseInt(args[++i]);
                    break;
                case "--invert":
                    invert = true;
                    break;
            }
        }

        try {
            switch (format.toLowerCase()) {
                case "ascii":
                    System.out.println(generateAscii(data, ecLevel, invert));
                    break;
                case "svg":
                    String svgPath = generateSvg(data, output, ecLevel, size);
                    System.out.println("SVG QR code saved to " + svgPath);
                    break;
                default:
                    String pngPath = generatePng(data, output, ecLevel, size,
                            0xFF000000, 0xFFFFFFFF);
                    System.out.println("PNG QR code saved to " + pngPath);
                    break;
            }
        } catch (Exception e) {
            System.err.println("Generation error: " + e.getMessage());
            System.exit(1);
        }
    }

    private static void handleDecode(String[] args) {
        if (args.length < 2) {
            System.err.println("Error: image path required");
            System.exit(1);
        }

        try {
            List<Map<String, Object>> results = decodeQr(args[1]);
            if (results.isEmpty()) {
                System.out.println("No QR codes found in the image.");
                System.exit(1);
            }
            for (int i = 0; i < results.size(); i++) {
                Map<String, Object> r = results.get(i);
                System.out.printf("QR #%d:%n", i + 1);
                System.out.printf("  Data: %s%n", r.get("data"));
                System.out.printf("  Format: %s%n", r.get("format"));
                System.out.printf("  Points: %s%n", r.get("points"));
            }
        } catch (Exception e) {
            System.err.println("Decode error: " + e.getMessage());
            System.exit(1);
        }
    }

    private static void handleRoundtrip(String[] args) {
        if (args.length < 2) {
            System.err.println("Error: data argument required");
            System.exit(1);
        }

        String data = args[1];
        String ecLevel = "M";

        for (int i = 2; i < args.length; i++) {
            if ("-e".equals(args[i]) || "--ec-level".equals(args[i])) {
                if (i + 1 < args.length) ecLevel = args[++i];
            }
        }

        boolean ok = roundtrip(data, ecLevel);
        if (ok) {
            System.out.println("Roundtrip successful: decoded data matches original.");
        } else {
            System.out.println("Roundtrip FAILED: decoded data does not match.");
            System.exit(1);
        }
    }
}