当前位置: 首页 > article >正文

基于DeepSeek实现PDF嵌入SVG图片无损放大

1. PDF中效果图

在这里插入图片描述

2. 询问Deepseek进行代码书写,不断优化后结果

/**
 * SVG工具类,用于生成价格趋势的SVG图表
 */
public class SvgUtils {

    // SVG画布尺寸
    private static final int WIDTH = 800;
    private static final int HEIGHT = 500;
    private static final int PADDING = 60;

    // 生成SVG折线图
    public static String generatePriceTrendSvg(List<PriceData> data, String title, String subtitle) {
        if (data.isEmpty()) {
            return "<svg xmlns='http://www.w3.org/2000/svg' width='" + WIDTH + "' height='" + HEIGHT + "'></svg>";
        }

        // 计算价格和时间的范围
        double minPrice = data.stream().mapToDouble(PriceData::getPrice).min().orElse(0) * 0.8;
        double maxPrice = data.stream().mapToDouble(PriceData::getPrice).max().orElse(1) * 1.2;

        // 解析最小和最大日期
        String minYearMonth = data.stream().map(PriceData::getYearmonth).min(String::compareTo).orElse("2024-06");
        String maxYearMonth = data.stream().map(PriceData::getYearmonth).max(String::compareTo).orElse("2025-01");

        // 构建SVG内容
        StringBuilder svg = new StringBuilder();
        svg.append(String.format("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>", WIDTH, HEIGHT));

        // 画背景
        svg.append(String.format("<rect width='%d' height='%d' fill='#ffffff'/>", WIDTH, HEIGHT));

        // 添加标题和副标题(居中显示)
        svg.append(String.format("<text x='%d' y='%d' font-size='20' font-family='Arial' fill='#333333' font-weight='bold' text-anchor='middle'>%s</text>",
                WIDTH / 2, 30, title));
        svg.append(String.format("<text x='%d' y='%d' font-size='14' font-family='Arial' fill='#666666' text-anchor='middle'>%s</text>",
                WIDTH / 2, 50, subtitle));

        // 画虚线网格线
        svg.append(drawGrid(minYearMonth, maxYearMonth, minPrice, maxPrice));

        // 画深色坐标轴
        svg.append(drawAxis(minYearMonth, maxYearMonth, minPrice, maxPrice));

        // 画浅色平滑折线
        svg.append(drawSmoothLine(data, minYearMonth, maxYearMonth, minPrice, maxPrice));

        svg.append("</svg>");
        return svg.toString();
    }

    // 画虚线网格线
    private static String drawGrid(String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        StringBuilder grid = new StringBuilder();

        // 水平网格线(价格)
        int numHorizontalLines = 5;
        for (int i = 0; i <= numHorizontalLines; i++) {
            double price = minPrice + (maxPrice - minPrice) * i / numHorizontalLines;
            int y = HEIGHT - PADDING - (int) ((price - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
            grid.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#e0e0e0' stroke-width='1' stroke-dasharray='5,5'/>",
                    PADDING, y, WIDTH - PADDING, y));
        }

        // 垂直网格线(时间)
        List<String> yearMonths = generateYearMonths(minYearMonth, maxYearMonth);
        for (String yearMonth : yearMonths) {
            int x = PADDING + (int) ((getMonthIndex(yearMonth) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (yearMonths.size() - 1));
            grid.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#e0e0e0' stroke-width='1' stroke-dasharray='5,5'/>",
                    x, PADDING, x, HEIGHT - PADDING));
        }

