iText区域标注测量字典创建:移动标注后面积值异常排查
Let's break down what's happening here in plain terms:
The Core Problem
When you first add the annotation, you hardcode the display text to "15.2 sq cm", so the PDF reader shows that exact value. But as soon as you move the annotation, the reader kicks into automatic mode—it recalculates the area using the rules in your Measure dictionary, and that's where the error creeps in.
Where Your Code Goes Wrong
Looking at your createMeasureDictionary method, the mistake is in the area number format dictionary (the A entry):
aDictionary.put(PdfName.C, new PdfNumber(1));
The C value here is the conversion factor that turns PDF user-space area into your real-world unit (sq cm). You already calculated that 5433 (PDF space area) × 0.00280691 ≈ 15.2 (correct real-world area), but you set C=1 instead of using your actual pdfCalibrationValue.
Here's why that causes the 0.04 result:
The reader assumes your length conversion factor (from the X dictionary) applies to area too (since area is 2D). It takes the PDF space area (~5433) and multiplies it by the length conversion factor squared: 5433 × (0.00280691)² ≈ 0.04. Since your area C factor was set to 1, it doesn't adjust this incorrect value.
Fixing the Code
You need to align your Measure dictionary with how you're calculating the area. Since you already have a direct area conversion factor (pdfCalibrationValue = 15.2 / 5433), set that as the C value in your area dictionary. We'll also clean up the length ratio for good practice:
private static PdfDictionary createMeasureDictionary(float pdfCalibrationValue) { String unit = "cm"; PdfDictionary measureDictionary = new PdfDictionary(); measureDictionary.put(PdfName.TYPE, PdfName.MEASURE); // Correct ratio to reflect real-world ↔ PDF units (optional but keeps things consistent) float lengthCalib = (float) Math.sqrt(pdfCalibrationValue); // ~0.05298 cm per PDF unit float pdfUnitsPerCm = 1 / lengthCalib; // ~18.875 PDF units per cm measureDictionary.put(PdfName.R, new PdfString("1 " + unit + " = " + pdfUnitsPerCm + " user units")); // Length format (for length measurements, if needed) PdfDictionary xDictionary = new PdfDictionary(); xDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT); xDictionary.put(PdfName.U, new PdfString(unit)); xDictionary.put(PdfName.C, new PdfNumber(lengthCalib)); // 1 PDF unit = lengthCalib cm PdfArray xarr = new PdfArray(); xarr.add(xDictionary); measureDictionary.put(PdfName.X, xarr); // Area format: use your pre-calculated area conversion factor PdfDictionary aDictionary = new PdfDictionary(); aDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT); aDictionary.put(PdfName.U, new PdfString("sq " + unit)); aDictionary.put(PdfName.C, new PdfNumber(pdfCalibrationValue)); // 1 PDF sq unit = pdfCalibrationValue sq cm PdfArray aarr = new PdfArray(); aarr.add(aDictionary); measureDictionary.put(PdfName.A, aarr); // Dimension format (keep as is) PdfDictionary dDictionary = new PdfDictionary(); dDictionary.put(PdfName.TYPE, PdfName.NUMBERFORMAT); dDictionary.put(PdfName.U, new PdfString(unit)); dDictionary.put(PdfName.C, new PdfNumber(1)); PdfArray darr = new PdfArray(); darr.add(dDictionary); measureDictionary.put(PdfName.D, darr); return measureDictionary; }
Key Takeaways
- Hardcoding the annotation text works initially, but moving triggers automatic recalculation using the
Measuredictionary. - The
Cvalue in theA(area) dictionary must match your direct area conversion factor (PDF sq unit → real-world sq unit). - If you include length measurements, the length conversion factor should be the square root of your area factor (since area is length squared).
Now when you move the annotation, the reader will recalculate the area correctly and show ~15.2 sq cm (assuming you only moved the polygon, not scaled it).
内容的提问来源于stack exchange,提问作者chitgoks