        return grid.toString();
    }

    // 画深色坐标轴
    private static String drawAxis(String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        StringBuilder axis = new StringBuilder();

        // X轴(时间)
        axis.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#333333' stroke-width='2'/>",
                PADDING, HEIGHT - PADDING, WIDTH - PADDING, HEIGHT - PADDING));

        // Y轴(价格)
        axis.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#333333' stroke-width='2'/>",
                PADDING, PADDING, PADDING, HEIGHT - PADDING));

        // X轴标签
        List<String> yearMonths = generateYearMonths(minYearMonth, maxYearMonth);
        for (String yearMonth : yearMonths) {
            int x = PADDING + (int) ((getMonthIndex(yearMonth) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (yearMonths.size() - 1));
            axis.append(String.format("<text x='%d' y='%d' font-size='12' font-family='Arial' fill='#000000' text-anchor='middle'>%s</text>",
                    x, HEIGHT - PADDING + 20, yearMonth));
        }

        // Y轴标签
        int numYLabels = 5;
        for (int i = 0; i <= numYLabels; i++) {
            double price = minPrice + (maxPrice - minPrice) * i / numYLabels;
            int y = HEIGHT - PADDING - (int) ((price - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
            axis.append(String.format("<text x='%d' y='%d' font-size='12' font-family='Arial' fill='#000000' text-anchor='end'>%.2f</text>",
                    PADDING - 10, y + 5, price));
        }

        return axis.toString();
    }

    // 画浅色平滑折线
    private static String drawSmoothLine(List<PriceData> data, String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        if (data.size() < 2) {
            return "";
        }

        StringBuilder path = new StringBuilder("<path d='M");

        for (int i = 0; i < data.size(); i++) {
            PriceData point = data.get(i);
            int x = PADDING + (int) ((getMonthIndex(point.getYearmonth()) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (getMonthIndex(maxYearMonth) - getMonthIndex(minYearMonth)));
            int y = HEIGHT - PADDING - (int) ((point.getPrice() - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));

            if (i == 0) {
                path.append(x).append(",").append(y);
            } else {
                // 计算控制点以实现平滑效果
                PriceData prevPoint = data.get(i - 1);
                int prevX = PADDING + (int) ((getMonthIndex(prevPoint.getYearmonth()) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (getMonthIndex(maxYearMonth) - getMonthIndex(minYearMonth)));
                int prevY = HEIGHT - PADDING - (int) ((prevPoint.getPrice() - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
                int ctrlX1 = (prevX + x) / 2;
                int ctrlY1 = prevY;
                int ctrlX2 = (prevX + x) / 2;
                int ctrlY2 = y;

                path.append(" C").append(ctrlX1).append(",").append(ctrlY1)
                        .append(" ").append(ctrlX2).append(",").append(ctrlY2)
                        .append(" ").append(x).append(",").append(y);
            }
        }

        path.append("' fill='none' stroke='#66B3FF' stroke-width='2'/>");
        return path.toString();
    }

    // 生成从 minYearMonth 到 maxYearMonth 的连续月份列表
    private static List<String> generateYearMonths(String minYearMonth, String maxYearMonth) {
        List<String> yearMonths = new ArrayList<>();
        int year = Integer.parseInt(minYearMonth.substring(0, 4));
        int month = Integer.parseInt(minYearMonth.substring(5));

        while (true) {
            yearMonths.add(String.format("%04d-%02d", year, month));
            if (yearMonths.get(yearMonths.size() - 1).equals(maxYearMonth)) {
                break;
            }
            month++;
            if (month > 12) {
                month = 1;
                year++;
            }
        }

        return yearMonths;
    }

    // 将 yearmonth 转换为索引(从 0 开始)
    private static int getMonthIndex(String yearMonth) {
        int year = Integer.parseInt(yearMonth.substring(0, 4));
        int month = Integer.parseInt(yearMonth.substring(5));
        return (year - 2024) * 12 + (month - 1); // 假设最小年份是 2024
    }

    public static void main(String[] args) {
        List<PriceData> data = PriceData.getSampleData();
        String title = "价格走势图";
        String subtitle = "2024-06 至 2025-01";
        String svg = SvgUtils.generatePriceTrendSvg(data, title, subtitle);
        System.out.println(svg);
    }
}
@Data
public class PriceData {
    private String yearmonth;
    private Double price;

    public PriceData() {}

    public PriceData(String yearmonth, Double price) {
        this.yearmonth = yearmonth;
        this.price = price;
    }

    public static List<PriceData> getSampleData() {
        List<PriceData> data = new ArrayList<>();
        data.add(new PriceData("2025-01", 100.0)); // 2023-01-01
        data.add(new PriceData("2025-02", 105.0)); // 2023-01-02
        data.add(new PriceData("2025-03", 102.0)); // 2023-01-03
        data.add(new PriceData("2025-04", 110.0)); // 2023-01-04
        data.add(new PriceData("2025-05", 108.0)); // 2023-01-05
        return data;
    }
}

OK, 生成的SVG嵌入到html网页中进行渲染即可


http://www.kler.cn/a/576873.html

相关文章:

  • 扫雷雷雷雷雷雷雷
  • 蓝桥杯P19718-回文字符串 题解
  • GET3D:从图像中学习的高质量3D纹理形状的生成模型
  • Bolt AI 技术浅析(五):实时编辑
  • C++20 DR11:数组 `new` 可以推导出数组大小
  • 常见的 Git 命令
  • Python 远程抓取服务器日志最后 1000行
  • c# 2025/3/8 周六
  • 网络运维学习笔记(DeepSeek优化版) 013网工初级(HCIA-Datacom与CCNA-EI)ACL访问控制列表
  • JAVA Spring Boot @Bean 注解的使用和注意事项
  • 【每日学点HarmonyOS Next知识】Tab切换声明周期、复杂Json组装、scroll最大高度、引用传递报错、Web性能
  • saltstack通过master下发脚本批量修改minion_id,修改为IP
  • 递归专题刷题
  • 大模型工程师学习日记(十五):Hugging Face 模型微调训练(基于 BERT 的中文评价情感分析)
  • Python写一个查星座的小程序,适合初学者练手——字典和if语句练习
  • ARMV8的64位指令
  • cdn取消接口缓存
  • Redis 各数据类型使用场景详解
  • Scaling Laws for Neural Language Models
  • DIY Tomcat:手写一个简易Servlet容器