From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- scanin/CMP_DT_003.cht | 336 +++ scanin/CMP_Digital_Target-3.cht | 1210 ++++++++++ scanin/CMP_Digital_Target-3.cie | 591 +++++ scanin/CMP_Digital_Target-3.ti2 | 601 +++++ scanin/ColorChecker.cht | 59 + scanin/ColorChecker.cie | 39 + scanin/ColorCheckerDC.cht | 318 +++ scanin/ColorCheckerPassport.cht | 122 + scanin/ColorCheckerPassport.cie | 64 + scanin/ColorCheckerSG.cht | 203 ++ scanin/Hutchcolor.cht | 597 +++++ scanin/Jamfile | 33 + scanin/LaserSoftDCPro.cht | 202 ++ scanin/License.txt | 662 ++++++ scanin/Makefile.am | 19 + scanin/QPcard_201.cht | 76 + scanin/QPcard_201.cie | 42 + scanin/QPcard_202.cht | 80 + scanin/QPcard_202.cie | 48 + scanin/Readme.txt | 8 + scanin/SpyderChecker.cht | 115 + scanin/SpyderChecker.cie | 62 + scanin/afiles | 28 + scanin/i1_RGB_Scan_1.4.cht | 341 +++ scanin/it8.cht | 338 +++ scanin/scanin.c | 1436 ++++++++++++ scanin/scanrd.c | 4659 +++++++++++++++++++++++++++++++++++++++ scanin/scanrd.h | 125 ++ scanin/scanrd_.h | 321 +++ 29 files changed, 12735 insertions(+) create mode 100644 scanin/CMP_DT_003.cht create mode 100644 scanin/CMP_Digital_Target-3.cht create mode 100644 scanin/CMP_Digital_Target-3.cie create mode 100644 scanin/CMP_Digital_Target-3.ti2 create mode 100644 scanin/ColorChecker.cht create mode 100644 scanin/ColorChecker.cie create mode 100644 scanin/ColorCheckerDC.cht create mode 100644 scanin/ColorCheckerPassport.cht create mode 100644 scanin/ColorCheckerPassport.cie create mode 100644 scanin/ColorCheckerSG.cht create mode 100644 scanin/Hutchcolor.cht create mode 100644 scanin/Jamfile create mode 100644 scanin/LaserSoftDCPro.cht create mode 100644 scanin/License.txt create mode 100644 scanin/Makefile.am create mode 100644 scanin/QPcard_201.cht create mode 100644 scanin/QPcard_201.cie create mode 100644 scanin/QPcard_202.cht create mode 100644 scanin/QPcard_202.cie create mode 100644 scanin/Readme.txt create mode 100644 scanin/SpyderChecker.cht create mode 100644 scanin/SpyderChecker.cie create mode 100644 scanin/afiles create mode 100644 scanin/i1_RGB_Scan_1.4.cht create mode 100644 scanin/it8.cht create mode 100644 scanin/scanin.c create mode 100644 scanin/scanrd.c create mode 100644 scanin/scanrd.h create mode 100644 scanin/scanrd_.h (limited to 'scanin') diff --git a/scanin/CMP_DT_003.cht b/scanin/CMP_DT_003.cht new file mode 100644 index 0000000..37411af --- /dev/null +++ b/scanin/CMP_DT_003.cht @@ -0,0 +1,336 @@ + +BOXES 286 + F _ _ 22 14 522 14 522 402 22 402 + D ALL ALL _ _ 500 388 22 14 0 0 + X A S 1 15 24.21052632 22.4 44.5 43.5 24.21052632 22.4 + +BOX_SHRINK 3.0 + +REF_ROTATION 0.0 + +XLIST 20 + 44.500000 1.0 1.0 + 68.710526 1.0 1.0 + 92.921053 1.0 1.0 + 117.131579 1.0 1.0 + 141.342105 1.0 1.0 + 165.552632 1.0 1.0 + 189.763158 1.0 1.0 + 213.973684 1.0 1.0 + 238.184211 1.0 1.0 + 262.394737 1.0 1.0 + 286.605263 1.0 1.0 + 310.815790 1.0 1.0 + 335.026316 1.0 1.0 + 359.236842 1.0 1.0 + 383.447368 1.0 1.0 + 407.657895 1.0 1.0 + 431.868421 1.0 1.0 + 456.078947 1.0 1.0 + 480.289474 1.0 1.0 + 504.500000 1.0 1.0 + +YLIST 16 + 43.5000000 1.0 1.0 + 65.9000000 1.0 1.0 + 88.3000000 1.0 1.0 + 110.7000000 1.0 1.0 + 133.1000000 1.0 1.0 + 155.5000000 1.0 1.0 + 177.9000000 1.0 1.0 + 200.3000000 1.0 1.0 + 222.7000000 1.0 1.0 + 245.1000000 1.0 1.0 + 267.5000000 1.0 1.0 + 289.9000000 1.0 1.0 + 312.3000000 1.0 1.0 + 334.7000000 1.0 1.0 + 357.1000000 1.0 1.0 + 379.5000000 1.0 1.0 + +EXPECTED XYZ 285 + A1 9.46 8.62 29.26 + A2 75.93 84.68 17.08 + A3 44.11 49.20 9.06 + A4 74.02 82.54 15.47 + A5 37.88 42.42 7.93 + A6 70.26 78.24 13.90 + A7 33.59 37.74 7.04 + A8 64.25 71.82 12.27 + A9 30.32 34.10 6.32 + A10 57.13 63.83 11.22 + A11 26.62 30.10 5.61 + A12 51.96 58.23 10.31 + A13 24.04 26.72 5.25 + A14 47.16 52.59 9.77 + A15 37.64 22.85 4.57 + B1 8.18 6.87 23.20 + B2 3.61 3.38 6.33 + B3 20.88 23.43 4.87 + B4 6.33 6.95 2.79 + B5 16.96 19.17 4.20 + B6 5.33 5.76 2.62 + B7 13.34 14.75 3.69 + B8 4.19 4.42 2.51 + B9 11.50 12.44 3.41 + B10 3.35 3.48 2.29 + B11 9.89 10.67 3.24 + B12 2.58 2.69 2.00 + B13 8.23 9.01 3.11 + B14 6.56 5.16 3.23 + B15 24.38 14.64 3.70 + C1 68.17 69.38 68.07 + C2 36.78 42.46 59.62 + C3 75.58 84.30 16.75 + C4 75.91 84.25 23.05 + C5 74.70 83.33 16.21 + C6 75.40 83.27 27.19 + C7 72.95 81.42 15.76 + C8 76.66 83.97 33.57 + C9 71.33 79.64 15.34 + C10 76.21 82.14 39.39 + C11 70.81 79.26 15.13 + C12 78.61 84.06 47.87 + C13 73.95 82.35 17.71 + C14 60.78 52.94 41.53 + C15 36.37 21.94 4.40 + D1 7.77 6.43 21.76 + D2 3.42 3.25 4.79 + D3 10.85 14.71 3.95 + D4 45.74 31.43 7.66 + D5 64.97 58.40 40.57 + D6 19.20 20.77 4.47 + D7 75.67 77.88 68.77 + D8 46.56 58.50 11.12 + D9 63.18 64.06 65.19 + D10 81.64 85.77 61.30 + D11 65.37 58.65 46.40 + D12 61.29 55.60 29.97 + D13 39.33 30.42 13.58 + D14 5.41 4.44 3.00 + D15 21.48 13.05 3.51 + E1 51.91 51.52 63.01 + E2 33.50 39.48 59.55 + E3 19.80 26.35 5.19 + E4 40.01 32.11 15.48 + E5 37.52 50.89 23.01 + E6 12.96 19.59 4.87 + E7 40.98 31.63 14.39 + E8 82.08 84.89 69.04 + E9 42.04 30.96 10.93 + E10 22.65 16.11 3.94 + E11 16.97 31.21 9.80 + E12 17.85 13.86 4.54 + E13 37.65 30.47 11.22 + E14 59.56 52.44 35.78 + E15 37.21 22.38 4.99 + F1 7.29 5.92 19.97 + F2 2.90 2.84 3.47 + F3 23.09 24.88 26.94 + F4 12.29 23.07 7.35 + F5 3.78 3.96 3.02 + F6 35.90 39.27 26.05 + F7 31.18 36.48 44.00 + F8 14.33 10.91 3.47 + F9 51.06 46.54 12.01 + F10 62.15 71.68 13.67 + F11 45.60 30.43 40.49 + F12 27.89 15.62 6.31 + F13 39.47 27.31 5.08 + F14 4.49 3.88 2.77 + F15 19.73 12.17 3.49 + G1 40.25 39.39 58.62 + G2 19.66 22.70 47.78 + G3 14.05 21.04 21.63 + G4 25.20 38.40 38.99 + G5 2.23 2.29 1.82 + G6 32.34 44.38 25.97 + G7 39.08 40.35 45.16 + G8 21.91 25.22 7.66 + G9 51.20 40.45 19.47 + G10 53.69 54.84 12.82 + G11 43.69 29.70 5.63 + G12 14.51 14.92 41.81 + G13 48.91 38.08 7.33 + G14 57.75 51.93 23.98 + G15 40.27 24.75 7.03 + H1 6.40 5.14 17.21 + H2 2.50 2.51 2.41 + H3 29.45 31.10 6.27 + H4 8.45 13.05 6.25 + H5 86.92 89.85 72.02 + H6 55.25 57.23 44.58 + H7 61.04 63.45 50.22 + H8 66.13 68.64 54.49 + H9 72.30 74.84 59.86 + H10 77.76 80.54 64.40 + H11 51.45 33.36 33.30 + H12 34.29 19.71 5.84 + H13 58.12 53.49 9.49 + H14 3.19 3.01 2.34 + H15 17.14 10.82 3.44 + I1 28.84 27.18 51.31 + I2 26.22 30.11 55.57 + I3 8.61 12.78 13.10 + I4 33.19 47.31 44.96 + I5 2.15 2.20 1.76 + I6 49.64 51.25 39.42 + I7 5.60 5.83 4.56 + I8 7.15 7.43 5.74 + I9 8.78 9.28 7.44 + I10 10.72 11.21 8.69 + I11 40.19 25.72 5.17 + I12 24.06 30.11 17.13 + I13 37.28 22.42 4.86 + I14 55.52 50.69 14.17 + I15 43.35 28.37 10.26 + J1 5.89 4.70 15.90 + J2 2.28 2.31 1.96 + J3 27.11 24.41 4.88 + J4 7.74 9.84 6.03 + J5 89.34 92.52 73.92 + J6 43.85 45.42 35.57 + J7 4.30 4.50 3.43 + J8 2.15 2.19 1.76 + J9 2.09 2.14 1.72 + J10 13.73 14.17 11.04 + J11 48.54 31.76 20.77 + J12 32.08 17.94 10.34 + J13 40.10 26.64 5.08 + J14 2.38 2.39 1.88 + J15 14.87 9.67 3.40 + K1 20.70 19.17 45.35 + K2 50.77 57.51 66.01 + K3 5.13 6.59 5.77 + K4 39.68 52.97 51.16 + K5 2.10 2.15 1.70 + K6 38.94 40.21 31.90 + K7 3.21 3.34 2.69 + K8 2.41 2.47 1.98 + K9 2.13 2.17 1.74 + K10 15.60 16.15 12.73 + K11 33.32 21.81 4.35 + K12 27.52 31.82 32.36 + K13 56.60 50.73 8.89 + K14 45.02 29.35 9.98 + K15 33.62 20.13 4.15 + L1 5.46 4.40 14.88 + L2 2.11 2.16 1.70 + L3 25.77 20.56 4.52 + L4 7.71 9.80 5.98 + L5 84.08 86.79 69.98 + L6 33.50 34.70 27.85 + L7 29.61 30.66 23.86 + L8 24.73 25.62 19.83 + L9 21.29 22.01 17.44 + L10 18.36 19.06 15.25 + L11 46.52 30.74 11.47 + L12 24.42 16.78 15.94 + L13 52.38 41.58 7.87 + L14 2.21 2.25 1.78 + L15 13.22 8.72 3.42 + M1 14.98 13.99 39.67 + M2 11.85 13.25 28.34 + M3 12.36 12.97 3.50 + M4 61.64 70.63 61.46 + M5 2.71 2.82 2.20 + M6 19.68 32.16 26.16 + M7 22.82 21.24 9.05 + M8 18.52 24.40 39.35 + M9 12.91 11.12 3.85 + M10 30.16 32.59 40.27 + M11 19.93 15.24 35.28 + M12 23.31 32.50 35.69 + M13 40.57 29.47 5.44 + M14 48.37 32.78 13.33 + M15 33.33 19.90 4.09 + N1 4.94 4.06 12.92 + N2 2.11 2.17 1.71 + N3 24.26 17.39 4.08 + N4 7.07 6.36 6.03 + N5 4.99 5.20 4.01 + N6 16.13 29.37 14.18 + N7 26.00 22.77 21.27 + N8 19.90 28.01 35.06 + N9 13.59 11.19 8.53 + N10 25.06 17.40 4.36 + N11 45.92 30.60 7.35 + N12 23.35 22.39 17.67 + N13 32.06 32.06 6.36 + N14 2.19 2.22 1.79 + N15 11.33 7.77 3.42 + O1 10.02 9.28 31.17 + O2 10.76 11.90 24.53 + O3 42.31 54.55 53.67 + O4 19.88 26.90 37.20 + O5 13.56 15.96 37.55 + O6 4.92 5.13 7.76 + O7 5.99 4.89 16.71 + O8 86.01 88.32 70.07 + O9 41.28 54.49 46.60 + O10 54.51 66.41 49.82 + O11 6.39 4.76 7.70 + O12 7.47 7.24 24.02 + O13 10.20 9.57 23.31 + O14 53.00 38.17 18.52 + O15 32.29 19.09 3.94 + P1 4.39 3.79 10.44 + P2 23.77 36.35 37.44 + P3 9.32 10.17 16.69 + P4 21.20 34.66 29.30 + P5 13.42 11.68 33.90 + P6 85.83 89.93 70.83 + P7 10.92 10.20 33.11 + P8 68.39 77.72 54.98 + P9 74.31 69.95 50.96 + P10 76.65 83.76 61.45 + P11 22.36 24.83 36.36 + P12 53.63 58.46 57.53 + P13 5.08 4.20 5.62 + P14 56.95 44.27 24.67 + P15 9.35 6.75 3.46 + Q1 8.80 8.07 28.22 + Q2 23.52 36.04 37.29 + Q3 20.50 35.70 11.97 + Q4 30.51 46.22 20.80 + Q5 20.45 35.69 11.99 + Q6 36.10 51.62 25.45 + Q7 20.44 35.71 12.27 + Q8 41.63 56.54 30.57 + Q9 21.38 36.76 13.48 + Q10 51.17 64.25 39.66 + Q11 23.24 38.80 15.22 + Q12 62.32 72.88 49.66 + Q13 26.49 42.23 17.36 + Q14 60.98 51.36 33.35 + Q15 29.32 17.44 3.82 + R1 3.95 3.59 8.36 + R2 20.13 30.86 31.56 + R3 10.16 18.47 6.04 + R4 4.78 6.56 3.40 + R5 9.21 15.96 5.65 + R6 4.38 5.64 3.17 + R7 8.46 14.35 5.50 + R8 3.97 4.84 3.01 + R9 7.21 11.73 4.98 + R10 3.21 3.65 2.53 + R11 6.23 9.66 4.43 + R12 2.54 2.69 2.07 + R13 5.50 7.95 3.98 + R14 65.19 58.07 40.38 + R15 7.60 5.78 3.43 + S1 8.92 8.17 28.21 + S2 20.24 35.38 11.78 + S3 17.56 32.25 10.31 + S4 19.54 34.67 11.34 + S5 17.29 31.99 10.02 + S6 18.80 33.75 11.17 + S7 16.23 30.73 9.38 + S8 16.69 31.26 9.79 + S9 14.30 27.57 7.99 + S10 19.72 34.91 12.50 + S11 12.91 24.49 7.31 + S12 26.55 41.95 17.28 + S13 11.56 21.36 6.62 + S14 33.15 44.32 24.54 + S15 26.38 15.91 3.70 diff --git a/scanin/CMP_Digital_Target-3.cht b/scanin/CMP_Digital_Target-3.cht new file mode 100644 index 0000000..eb95ed8 --- /dev/null +++ b/scanin/CMP_Digital_Target-3.cht @@ -0,0 +1,1210 @@ + +BOXES 571 + F _ _ 100 200 3100 200 3100 2100 100 2100 + D ALL ALL _ _ 3200 200 0 0 0 0 + X A Z 1 19 100 100 100 200 100 100 + X 2A 2D 1 19 100 100 2700 200 100 100 + +BOX_SHRINK 12 + +REF_ROTATION 0.0 + +XLIST 31 + 100 1 1 + 200 1 1 + 300 1 1 + 400 1 1 + 500 1 1 + 600 1 1 + 700 1 1 + 800 1 1 + 900 1 1 + 1000 1 1 + 1100 1 1 + 1200 1 1 + 1300 1 1 + 1400 1 1 + 1500 1 1 + 1600 1 1 + 1700 1 1 + 1800 1 1 + 1900 1 1 + 2000 1 1 + 2100 1 1 + 2200 1 1 + 2300 1 1 + 2400 1 1 + 2500 1 1 + 2600 1 1 + 2700 1 1 + 2800 1 1 + 2900 1 1 + 3000 1 1 + 3100 1 1 + +YLIST 21 + 200 1 1 + 300 1 1 + 400 1 1 + 500 1 1 + 600 1 1 + 700 1 1 + 800 1 1 + 900 1 1 + 1000 1 1 + 1100 1 1 + 1200 1 1 + 1300 1 1 + 1400 1 1 + 1500 1 1 + 1500 1 1 + 1600 1 1 + 1700 1 1 + 1800 1 1 + 1900 1 1 + 2000 1 1 + 2100 1 1 + +EXPECTED XYZ 570 +A1 19.991 14.120 27.886 +B1 19.926 34.054 14.005 +C1 6.2319 5.6339 19.078 +D1 32.785 35.198 16.672 +E1 38.996 22.658 25.805 +F1 16.011 17.612 14.561 +G1 39.496 24.997 12.003 +H1 7.4905 6.2468 18.358 +I1 11.987 23.286 6.5928 +J1 16.591 12.444 27.331 +K1 63.038 64.179 58.403 +L1 4.3513 3.8393 2.7750 +M1 27.386 30.873 42.527 +N1 31.789 44.281 40.439 +O1 59.453 61.985 40.335 +P1 26.783 15.713 3.5833 +Q1 3.0238 3.6843 3.0876 +R1 15.462 28.885 12.776 +S1 23.694 16.421 29.352 +T1 65.900 73.381 11.377 +U1 8.3333 15.036 13.749 +V1 72.416 77.985 33.423 +W1 16.393 25.254 38.122 +X1 2.3144 2.3581 1.9303 +Y1 27.102 23.276 16.813 +Z1 2.6994 2.8850 2.2332 +2A1 10.757 20.588 4.8216 +2B1 40.765 45.919 58.857 +2C1 22.864 16.381 33.839 +2D1 28.289 21.404 20.483 +A2 10.412 10.567 30.978 +B2 24.139 14.085 3.5857 +C2 19.473 21.752 38.376 +D2 26.280 16.991 28.035 +E2 42.573 39.671 9.6556 +F2 17.113 18.705 43.690 +G2 35.850 22.548 3.8554 +H2 13.037 10.392 26.425 +I2 14.946 28.262 8.1825 +J2 3.1780 3.3914 2.3047 +K2 35.880 35.178 26.683 +L2 36.434 22.147 28.386 +M2 17.689 17.022 15.072 +N2 36.396 23.022 13.623 +O2 19.884 26.988 39.544 +P2 10.294 7.4271 3.4839 +Q2 24.415 37.008 36.288 +R2 36.078 21.682 26.898 +S2 12.232 12.247 33.412 +T2 12.486 23.920 5.4357 +U2 38.913 47.091 40.794 +V2 8.3779 6.8387 3.7119 +W2 2.3401 2.3804 1.9157 +X2 17.501 20.678 9.7225 +Y2 60.324 56.490 9.7029 +Z2 18.340 14.257 6.9452 +2A2 39.051 50.700 6.0515 +2B2 5.3134 8.7205 3.7883 +2C2 24.040 16.842 14.641 +2D2 10.963 22.720 8.1563 +A3 3.2215 2.8069 3.1344 +B3 35.703 49.122 24.276 +C3 9.6710 9.2674 28.141 +D3 39.368 42.329 16.693 +E3 9.8448 9.8037 29.501 +F3 50.040 60.997 38.371 +G3 9.8731 9.2375 28.216 +H3 31.926 43.409 5.2962 +I3 18.889 24.530 52.235 +J3 36.271 22.167 11.952 +K3 34.281 37.060 50.573 +L3 2.4511 2.5353 2.0398 +M3 34.120 37.136 30.510 +N3 28.309 16.461 3.7229 +O3 12.851 10.508 27.052 +P3 24.532 27.910 7.4170 +Q3 29.800 23.719 40.761 +R3 11.420 17.249 4.2060 +S3 30.098 17.923 3.6411 +T3 15.102 16.455 41.548 +U3 16.816 29.880 6.2892 +V3 19.054 17.886 40.635 +W3 21.160 13.146 3.6418 +X3 56.827 44.647 36.033 +Y3 7.3224 13.350 4.3645 +Z3 34.447 20.515 11.595 +2A3 10.795 11.448 32.464 +2B3 20.617 25.691 5.5795 +2C3 11.126 10.174 28.914 +2D3 68.724 66.102 56.410 +A4 19.671 15.554 33.919 +B4 17.501 19.753 3.8498 +C4 21.509 25.734 51.674 +D4 51.958 42.451 9.1213 +E4 14.112 17.806 42.697 +F4 61.487 65.884 27.427 +G4 38.420 23.239 29.457 +H4 9.8759 9.7311 29.126 +I4 75.793 79.718 46.695 +J4 10.595 15.480 24.653 +K4 32.187 21.331 32.814 +L4 13.777 17.753 16.663 +M4 27.339 16.027 3.5603 +N4 16.922 28.995 29.336 +O4 6.3066 4.7610 6.9921 +P4 22.390 29.210 15.592 +Q4 30.657 20.369 32.268 +R4 19.152 19.807 15.592 +S4 13.948 25.671 5.2122 +T4 14.991 27.898 19.745 +U4 11.486 7.6381 12.484 +V4 10.749 11.899 3.2945 +W4 77.699 80.782 67.995 +X4 24.430 21.610 7.1800 +Y4 3.2104 3.1999 4.2513 +Z4 14.450 27.763 8.5197 +2A4 21.679 16.235 32.574 +2B4 15.737 29.267 10.078 +2C4 3.9226 4.4418 7.5674 +2D4 24.022 34.375 15.022 +A5 16.920 10.945 3.6233 +B5 32.876 32.373 51.547 +C5 23.454 37.144 7.5202 +D5 24.762 25.266 23.702 +E5 29.192 16.958 3.5359 +F5 23.640 37.186 26.447 +G5 20.387 28.842 4.7028 +H5 3.3636 4.0809 2.6833 +I5 23.272 35.820 35.198 +J5 30.642 19.573 30.103 +K5 22.753 35.416 35.064 +L5 11.209 7.8786 3.5144 +M5 17.513 29.721 30.234 +N5 2.9935 2.9559 2.2837 +O5 44.139 49.035 35.423 +P5 14.200 13.959 3.6761 +Q5 59.021 56.831 48.262 +R5 6.3401 9.2262 3.4989 +S5 45.700 49.818 40.124 +T5 9.3142 14.437 4.0636 +U5 2.3535 2.3975 1.9290 +V5 27.766 28.925 20.091 +W5 3.0887 2.9300 2.3596 +X5 8.7239 16.803 5.0276 +Y5 70.161 75.882 63.247 +Z5 11.191 11.244 16.654 +2A5 62.394 68.771 47.096 +2B5 12.640 10.459 27.333 +2C5 11.160 21.761 5.5099 +2D5 77.413 80.592 53.936 +A6 37.703 22.453 27.499 +B6 14.943 18.301 44.058 +C6 44.282 30.956 7.9185 +D6 10.440 18.144 6.5076 +E6 32.892 20.486 29.274 +F6 17.819 31.263 19.184 +G6 3.7468 3.6058 6.3752 +H6 45.907 41.132 28.818 +I6 4.4472 4.1158 9.1204 +J6 20.388 31.549 44.358 +K6 2.3970 2.4515 1.9961 +L6 14.323 24.343 14.536 +M6 2.3623 2.4293 1.9541 +N6 41.190 36.767 50.714 +O6 62.357 69.847 6.3069 +P6 10.124 10.811 31.915 +Q6 67.127 65.762 49.352 +R6 39.128 23.959 27.822 +S6 10.413 15.222 6.7952 +T6 41.195 30.074 26.292 +U6 8.4099 9.5591 6.5834 +V6 43.942 26.976 32.439 +W6 33.397 44.263 15.513 +X6 56.629 45.672 50.137 +Y6 10.198 10.583 6.9283 +Z6 42.782 29.822 40.386 +2A6 61.567 65.013 61.274 +2B6 21.335 15.115 28.916 +2C6 3.2203 3.7212 2.6005 +2D6 35.799 34.854 29.422 +A7 19.123 33.078 10.667 +B7 12.915 10.831 28.225 +C7 77.518 80.587 57.622 +D7 11.348 10.154 28.703 +E7 12.442 24.254 5.6475 +F7 15.345 13.969 34.910 +G7 52.703 61.988 5.9513 +H7 9.9056 10.888 32.881 +I7 67.471 66.483 44.705 +J7 8.8426 9.6268 8.1730 +K7 61.925 56.855 24.968 +L7 9.6349 10.726 32.427 +M7 32.435 45.157 6.1480 +N7 30.427 18.146 3.6270 +O7 16.928 17.695 11.911 +P7 56.094 48.894 4.9467 +Q7 11.934 11.778 20.573 +R7 15.285 28.434 6.3346 +S7 3.5054 4.3615 2.7830 +T7 35.099 44.589 58.771 +U7 26.155 17.005 28.079 +V7 8.9086 14.924 14.071 +W7 30.611 33.536 8.6858 +X7 79.113 81.784 66.503 +Y7 10.240 10.764 31.229 +Z7 11.976 23.218 5.4228 +2A7 9.9976 9.7574 28.929 +2B7 25.572 39.297 14.262 +2C7 66.257 69.908 5.8960 +2D7 14.893 16.603 41.626 +A8 12.100 24.359 8.4071 +B8 42.436 39.900 4.7260 +C8 20.574 15.216 20.136 +D8 12.701 25.255 8.1803 +E8 18.324 13.039 26.409 +F8 16.724 30.035 13.212 +G8 3.3200 3.1831 3.0291 +H8 20.304 33.570 24.443 +I8 2.9169 2.9009 3.0168 +J8 48.038 46.099 39.891 +K8 5.2241 8.0427 3.5985 +L8 38.619 50.368 44.407 +M8 2.3428 2.3959 1.9273 +N8 3.1956 3.3116 2.6415 +O8 10.494 10.847 8.8081 +P8 22.233 23.005 18.548 +Q8 39.317 40.778 33.056 +R8 63.147 65.480 53.862 +S8 28.252 23.514 24.400 +T8 14.520 26.909 5.4756 +U8 18.057 24.054 51.817 +V8 2.3402 2.3911 1.9209 +W8 77.838 79.255 64.883 +X8 14.232 12.342 3.5677 +Y8 31.451 43.594 39.472 +Z8 3.8429 5.0881 3.0661 +2A8 27.844 41.491 21.140 +2B8 2.4921 2.5648 2.0613 +2C8 34.635 36.777 50.964 +2D8 2.3436 2.3905 1.9440 +A9 46.811 59.109 25.406 +B9 35.695 26.905 33.928 +C9 8.0578 15.313 4.8058 +D9 70.562 68.540 46.575 +E9 10.633 11.656 33.787 +F9 54.113 43.360 23.933 +G9 7.1200 11.358 10.328 +H9 31.237 20.786 32.756 +I9 14.469 27.174 19.553 +J9 11.813 8.1727 3.4750 +K9 51.613 51.265 59.093 +L9 11.232 21.889 5.3482 +M9 2.3389 2.3932 1.9205 +N9 4.6543 4.8363 3.9004 +O9 11.973 12.444 10.082 +P9 24.548 25.410 20.720 +Q9 43.270 44.842 36.215 +R9 68.113 71.034 59.864 +S9 31.468 18.903 5.4734 +T9 3.2297 3.6435 2.9170 +U9 31.779 25.042 15.321 +V9 30.098 43.673 10.856 +W9 65.360 57.273 55.175 +X9 7.8261 15.682 5.0934 +Y9 30.151 17.603 3.5424 +Z9 14.169 10.872 25.545 +2A9 49.740 51.961 35.295 +2B9 19.293 14.167 28.533 +2C9 23.305 29.469 10.465 +2D9 22.420 16.254 30.792 +A10 7.4766 14.316 6.7672 +B10 30.693 34.185 4.8132 +C10 11.568 23.235 13.773 +D10 2.4307 2.4999 2.0171 +E10 30.140 19.949 31.751 +F10 15.810 25.353 37.521 +G10 2.4272 2.4936 1.9887 +H10 12.549 25.096 11.562 +I10 2.3402 2.3788 1.9223 +J10 13.387 24.235 23.958 +K10 25.478 22.853 4.3681 +L10 5.0366 4.2550 2.8902 +M10 2.3374 2.3915 1.9194 +N10 5.8942 6.1054 4.9143 +O10 13.462 14.013 11.428 +P10 27.055 28.014 23.007 +Q10 47.406 49.169 39.386 +R10 73.974 77.043 65.729 +S10 7.8358 8.0794 7.9176 +T10 54.395 42.563 48.165 +U10 11.113 22.841 7.7084 +V10 2.9394 3.4387 2.9247 +W10 13.284 25.973 11.867 +X10 2.4768 2.5120 2.1182 +Y10 27.102 26.481 19.829 +Z10 23.978 16.698 3.6586 +2A10 24.659 30.178 27.108 +2B10 13.618 8.1445 8.4106 +2C10 24.412 26.496 22.533 +2D10 5.2897 4.2252 10.803 +A11 15.662 9.9371 16.757 +B11 6.3528 11.756 4.1276 +C11 70.247 65.054 58.834 +D11 42.904 30.283 4.3741 +E11 33.675 37.292 27.259 +F11 7.3260 5.3398 8.4321 +G11 56.748 56.026 41.441 +H11 8.1585 8.7147 3.0001 +I11 54.512 56.195 42.466 +J11 4.9736 7.2275 6.1574 +K11 50.413 50.352 29.675 +L11 11.783 8.3671 18.993 +M11 2.4004 2.4632 1.9865 +N11 7.0502 7.2979 5.9348 +O11 15.157 15.663 12.643 +P11 30.809 31.935 26.037 +Q11 51.029 52.827 42.179 +R11 78.892 82.077 69.152 +S11 9.0391 9.3614 7.5795 +T11 54.688 46.067 27.270 +U11 7.0672 5.5203 3.1542 +V11 19.018 30.251 40.808 +W11 2.6438 2.7813 2.1741 +X11 20.294 33.254 28.954 +Y11 4.7917 4.3367 10.461 +Z11 39.678 51.335 44.730 +2A11 11.397 22.075 5.4606 +2B11 43.396 54.386 47.692 +2C11 9.0264 8.0855 4.5632 +2D11 29.263 17.239 3.6542 +A12 42.435 55.238 11.960 +B12 10.244 9.5241 28.550 +C12 25.557 39.490 11.397 +D12 9.5983 9.1448 8.3283 +E12 71.285 77.444 27.463 +F12 32.592 33.399 30.058 +G12 5.1430 4.3541 13.182 +H12 18.517 32.087 22.562 +I12 6.9977 5.1440 3.8014 +J12 69.246 76.042 17.844 +K12 10.642 7.6407 17.593 +L12 21.927 35.477 19.681 +M12 2.4287 2.4921 1.9949 +N12 7.9937 8.3172 6.7360 +O12 17.120 17.761 14.285 +P12 33.242 34.486 28.221 +Q12 55.136 57.000 45.303 +R12 84.047 87.070 71.496 +S12 46.799 45.618 34.284 +T12 6.6921 6.0185 19.773 +U12 31.583 45.365 15.646 +V12 35.975 22.808 7.0470 +W12 15.632 16.004 15.333 +X12 32.188 19.569 3.7849 +Y12 9.9981 9.6287 28.171 +Z12 14.429 27.348 6.4901 +2A12 13.822 12.446 29.936 +2B12 68.261 74.431 52.067 +2C12 2.4685 2.5621 2.0287 +2D12 28.798 30.974 45.549 +A13 14.129 10.884 26.286 +B13 21.280 29.662 4.6515 +C13 32.064 17.966 13.604 +D13 9.9611 10.733 32.277 +E13 51.845 54.927 28.181 +F13 6.3441 8.5421 15.068 +G13 68.699 71.452 46.387 +H13 10.374 10.902 29.169 +I13 26.203 23.997 4.3858 +J13 25.753 36.554 54.373 +K13 5.9068 4.9157 15.287 +L13 35.348 27.270 4.1933 +M13 2.6154 2.7053 2.1626 +N13 9.3637 9.6843 7.8391 +O13 19.359 20.106 16.147 +P13 36.624 37.957 30.671 +Q13 59.859 61.861 49.702 +R13 89.957 93.025 75.604 +S13 17.613 12.665 26.369 +T13 22.969 25.114 7.7873 +U13 13.623 8.3610 7.6135 +V13 59.661 54.433 33.140 +W13 15.045 10.609 3.4373 +X13 26.676 39.190 37.659 +Y13 16.770 18.831 3.7976 +Z13 16.243 13.004 15.620 +2A13 62.079 69.145 59.254 +2B13 9.8300 11.508 34.315 +2C13 13.378 8.4024 4.1065 +2D13 11.706 16.228 24.708 +A14 27.260 17.709 28.446 +B14 10.007 11.116 33.309 +C14 55.170 63.826 56.969 +D14 22.474 12.791 7.8220 +E14 17.833 19.340 7.6068 +F14 25.508 15.387 3.5019 +G14 28.674 42.244 25.294 +H14 20.013 14.167 27.201 +I14 2.4079 2.4331 1.9867 +J14 23.527 21.066 41.374 +K14 23.203 12.509 8.0121 +L14 48.486 42.511 43.112 +M14 8.6031 15.926 4.6200 +N14 53.107 53.884 48.977 +O14 3.9836 3.7404 6.5852 +P14 35.517 35.068 43.001 +Q14 37.782 22.314 19.042 +R14 17.467 17.105 13.104 +S14 22.370 35.508 5.9931 +T14 23.886 13.985 16.868 +U14 19.591 19.252 12.172 +V14 63.345 63.812 5.6645 +W14 12.028 10.481 3.3856 +X14 42.635 43.420 39.912 +Y14 19.856 32.192 5.1431 +Z14 15.570 17.641 12.711 +2A14 29.733 19.495 31.105 +2B14 81.209 84.285 67.959 +2C14 16.972 13.897 32.504 +2D14 20.262 27.906 7.7177 +A15 24.922 14.319 17.652 +B15 20.394 32.266 39.177 +C15 28.847 42.042 6.3345 +D15 27.579 26.553 23.681 +E15 38.874 23.290 19.357 +F15 36.703 46.352 27.027 +G15 34.061 22.803 34.531 +H15 10.113 11.921 31.879 +I15 64.423 58.008 39.281 +J15 9.4542 9.1717 6.7120 +K15 48.073 52.062 16.154 +L15 22.225 20.657 33.169 +M15 32.410 43.840 8.6168 +N15 19.932 29.141 53.896 +O15 8.2354 6.1612 3.2448 +P15 21.186 33.689 34.860 +Q15 2.8839 2.9372 2.7235 +R15 16.647 10.677 18.389 +S15 35.874 22.454 3.7685 +T15 18.024 31.495 21.231 +U15 26.027 17.635 30.172 +V15 5.7623 9.6302 3.8733 +W15 53.522 58.991 41.376 +X15 23.991 17.693 34.060 +Y15 3.5595 3.8688 2.3978 +Z15 34.055 35.265 28.241 +2A15 29.379 16.826 7.3609 +2B15 9.2107 8.5579 25.691 +2C15 25.707 18.129 3.6532 +2D15 13.875 19.568 19.948 +A16 32.441 19.582 3.7464 +B16 43.738 40.362 16.554 +C16 4.9159 8.3065 7.2559 +D16 37.197 27.832 7.4910 +E16 36.691 35.876 51.695 +F16 38.836 30.036 4.3338 +G16 17.555 13.363 28.888 +H16 75.466 77.836 67.216 +I16 16.954 15.112 7.2992 +J16 47.072 52.200 10.669 +K16 55.962 60.759 50.287 +L16 10.165 9.7715 28.705 +M16 36.859 23.500 3.8297 +N16 29.735 43.076 29.229 +O16 7.3545 6.2503 2.9745 +P16 46.114 46.965 33.568 +Q16 6.2218 6.8107 2.7776 +R16 29.663 17.214 6.8286 +S16 8.0381 10.138 16.410 +T16 31.088 18.734 3.6263 +U16 18.911 32.215 23.899 +V16 26.145 16.883 27.363 +W16 33.705 20.761 3.7986 +X16 14.361 27.487 7.1744 +Y16 29.882 22.982 39.138 +Z16 2.4233 2.4412 1.9648 +2A16 42.519 39.188 21.270 +2B16 5.2349 4.4461 13.823 +2C16 32.492 19.465 7.0806 +2D16 33.454 46.863 22.481 +A17 18.355 31.722 19.048 +B17 4.8626 4.2833 10.526 +C17 39.631 36.092 16.781 +D17 3.8471 5.8319 4.8962 +E17 43.491 44.349 22.904 +F17 35.028 21.444 3.8305 +G17 23.826 20.302 40.464 +H17 44.211 56.679 16.435 +I17 6.5115 6.2807 3.6004 +J17 35.464 48.530 31.500 +K17 31.217 18.833 4.2081 +L17 6.1796 5.0138 3.0160 +M17 21.355 33.511 36.981 +N17 31.382 17.339 13.539 +O17 20.515 20.076 24.934 +P17 32.143 19.447 3.7592 +Q17 60.501 50.532 52.708 +R17 12.657 24.420 5.6873 +S17 3.4355 3.1639 2.5372 +T17 28.192 29.771 51.322 +U17 52.660 42.651 15.019 +V17 69.823 71.393 63.731 +W17 44.995 50.413 5.2421 +X17 37.401 38.967 26.702 +Y17 8.0339 5.5483 9.9052 +Z17 10.382 21.829 11.599 +2A17 34.325 21.131 7.2263 +2B17 9.1863 9.9839 3.1512 +2C17 75.534 73.388 61.922 +2D17 19.258 14.916 29.290 +A18 74.089 78.770 59.424 +B18 42.903 30.204 40.715 +C18 8.7363 10.837 6.0872 +D18 75.509 74.636 56.066 +E18 10.413 9.8011 28.727 +F18 11.836 22.861 5.4226 +G18 26.954 18.177 29.358 +H18 16.220 29.699 13.154 +I18 2.3647 2.3980 1.9090 +J18 77.786 81.283 65.463 +K18 14.363 11.898 6.7644 +L18 60.378 57.128 5.2726 +M18 30.554 20.123 31.743 +N18 24.748 27.645 20.451 +O18 44.929 31.003 12.389 +P18 11.881 10.425 27.990 +Q18 25.737 39.690 14.823 +R18 52.300 42.856 4.6545 +S18 7.2126 14.429 7.1944 +T18 77.679 78.425 65.193 +U18 47.084 32.209 22.319 +V18 6.6683 11.848 10.189 +W18 65.207 70.970 60.729 +X18 6.2806 11.330 4.1095 +Y18 60.571 56.044 16.070 +Z18 15.673 16.045 40.153 +2A18 41.178 25.901 19.845 +2B18 13.693 16.674 24.407 +2C18 74.223 78.952 41.733 +2D18 38.135 24.817 4.1395 +A19 39.239 29.094 15.479 +B19 4.7416 7.0454 3.4644 +C19 49.395 43.657 28.522 +D19 42.332 52.372 5.7052 +E19 24.242 22.424 14.026 +F19 2.4551 2.5226 2.0256 +G19 16.677 25.667 25.825 +H19 13.124 8.8453 3.5763 +I19 28.527 37.076 34.358 +J19 22.891 16.490 6.9749 +K19 22.666 35.279 35.631 +L19 5.4212 4.5484 2.9627 +M19 11.199 21.925 5.4425 +N19 22.708 12.897 3.6335 +O19 12.507 23.738 22.498 +P19 2.3442 2.3896 1.9267 +Q19 30.303 17.749 3.5777 +R19 10.104 9.7374 28.448 +S19 13.901 26.685 6.3873 +T19 2.4391 2.4780 2.0610 +U19 45.972 49.473 57.247 +V19 4.8275 8.3485 3.9886 +W19 63.154 70.855 7.5811 +X19 14.863 14.166 8.5770 +Y19 74.340 78.986 66.286 +Z19 49.996 33.344 36.894 +2A19 10.165 11.287 33.081 +2B19 62.642 69.515 6.2139 +2C19 38.429 24.741 7.3479 +2D19 12.944 12.283 32.608 + +A1 106.60 73.896 140.50 +B1 101.22 157.76 91.298 +C1 56.474 54.712 116.20 +D1 142.23 143.96 106.67 +E1 161.58 92.303 143.82 +F1 90.405 96.497 94.153 +G1 163.39 98.124 88.178 +H1 63.278 55.370 115.21 +I1 71.385 133.64 49.363 +J1 97.757 75.383 143.28 +K1 194.49 193.52 200.39 +L1 43.729 37.037 36.612 +M1 128.36 143.53 178.51 +N1 136.71 176.12 173.90 +O1 190.25 190.03 173.26 +P1 139.89 69.074 45.054 +Q1 34.433 40.188 37.667 +R1 87.362 153.04 89.833 +S1 124.79 84.048 151.84 +T1 201.42 206.76 79.283 +U1 59.875 104.70 93.370 +V1 205.39 208.60 159.63 +W1 91.572 136.12 167.03 +X1 30.336 29.306 28.957 +Y1 132.60 110.17 107.91 +Z1 32.956 33.215 31.185 +2A1 70.282 129.32 46.946 +2B1 159.00 173.65 202.91 +2C1 121.19 88.150 161.84 +2D1 136.59 101.50 125.83 +A2 75.414 80.525 150.43 +B2 128.64 63.027 42.872 +C2 101.62 116.40 166.26 +D2 129.62 78.772 146.55 +E2 164.20 144.75 82.589 +F2 96.904 110.83 179.21 +G2 157.24 84.071 46.359 +H2 84.439 70.424 140.26 +I2 81.661 147.44 58.864 +J2 35.433 35.856 32.072 +K2 150.66 144.08 140.58 +L2 158.35 93.379 154.74 +M2 100.38 93.492 99.897 +N2 158.93 93.968 95.921 +O2 102.60 137.21 171.09 +P2 74.932 50.703 44.902 +Q2 115.12 165.78 166.70 +R2 157.97 92.663 150.58 +S2 83.913 88.787 161.27 +T2 72.772 133.20 48.154 +U2 155.64 177.45 175.23 +V2 65.311 50.797 44.712 +W2 30.304 29.389 28.630 +X2 98.383 112.57 76.501 +Y2 196.95 176.56 81.174 +Z2 106.87 76.461 64.020 +2A2 149.29 180.57 55.756 +2B2 46.850 72.093 42.887 +2C2 126.21 86.097 104.74 +2D2 68.443 138.05 59.668 +A3 40.703 34.668 43.170 +B3 140.80 177.61 130.47 +C3 71.422 72.467 144.63 +D3 157.83 159.05 109.87 +E3 74.511 78.412 148.91 +F3 172.35 192.98 167.60 +G3 72.505 72.322 146.66 +H3 132.85 167.63 50.020 +I3 99.822 132.27 193.48 +J3 158.78 88.817 87.144 +K3 146.32 156.61 192.38 +L3 30.978 30.641 29.826 +M3 146.27 153.30 150.57 +N3 144.16 70.919 46.534 +O3 85.091 72.947 144.27 +P3 122.91 131.12 67.881 +Q3 140.27 116.77 178.48 +R3 73.020 103.31 46.082 +S3 148.58 74.828 46.145 +T3 92.676 106.61 179.17 +U3 89.067 149.36 56.522 +V3 104.27 103.98 177.68 +W3 122.27 64.970 44.965 +X3 190.80 157.08 167.65 +Y3 55.033 94.759 44.077 +Z3 157.08 85.576 87.558 +2A3 79.250 88.578 159.52 +2B3 108.15 127.71 55.172 +2C3 78.102 75.847 150.05 +2D3 202.83 194.20 199.16 +A4 105.09 86.729 157.14 +B4 99.696 102.26 43.923 +C4 107.26 130.81 190.72 +D4 178.30 141.51 75.719 +E4 86.201 111.97 176.39 +F4 192.41 193.92 143.50 +G4 161.20 95.317 155.94 +H4 74.863 77.945 149.59 +I4 207.61 208.23 184.16 +J4 70.931 101.90 131.71 +K4 147.01 94.545 162.80 +L4 81.586 103.83 104.84 +M4 141.06 69.848 45.247 +N4 90.494 151.07 150.65 +O4 55.294 41.016 63.313 +P4 111.84 140.47 103.22 +Q4 144.45 93.249 162.31 +R4 105.31 104.82 101.31 +S4 79.325 137.68 48.973 +T4 84.189 150.82 120.01 +U4 81.413 52.379 93.432 +V4 76.459 77.531 42.048 +W4 211.28 212.44 213.00 +X4 125.79 102.06 67.469 +Y4 36.736 36.340 46.306 +Z4 83.114 150.29 61.891 +2A4 117.71 90.574 160.37 +2B4 89.463 153.87 72.494 +2C4 42.498 47.832 65.570 +2D4 115.91 156.34 101.73 +A5 100.43 57.576 43.875 +B5 139.57 140.52 191.37 +C5 106.24 157.82 63.346 +D5 120.63 119.68 128.56 +E5 144.32 70.530 44.643 +F5 112.12 164.88 139.23 +G5 103.37 136.87 47.413 +H5 36.251 41.780 35.395 +I5 111.24 162.80 164.26 +J5 143.56 87.562 156.55 +K5 109.54 163.06 164.19 +L5 79.627 52.133 45.354 +M5 92.456 152.33 153.19 +N5 34.714 33.013 32.281 +O5 166.35 175.94 163.99 +P5 89.669 79.549 47.144 +Q5 191.24 182.85 188.48 +R5 51.675 70.899 41.770 +S5 170.53 177.54 173.76 +T5 63.890 93.942 45.687 +U5 30.168 29.299 28.940 +V5 133.08 133.14 122.05 +W5 36.054 32.923 33.276 +X5 61.314 111.77 45.755 +Y5 203.39 209.40 208.06 +Z5 76.353 77.670 109.77 +2A5 193.86 202.18 186.73 +2B5 84.630 73.965 145.61 +2C5 68.392 129.05 45.336 +2D5 210.46 210.49 195.89 +A6 156.79 90.614 148.03 +B6 88.481 111.82 178.46 +C6 167.90 108.82 66.983 +D6 66.578 110.85 54.360 +E6 148.31 87.735 154.80 +F6 93.611 155.13 115.73 +G6 40.190 39.280 58.763 +H6 170.89 152.59 147.19 +I6 46.469 44.545 75.326 +J6 102.48 151.18 180.03 +K6 30.872 30.164 29.516 +L6 83.294 137.00 98.315 +M6 30.722 30.150 29.446 +N6 163.74 151.67 194.83 +O6 199.83 203.65 49.970 +P6 77.512 86.873 159.07 +Q6 200.99 194.31 190.45 +R6 165.39 100.99 154.68 +S6 69.496 98.026 61.986 +T6 167.68 124.93 146.98 +U6 62.706 68.483 60.211 +V6 174.63 108.06 166.14 +W6 138.60 174.02 106.27 +X6 192.12 161.59 197.05 +Y6 71.207 70.503 63.173 +Z6 171.42 121.85 182.26 +2A6 193.77 197.98 207.14 +2B6 117.80 82.965 151.94 +2C6 36.305 39.517 34.462 +2D6 152.48 145.44 148.89 +A7 93.637 153.35 73.710 +B7 83.277 73.755 144.52 +C7 206.85 206.70 197.33 +D7 77.454 73.349 146.72 +E7 70.809 132.64 47.023 +F7 91.049 88.345 163.10 +G7 177.87 190.87 53.018 +H7 75.960 87.720 159.98 +I7 199.48 192.77 181.55 +J7 64.713 68.090 67.610 +K7 193.08 175.48 139.54 +L7 75.430 87.876 159.79 +M7 133.24 173.17 56.742 +N7 148.49 75.098 46.216 +O7 97.134 97.177 86.559 +P7 191.20 160.30 54.685 +Q7 80.068 80.251 125.32 +R7 83.368 147.19 55.358 +S7 37.747 44.719 36.907 +T7 146.52 175.26 205.50 +U7 133.97 82.941 152.98 +V7 63.182 103.22 97.125 +W7 144.22 147.07 76.384 +X7 212.78 213.19 211.89 +Y7 77.896 86.298 158.37 +Z7 71.313 133.52 47.389 +2A7 75.926 78.650 151.98 +2B7 118.08 168.98 98.781 +2C7 207.34 198.34 43.623 +2D7 92.639 108.26 179.66 +A8 69.904 137.36 58.325 +B8 167.09 144.55 49.599 +C8 111.10 78.672 121.83 +D8 74.340 141.34 56.829 +E8 104.13 74.055 141.65 +F8 90.075 154.61 90.911 +G8 36.341 33.896 36.868 +H8 101.65 159.66 134.07 +I8 34.216 33.499 37.712 +J8 174.41 165.56 173.38 +K8 46.252 66.300 42.397 +L8 152.69 184.12 182.69 +M8 30.240 29.863 28.939 +N8 35.593 35.467 34.190 +O8 71.728 71.553 70.937 +P8 115.92 116.10 114.68 +Q8 159.85 160.38 159.13 +R8 196.60 197.21 197.12 +S8 137.57 112.53 140.33 +T8 80.940 142.13 50.952 +U8 99.365 133.93 196.43 +V8 30.957 30.566 29.813 +W8 212.09 210.69 210.55 +X8 90.920 71.799 46.751 +Y8 137.72 177.30 175.40 +Z8 39.524 49.911 38.685 +2A8 130.39 176.13 127.05 +2B8 31.904 31.437 30.690 +2C8 149.77 158.18 196.00 +2D8 30.719 29.824 29.600 +A9 160.64 188.72 135.75 +B9 151.09 113.48 161.82 +C9 56.378 101.12 44.028 +D9 200.86 192.61 183.06 +E9 77.639 89.149 161.20 +F9 183.43 148.52 132.23 +G9 53.868 83.869 77.703 +H9 144.68 93.693 163.06 +I9 80.625 147.05 117.46 +J9 82.612 53.093 45.342 +K9 179.05 178.11 205.03 +L9 68.256 128.21 45.397 +M9 30.122 29.559 28.786 +N9 44.132 44.030 43.113 +O9 77.603 77.496 77.212 +P9 123.38 123.35 123.35 +Q9 167.61 168.12 167.11 +R9 202.61 204.17 205.53 +S9 152.34 81.269 59.657 +T9 36.525 39.233 37.120 +U9 147.79 112.59 105.57 +V9 128.85 175.42 85.449 +W9 202.12 182.11 203.04 +X9 58.841 111.22 46.014 +Y9 150.27 74.574 46.780 +Z9 91.373 72.814 142.15 +2A9 178.42 178.87 165.68 +2B9 110.21 82.066 150.83 +2C9 115.57 141.00 82.227 +2D9 120.44 87.308 156.62 +A10 54.278 98.104 59.100 +B10 141.49 142.92 50.130 +C10 69.545 135.98 93.417 +D10 30.772 30.009 29.471 +E10 140.52 89.479 159.03 +F10 88.149 135.62 165.23 +G10 30.508 30.075 29.389 +H10 75.794 144.13 86.030 +I10 29.881 29.286 28.915 +J10 78.427 139.08 135.09 +K10 127.69 103.24 52.122 +L10 47.518 38.484 37.887 +M10 30.202 29.466 28.978 +N10 50.671 50.438 49.901 +O10 84.087 84.218 84.130 +P10 130.92 131.27 131.19 +Q10 174.24 174.94 173.31 +R10 208.46 209.75 212.17 +S10 61.440 61.759 68.112 +T10 189.59 154.63 195.61 +U10 70.065 139.76 58.155 +V10 34.382 38.877 37.374 +W10 81.185 148.91 88.683 +X10 31.337 30.706 30.647 +Y10 132.10 124.54 122.36 +Z10 128.86 77.259 44.848 +2A10 121.07 144.71 145.24 +2B10 91.404 54.498 76.524 +2C10 122.45 129.19 129.52 +2D10 52.091 43.712 85.349 +A11 95.121 56.945 109.13 +B11 49.247 84.978 41.595 +C11 201.38 188.28 201.57 +D11 165.99 106.71 48.883 +E11 142.45 151.87 140.77 +F11 59.895 43.373 70.686 +G11 185.60 179.80 175.52 +H11 62.810 62.001 39.464 +I11 182.38 181.99 177.01 +J11 44.613 62.579 56.523 +K11 177.26 171.26 154.02 +L11 81.706 58.921 119.57 +M11 30.648 29.769 29.464 +N11 56.534 56.324 55.689 +O11 89.911 89.936 88.980 +P11 140.77 141.41 140.88 +Q11 179.84 180.21 178.58 +R11 212.60 213.84 215.53 +S11 66.493 66.184 65.558 +T11 187.32 160.61 146.99 +U11 59.842 44.929 41.517 +V11 100.71 151.70 177.40 +W11 32.433 32.983 31.555 +X11 103.41 161.56 150.03 +Y11 49.930 46.756 84.028 +Z11 157.24 187.57 185.20 +2A11 69.840 130.51 46.639 +2B11 164.73 190.77 189.92 +2C11 67.660 57.565 50.639 +2D11 146.88 73.255 46.894 +A12 149.18 183.06 84.464 +B12 72.446 71.794 146.17 +C12 111.58 163.80 82.344 +D12 67.115 62.023 67.669 +E12 202.25 206.59 144.16 +F12 142.52 142.52 149.46 +G12 52.218 46.843 96.005 +H12 95.301 157.62 128.66 +I12 58.804 42.199 45.333 +J12 201.67 207.01 112.57 +K12 76.878 56.433 113.86 +L12 110.43 164.87 121.89 +M12 31.073 30.502 29.828 +N12 60.863 60.999 60.221 +O12 97.436 97.414 96.425 +P12 146.96 147.76 147.68 +Q12 186.04 186.49 184.52 +R12 217.03 217.69 217.80 +S12 173.81 166.67 164.48 +T12 61.998 59.133 126.43 +U12 133.08 178.53 107.01 +V12 159.59 92.307 67.569 +W12 92.823 93.091 102.67 +X12 153.31 79.910 48.385 +Y12 76.169 77.765 152.48 +Z12 80.867 145.82 55.209 +2A12 88.726 84.091 155.13 +2B12 201.37 208.14 195.53 +2C12 32.004 31.705 30.813 +2D12 135.53 145.08 187.78 +A13 86.415 69.301 138.07 +B13 104.58 136.42 46.559 +C13 147.82 79.114 100.32 +D13 75.334 85.157 157.26 +E13 178.81 179.96 148.24 +F13 55.482 72.327 100.16 +G13 200.09 199.75 184.43 +H13 76.688 84.710 151.41 +I13 129.73 107.35 52.022 +J13 119.03 160.66 198.42 +K13 56.473 50.032 106.16 +L13 153.18 106.56 46.936 +M13 32.264 31.978 31.289 +N13 66.470 66.520 66.246 +O13 105.28 105.86 104.76 +P13 153.75 154.63 154.12 +Q13 192.03 192.25 191.27 +R13 221.68 221.89 221.96 +S13 104.20 75.856 145.33 +T13 121.87 124.18 72.370 +U13 91.392 55.886 72.021 +V13 193.01 176.53 161.70 +W13 97.047 61.496 44.638 +X13 124.18 171.27 172.48 +Y13 100.95 103.55 45.932 +Z13 98.719 76.722 108.03 +2A13 193.99 204.68 205.71 +2B13 77.619 94.368 167.50 +2C13 91.512 53.191 50.701 +2D13 76.609 104.98 135.45 +A14 129.84 79.131 147.61 +B14 74.731 86.884 158.53 +C14 178.45 194.65 198.02 +D14 122.80 65.789 71.805 +E14 99.529 101.15 66.691 +F14 133.73 68.160 43.803 +G14 130.31 174.28 137.87 +H14 110.49 77.413 145.63 +I14 30.999 29.764 29.587 +J14 120.14 114.13 178.99 +K14 128.29 64.544 74.117 +L14 176.70 157.34 183.40 +M14 59.777 105.00 45.141 +N14 182.00 181.11 190.30 +O14 42.651 40.749 62.042 +P14 151.32 150.31 182.91 +Q14 162.51 94.932 125.82 +R14 99.745 94.301 93.467 +S14 107.25 159.78 58.090 +T14 128.01 72.369 117.84 +U14 107.76 101.18 90.766 +V14 204.14 190.16 48.644 +W14 82.597 65.626 44.970 +X14 166.39 166.20 175.82 +Y14 100.69 152.17 51.384 +Z14 91.650 100.20 90.746 +2A14 143.62 91.243 162.04 +2B14 214.71 215.34 214.31 +2C14 101.32 87.875 161.74 +2D14 105.18 138.75 68.497 +A15 124.84 68.758 114.78 +B15 99.929 150.22 167.53 +C15 121.25 165.78 57.133 +D15 129.49 121.04 130.58 +E15 161.27 95.254 123.97 +F15 148.20 174.03 142.22 +G15 150.41 98.923 167.42 +H15 75.180 91.615 158.04 +I15 196.22 179.25 172.32 +J15 66.558 62.105 60.696 +K15 174.25 177.65 112.40 +L15 116.33 112.29 162.02 +M15 133.68 171.46 73.038 +N15 102.47 146.49 198.15 +O15 64.715 46.574 43.032 +P15 105.91 159.08 164.78 +Q15 34.379 33.754 36.003 +R15 102.62 61.271 119.89 +S15 159.62 86.224 48.021 +T15 95.611 158.57 127.45 +U15 133.03 87.140 157.87 +V15 48.894 77.368 43.484 +W15 182.54 191.20 178.40 +X15 126.00 95.308 166.74 +Y15 38.376 39.986 33.590 +Z15 148.30 148.94 147.37 +2A15 146.55 75.055 68.429 +2B15 71.706 70.645 144.63 +2C15 133.02 80.816 44.452 +2D15 82.777 113.54 117.52 +A16 147.43 75.104 45.417 +B16 162.22 145.05 108.87 +C16 43.273 69.681 61.261 +D16 154.15 106.72 65.606 +E16 149.19 148.83 193.98 +F16 157.80 111.38 47.573 +G16 100.61 79.449 149.13 +H16 206.92 207.61 211.44 +I16 97.895 82.272 66.348 +J16 172.80 178.46 82.595 +K16 183.90 191.17 190.75 +L16 75.048 76.021 151.02 +M16 159.42 88.282 47.938 +N16 133.24 176.09 150.50 +O16 59.749 48.251 40.198 +P16 171.06 168.69 161.58 +Q16 53.260 54.841 37.700 +R16 147.03 76.735 66.424 +S16 63.206 78.809 107.93 +T16 150.22 77.352 47.226 +U16 97.824 159.49 134.64 +V16 133.39 81.567 151.23 +W16 155.32 82.024 48.477 +X16 81.301 147.86 56.013 +Y16 141.53 112.75 178.08 +Z16 31.556 30.196 30.075 +2A16 166.04 149.78 129.15 +2B16 53.939 48.402 100.70 +2C16 152.96 83.435 68.500 +2D16 141.97 181.00 131.63 +A17 93.002 152.57 112.99 +B17 48.562 44.595 81.595 +C17 155.24 137.12 108.13 +D17 37.723 54.820 48.270 +E17 163.04 158.68 133.73 +F17 155.10 81.151 47.477 +G17 119.76 108.26 175.73 +H17 155.83 188.69 108.40 +I17 54.125 49.417 43.252 +J17 146.89 182.65 155.76 +K17 148.71 77.345 50.119 +L17 53.925 41.854 39.291 +M17 105.46 156.83 167.45 +N17 149.16 79.222 103.08 +O17 109.98 107.89 138.78 +P17 151.99 78.765 47.620 +Q17 195.13 169.06 200.08 +R17 73.599 136.55 49.271 +S17 37.757 33.718 34.938 +T17 132.61 142.77 197.68 +U17 181.82 145.93 103.48 +V17 204.10 203.91 210.35 +W17 175.82 179.36 52.229 +X17 155.69 156.50 143.88 +Y17 65.731 44.495 80.654 +Z17 67.930 138.21 88.916 +2A17 156.40 87.866 68.881 +2B17 68.870 68.990 41.254 +2C17 209.60 202.66 207.60 +2D17 108.97 87.062 152.98 +A18 200.70 204.40 197.90 +B18 164.93 117.44 177.68 +C18 61.227 72.827 56.013 +D18 204.51 199.19 195.95 +E18 73.692 73.322 148.06 +F18 68.313 128.24 45.392 +G18 131.14 85.288 152.52 +H18 89.609 153.68 93.128 +I18 30.179 29.676 28.922 +J18 208.65 210.69 209.48 +K18 88.863 70.346 63.498 +L18 197.92 177.16 54.602 +M18 143.55 91.470 162.00 +N18 121.99 131.52 122.44 +O18 172.04 115.00 91.328 +P18 81.187 74.923 148.64 +Q18 117.91 169.48 101.12 +R18 183.93 145.62 52.297 +S18 55.452 105.38 65.438 +T18 211.11 208.92 210.90 +U18 177.41 124.39 134.00 +V18 53.506 90.891 78.889 +W18 197.65 205.13 206.81 +X18 51.396 86.860 43.674 +Y18 193.58 175.18 113.92 +Z18 96.313 103.94 178.60 +2A18 168.53 106.08 128.73 +2B18 85.496 104.15 136.89 +2C18 208.09 210.26 179.31 +2D18 161.94 92.492 50.116 +A19 156.71 112.54 101.12 +B19 42.513 58.501 40.536 +C19 172.17 152.13 143.40 +D19 159.73 183.13 54.703 +E19 119.21 105.48 95.518 +F19 30.235 29.764 29.269 +G19 88.689 134.99 136.69 +H19 86.392 53.901 45.566 +I19 126.88 158.15 160.78 +J19 120.42 79.125 64.241 +K19 108.34 160.80 164.56 +L19 49.327 39.952 38.592 +M19 67.917 128.27 44.976 +N19 127.84 62.080 45.945 +O19 74.380 138.45 130.11 +P19 30.060 29.337 28.817 +Q19 147.97 73.539 46.480 +R19 75.153 76.608 151.15 +S19 78.339 144.41 52.936 +T19 31.312 30.556 30.767 +U19 169.32 177.98 203.35 +V19 44.471 72.376 45.634 +W19 199.02 205.39 55.979 +X19 90.125 81.954 73.039 +Y19 207.33 211.44 212.22 +Z19 182.95 126.85 175.69 +2A19 77.857 90.598 163.13 +2B19 202.16 204.23 49.052 +2C19 162.94 96.440 68.740 +2D19 83.952 84.116 160.97 + diff --git a/scanin/CMP_Digital_Target-3.cie b/scanin/CMP_Digital_Target-3.cie new file mode 100644 index 0000000..6c8ff5d --- /dev/null +++ b/scanin/CMP_Digital_Target-3.cie @@ -0,0 +1,591 @@ +CTI3 + +DESCRIPTOR "Argyll Calibration Target chart information 3" +ORIGINATOR "Argyll chartread" +CREATED "Mon Sep 7 08:33:21 2009" +KEYWORD "DEVICE_CLASS" +DEVICE_CLASS "OUTPUT" +KEYWORD "COLOR_REP" +COLOR_REP "RGB_XYZ" +KEYWORD "TARGET_INSTRUMENT" +TARGET_INSTRUMENT "GretagMacbeth i1 Pro" + +KEYWORD "SAMPLE_LOC" +NUMBER_OF_FIELDS 8 +BEGIN_DATA_FORMAT +SAMPLE_ID SAMPLE_LOC RGB_R RGB_G RGB_B XYZ_X XYZ_Y XYZ_Z +END_DATA_FORMAT + +NUMBER_OF_SETS 570 +BEGIN_DATA +1 "A1" 106.60 73.896 140.50 19.991 14.120 27.886 +2 "B1" 101.22 157.76 91.298 19.926 34.054 14.005 +3 "C1" 56.474 54.712 116.20 6.2319 5.6339 19.078 +4 "D1" 142.23 143.96 106.67 32.785 35.198 16.672 +5 "E1" 161.58 92.303 143.82 38.996 22.658 25.805 +6 "F1" 90.405 96.497 94.153 16.011 17.612 14.561 +7 "G1" 163.39 98.124 88.178 39.496 24.997 12.003 +8 "H1" 63.278 55.370 115.21 7.4905 6.2468 18.358 +9 "I1" 71.385 133.64 49.363 11.987 23.286 6.5928 +10 "J1" 97.757 75.383 143.28 16.591 12.444 27.331 +11 "K1" 194.49 193.52 200.39 63.038 64.179 58.403 +12 "L1" 43.729 37.037 36.612 4.3513 3.8393 2.7750 +13 "M1" 128.36 143.53 178.51 27.386 30.873 42.527 +14 "N1" 136.71 176.12 173.90 31.789 44.281 40.439 +15 "O1" 190.25 190.03 173.26 59.453 61.985 40.335 +16 "P1" 139.89 69.074 45.054 26.783 15.713 3.5833 +17 "Q1" 34.433 40.188 37.667 3.0238 3.6843 3.0876 +18 "R1" 87.362 153.04 89.833 15.462 28.885 12.776 +19 "S1" 124.79 84.048 151.84 23.694 16.421 29.352 +20 "T1" 201.42 206.76 79.283 65.900 73.381 11.377 +21 "U1" 59.875 104.70 93.370 8.3333 15.036 13.749 +22 "V1" 205.39 208.60 159.63 72.416 77.985 33.423 +23 "W1" 91.572 136.12 167.03 16.393 25.254 38.122 +24 "X1" 30.336 29.306 28.957 2.3144 2.3581 1.9303 +25 "Y1" 132.60 110.17 107.91 27.102 23.276 16.813 +26 "Z1" 32.956 33.215 31.185 2.6994 2.8850 2.2332 +27 "2A1" 70.282 129.32 46.946 10.757 20.588 4.8216 +28 "2B1" 159.00 173.65 202.91 40.765 45.919 58.857 +29 "2C1" 121.19 88.150 161.84 22.864 16.381 33.839 +30 "2D1" 136.59 101.50 125.83 28.289 21.404 20.483 +31 "A2" 75.414 80.525 150.43 10.412 10.567 30.978 +32 "B2" 128.64 63.027 42.872 24.139 14.085 3.5857 +33 "C2" 101.62 116.40 166.26 19.473 21.752 38.376 +34 "D2" 129.62 78.772 146.55 26.280 16.991 28.035 +35 "E2" 164.20 144.75 82.589 42.573 39.671 9.6556 +36 "F2" 96.904 110.83 179.21 17.113 18.705 43.690 +37 "G2" 157.24 84.071 46.359 35.850 22.548 3.8554 +38 "H2" 84.439 70.424 140.26 13.037 10.392 26.425 +39 "I2" 81.661 147.44 58.864 14.946 28.262 8.1825 +40 "J2" 35.433 35.856 32.072 3.1780 3.3914 2.3047 +41 "K2" 150.66 144.08 140.58 35.880 35.178 26.683 +42 "L2" 158.35 93.379 154.74 36.434 22.147 28.386 +43 "M2" 100.38 93.492 99.897 17.689 17.022 15.072 +44 "N2" 158.93 93.968 95.921 36.396 23.022 13.623 +45 "O2" 102.60 137.21 171.09 19.884 26.988 39.544 +46 "P2" 74.932 50.703 44.902 10.294 7.4271 3.4839 +47 "Q2" 115.12 165.78 166.70 24.415 37.008 36.288 +48 "R2" 157.97 92.663 150.58 36.078 21.682 26.898 +49 "S2" 83.913 88.787 161.27 12.232 12.247 33.412 +50 "T2" 72.772 133.20 48.154 12.486 23.920 5.4357 +51 "U2" 155.64 177.45 175.23 38.913 47.091 40.794 +52 "V2" 65.311 50.797 44.712 8.3779 6.8387 3.7119 +53 "W2" 30.304 29.389 28.630 2.3401 2.3804 1.9157 +54 "X2" 98.383 112.57 76.501 17.501 20.678 9.7225 +55 "Y2" 196.95 176.56 81.174 60.324 56.490 9.7029 +56 "Z2" 106.87 76.461 64.020 18.340 14.257 6.9452 +57 "2A2" 149.29 180.57 55.756 39.051 50.700 6.0515 +58 "2B2" 46.850 72.093 42.887 5.3134 8.7205 3.7883 +59 "2C2" 126.21 86.097 104.74 24.040 16.842 14.641 +60 "2D2" 68.443 138.05 59.668 10.963 22.720 8.1563 +61 "A3" 40.703 34.668 43.170 3.2215 2.8069 3.1344 +62 "B3" 140.80 177.61 130.47 35.703 49.122 24.276 +63 "C3" 71.422 72.467 144.63 9.6710 9.2674 28.141 +64 "D3" 157.83 159.05 109.87 39.368 42.329 16.693 +65 "E3" 74.511 78.412 148.91 9.8448 9.8037 29.501 +66 "F3" 172.35 192.98 167.60 50.040 60.997 38.371 +67 "G3" 72.505 72.322 146.66 9.8731 9.2375 28.216 +68 "H3" 132.85 167.63 50.020 31.926 43.409 5.2962 +69 "I3" 99.822 132.27 193.48 18.889 24.530 52.235 +70 "J3" 158.78 88.817 87.144 36.271 22.167 11.952 +71 "K3" 146.32 156.61 192.38 34.281 37.060 50.573 +72 "L3" 30.978 30.641 29.826 2.4511 2.5353 2.0398 +73 "M3" 146.27 153.30 150.57 34.120 37.136 30.510 +74 "N3" 144.16 70.919 46.534 28.309 16.461 3.7229 +75 "O3" 85.091 72.947 144.27 12.851 10.508 27.052 +76 "P3" 122.91 131.12 67.881 24.532 27.910 7.4170 +77 "Q3" 140.27 116.77 178.48 29.800 23.719 40.761 +78 "R3" 73.020 103.31 46.082 11.420 17.249 4.2060 +79 "S3" 148.58 74.828 46.145 30.098 17.923 3.6411 +80 "T3" 92.676 106.61 179.17 15.102 16.455 41.548 +81 "U3" 89.067 149.36 56.522 16.816 29.880 6.2892 +82 "V3" 104.27 103.98 177.68 19.054 17.886 40.635 +83 "W3" 122.27 64.970 44.965 21.160 13.146 3.6418 +84 "X3" 190.80 157.08 167.65 56.827 44.647 36.033 +85 "Y3" 55.033 94.759 44.077 7.3224 13.350 4.3645 +86 "Z3" 157.08 85.576 87.558 34.447 20.515 11.595 +87 "2A3" 79.250 88.578 159.52 10.795 11.448 32.464 +88 "2B3" 108.15 127.71 55.172 20.617 25.691 5.5795 +89 "2C3" 78.102 75.847 150.05 11.126 10.174 28.914 +90 "2D3" 202.83 194.20 199.16 68.724 66.102 56.410 +91 "A4" 105.09 86.729 157.14 19.671 15.554 33.919 +92 "B4" 99.696 102.26 43.923 17.501 19.753 3.8498 +93 "C4" 107.26 130.81 190.72 21.509 25.734 51.674 +94 "D4" 178.30 141.51 75.719 51.958 42.451 9.1213 +95 "E4" 86.201 111.97 176.39 14.112 17.806 42.697 +96 "F4" 192.41 193.92 143.50 61.487 65.884 27.427 +97 "G4" 161.20 95.317 155.94 38.420 23.239 29.457 +98 "H4" 74.863 77.945 149.59 9.8759 9.7311 29.126 +99 "I4" 207.61 208.23 184.16 75.793 79.718 46.695 +100 "J4" 70.931 101.90 131.71 10.595 15.480 24.653 +101 "K4" 147.01 94.545 162.80 32.187 21.331 32.814 +102 "L4" 81.586 103.83 104.84 13.777 17.753 16.663 +103 "M4" 141.06 69.848 45.247 27.339 16.027 3.5603 +104 "N4" 90.494 151.07 150.65 16.922 28.995 29.336 +105 "O4" 55.294 41.016 63.313 6.3066 4.7610 6.9921 +106 "P4" 111.84 140.47 103.22 22.390 29.210 15.592 +107 "Q4" 144.45 93.249 162.31 30.657 20.369 32.268 +108 "R4" 105.31 104.82 101.31 19.152 19.807 15.592 +109 "S4" 79.325 137.68 48.973 13.948 25.671 5.2122 +110 "T4" 84.189 150.82 120.01 14.991 27.898 19.745 +111 "U4" 81.413 52.379 93.432 11.486 7.6381 12.484 +112 "V4" 76.459 77.531 42.048 10.749 11.899 3.2945 +113 "W4" 211.28 212.44 213.00 77.699 80.782 67.995 +114 "X4" 125.79 102.06 67.469 24.430 21.610 7.1800 +115 "Y4" 36.736 36.340 46.306 3.2104 3.1999 4.2513 +116 "Z4" 83.114 150.29 61.891 14.450 27.763 8.5197 +117 "2A4" 117.71 90.574 160.37 21.679 16.235 32.574 +118 "2B4" 89.463 153.87 72.494 15.737 29.267 10.078 +119 "2C4" 42.498 47.832 65.570 3.9226 4.4418 7.5674 +120 "2D4" 115.91 156.34 101.73 24.022 34.375 15.022 +121 "A5" 100.43 57.576 43.875 16.920 10.945 3.6233 +122 "B5" 139.57 140.52 191.37 32.876 32.373 51.547 +123 "C5" 106.24 157.82 63.346 23.454 37.144 7.5202 +124 "D5" 120.63 119.68 128.56 24.762 25.266 23.702 +125 "E5" 144.32 70.530 44.643 29.192 16.958 3.5359 +126 "F5" 112.12 164.88 139.23 23.640 37.186 26.447 +127 "G5" 103.37 136.87 47.413 20.387 28.842 4.7028 +128 "H5" 36.251 41.780 35.395 3.3636 4.0809 2.6833 +129 "I5" 111.24 162.80 164.26 23.272 35.820 35.198 +130 "J5" 143.56 87.562 156.55 30.642 19.573 30.103 +131 "K5" 109.54 163.06 164.19 22.753 35.416 35.064 +132 "L5" 79.627 52.133 45.354 11.209 7.8786 3.5144 +133 "M5" 92.456 152.33 153.19 17.513 29.721 30.234 +134 "N5" 34.714 33.013 32.281 2.9935 2.9559 2.2837 +135 "O5" 166.35 175.94 163.99 44.139 49.035 35.423 +136 "P5" 89.669 79.549 47.144 14.200 13.959 3.6761 +137 "Q5" 191.24 182.85 188.48 59.021 56.831 48.262 +138 "R5" 51.675 70.899 41.770 6.3401 9.2262 3.4989 +139 "S5" 170.53 177.54 173.76 45.700 49.818 40.124 +140 "T5" 63.890 93.942 45.687 9.3142 14.437 4.0636 +141 "U5" 30.168 29.299 28.940 2.3535 2.3975 1.9290 +142 "V5" 133.08 133.14 122.05 27.766 28.925 20.091 +143 "W5" 36.054 32.923 33.276 3.0887 2.9300 2.3596 +144 "X5" 61.314 111.77 45.755 8.7239 16.803 5.0276 +145 "Y5" 203.39 209.40 208.06 70.161 75.882 63.247 +146 "Z5" 76.353 77.670 109.77 11.191 11.244 16.654 +147 "2A5" 193.86 202.18 186.73 62.394 68.771 47.096 +148 "2B5" 84.630 73.965 145.61 12.640 10.459 27.333 +149 "2C5" 68.392 129.05 45.336 11.160 21.761 5.5099 +150 "2D5" 210.46 210.49 195.89 77.413 80.592 53.936 +151 "A6" 156.79 90.614 148.03 37.703 22.453 27.499 +152 "B6" 88.481 111.82 178.46 14.943 18.301 44.058 +153 "C6" 167.90 108.82 66.983 44.282 30.956 7.9185 +154 "D6" 66.578 110.85 54.360 10.440 18.144 6.5076 +155 "E6" 148.31 87.735 154.80 32.892 20.486 29.274 +156 "F6" 93.611 155.13 115.73 17.819 31.263 19.184 +157 "G6" 40.190 39.280 58.763 3.7468 3.6058 6.3752 +158 "H6" 170.89 152.59 147.19 45.907 41.132 28.818 +159 "I6" 46.469 44.545 75.326 4.4472 4.1158 9.1204 +160 "J6" 102.48 151.18 180.03 20.388 31.549 44.358 +161 "K6" 30.872 30.164 29.516 2.3970 2.4515 1.9961 +162 "L6" 83.294 137.00 98.315 14.323 24.343 14.536 +163 "M6" 30.722 30.150 29.446 2.3623 2.4293 1.9541 +164 "N6" 163.74 151.67 194.83 41.190 36.767 50.714 +165 "O6" 199.83 203.65 49.970 62.357 69.847 6.3069 +166 "P6" 77.512 86.873 159.07 10.124 10.811 31.915 +167 "Q6" 200.99 194.31 190.45 67.127 65.762 49.352 +168 "R6" 165.39 100.99 154.68 39.128 23.959 27.822 +169 "S6" 69.496 98.026 61.986 10.413 15.222 6.7952 +170 "T6" 167.68 124.93 146.98 41.195 30.074 26.292 +171 "U6" 62.706 68.483 60.211 8.4099 9.5591 6.5834 +172 "V6" 174.63 108.06 166.14 43.942 26.976 32.439 +173 "W6" 138.60 174.02 106.27 33.397 44.263 15.513 +174 "X6" 192.12 161.59 197.05 56.629 45.672 50.137 +175 "Y6" 71.207 70.503 63.173 10.198 10.583 6.9283 +176 "Z6" 171.42 121.85 182.26 42.782 29.822 40.386 +177 "2A6" 193.77 197.98 207.14 61.567 65.013 61.274 +178 "2B6" 117.80 82.965 151.94 21.335 15.115 28.916 +179 "2C6" 36.305 39.517 34.462 3.2203 3.7212 2.6005 +180 "2D6" 152.48 145.44 148.89 35.799 34.854 29.422 +181 "A7" 93.637 153.35 73.710 19.123 33.078 10.667 +182 "B7" 83.277 73.755 144.52 12.915 10.831 28.225 +183 "C7" 206.85 206.70 197.33 77.518 80.587 57.622 +184 "D7" 77.454 73.349 146.72 11.348 10.154 28.703 +185 "E7" 70.809 132.64 47.023 12.442 24.254 5.6475 +186 "F7" 91.049 88.345 163.10 15.345 13.969 34.910 +187 "G7" 177.87 190.87 53.018 52.703 61.988 5.9513 +188 "H7" 75.960 87.720 159.98 9.9056 10.888 32.881 +189 "I7" 199.48 192.77 181.55 67.471 66.483 44.705 +190 "J7" 64.713 68.090 67.610 8.8426 9.6268 8.1730 +191 "K7" 193.08 175.48 139.54 61.925 56.855 24.968 +192 "L7" 75.430 87.876 159.79 9.6349 10.726 32.427 +193 "M7" 133.24 173.17 56.742 32.435 45.157 6.1480 +194 "N7" 148.49 75.098 46.216 30.427 18.146 3.6270 +195 "O7" 97.134 97.177 86.559 16.928 17.695 11.911 +196 "P7" 191.20 160.30 54.685 56.094 48.894 4.9467 +197 "Q7" 80.068 80.251 125.32 11.934 11.778 20.573 +198 "R7" 83.368 147.19 55.358 15.285 28.434 6.3346 +199 "S7" 37.747 44.719 36.907 3.5054 4.3615 2.7830 +200 "T7" 146.52 175.26 205.50 35.099 44.589 58.771 +201 "U7" 133.97 82.941 152.98 26.155 17.005 28.079 +202 "V7" 63.182 103.22 97.125 8.9086 14.924 14.071 +203 "W7" 144.22 147.07 76.384 30.611 33.536 8.6858 +204 "X7" 212.78 213.19 211.89 79.113 81.784 66.503 +205 "Y7" 77.896 86.298 158.37 10.240 10.764 31.229 +206 "Z7" 71.313 133.52 47.389 11.976 23.218 5.4228 +207 "2A7" 75.926 78.650 151.98 9.9976 9.7574 28.929 +208 "2B7" 118.08 168.98 98.781 25.572 39.297 14.262 +209 "2C7" 207.34 198.34 43.623 66.257 69.908 5.8960 +210 "2D7" 92.639 108.26 179.66 14.893 16.603 41.626 +211 "A8" 69.904 137.36 58.325 12.100 24.359 8.4071 +212 "B8" 167.09 144.55 49.599 42.436 39.900 4.7260 +213 "C8" 111.10 78.672 121.83 20.574 15.216 20.136 +214 "D8" 74.340 141.34 56.829 12.701 25.255 8.1803 +215 "E8" 104.13 74.055 141.65 18.324 13.039 26.409 +216 "F8" 90.075 154.61 90.911 16.724 30.035 13.212 +217 "G8" 36.341 33.896 36.868 3.3200 3.1831 3.0291 +218 "H8" 101.65 159.66 134.07 20.304 33.570 24.443 +219 "I8" 34.216 33.499 37.712 2.9169 2.9009 3.0168 +220 "J8" 174.41 165.56 173.38 48.038 46.099 39.891 +221 "K8" 46.252 66.300 42.397 5.2241 8.0427 3.5985 +222 "L8" 152.69 184.12 182.69 38.619 50.368 44.407 +223 "M8" 30.240 29.863 28.939 2.3428 2.3959 1.9273 +224 "N8" 35.593 35.467 34.190 3.1956 3.3116 2.6415 +225 "O8" 71.728 71.553 70.937 10.494 10.847 8.8081 +226 "P8" 115.92 116.10 114.68 22.233 23.005 18.548 +227 "Q8" 159.85 160.38 159.13 39.317 40.778 33.056 +228 "R8" 196.60 197.21 197.12 63.147 65.480 53.862 +229 "S8" 137.57 112.53 140.33 28.252 23.514 24.400 +230 "T8" 80.940 142.13 50.952 14.520 26.909 5.4756 +231 "U8" 99.365 133.93 196.43 18.057 24.054 51.817 +232 "V8" 30.957 30.566 29.813 2.3402 2.3911 1.9209 +233 "W8" 212.09 210.69 210.55 77.838 79.255 64.883 +234 "X8" 90.920 71.799 46.751 14.232 12.342 3.5677 +235 "Y8" 137.72 177.30 175.40 31.451 43.594 39.472 +236 "Z8" 39.524 49.911 38.685 3.8429 5.0881 3.0661 +237 "2A8" 130.39 176.13 127.05 27.844 41.491 21.140 +238 "2B8" 31.904 31.437 30.690 2.4921 2.5648 2.0613 +239 "2C8" 149.77 158.18 196.00 34.635 36.777 50.964 +240 "2D8" 30.719 29.824 29.600 2.3436 2.3905 1.9440 +241 "A9" 160.64 188.72 135.75 46.811 59.109 25.406 +242 "B9" 151.09 113.48 161.82 35.695 26.905 33.928 +243 "C9" 56.378 101.12 44.028 8.0578 15.313 4.8058 +244 "D9" 200.86 192.61 183.06 70.562 68.540 46.575 +245 "E9" 77.639 89.149 161.20 10.633 11.656 33.787 +246 "F9" 183.43 148.52 132.23 54.113 43.360 23.933 +247 "G9" 53.868 83.869 77.703 7.1200 11.358 10.328 +248 "H9" 144.68 93.693 163.06 31.237 20.786 32.756 +249 "I9" 80.625 147.05 117.46 14.469 27.174 19.553 +250 "J9" 82.612 53.093 45.342 11.813 8.1727 3.4750 +251 "K9" 179.05 178.11 205.03 51.613 51.265 59.093 +252 "L9" 68.256 128.21 45.397 11.232 21.889 5.3482 +253 "M9" 30.122 29.559 28.786 2.3389 2.3932 1.9205 +254 "N9" 44.132 44.030 43.113 4.6543 4.8363 3.9004 +255 "O9" 77.603 77.496 77.212 11.973 12.444 10.082 +256 "P9" 123.38 123.35 123.35 24.548 25.410 20.720 +257 "Q9" 167.61 168.12 167.11 43.270 44.842 36.215 +258 "R9" 202.61 204.17 205.53 68.113 71.034 59.864 +259 "S9" 152.34 81.269 59.657 31.468 18.903 5.4734 +260 "T9" 36.525 39.233 37.120 3.2297 3.6435 2.9170 +261 "U9" 147.79 112.59 105.57 31.779 25.042 15.321 +262 "V9" 128.85 175.42 85.449 30.098 43.673 10.856 +263 "W9" 202.12 182.11 203.04 65.360 57.273 55.175 +264 "X9" 58.841 111.22 46.014 7.8261 15.682 5.0934 +265 "Y9" 150.27 74.574 46.780 30.151 17.603 3.5424 +266 "Z9" 91.373 72.814 142.15 14.169 10.872 25.545 +267 "2A9" 178.42 178.87 165.68 49.740 51.961 35.295 +268 "2B9" 110.21 82.066 150.83 19.293 14.167 28.533 +269 "2C9" 115.57 141.00 82.227 23.305 29.469 10.465 +270 "2D9" 120.44 87.308 156.62 22.420 16.254 30.792 +271 "A10" 54.278 98.104 59.100 7.4766 14.316 6.7672 +272 "B10" 141.49 142.92 50.130 30.693 34.185 4.8132 +273 "C10" 69.545 135.98 93.417 11.568 23.235 13.773 +274 "D10" 30.772 30.009 29.471 2.4307 2.4999 2.0171 +275 "E10" 140.52 89.479 159.03 30.140 19.949 31.751 +276 "F10" 88.149 135.62 165.23 15.810 25.353 37.521 +277 "G10" 30.508 30.075 29.389 2.4272 2.4936 1.9887 +278 "H10" 75.794 144.13 86.030 12.549 25.096 11.562 +279 "I10" 29.881 29.286 28.915 2.3402 2.3788 1.9223 +280 "J10" 78.427 139.08 135.09 13.387 24.235 23.958 +281 "K10" 127.69 103.24 52.122 25.478 22.853 4.3681 +282 "L10" 47.518 38.484 37.887 5.0366 4.2550 2.8902 +283 "M10" 30.202 29.466 28.978 2.3374 2.3915 1.9194 +284 "N10" 50.671 50.438 49.901 5.8942 6.1054 4.9143 +285 "O10" 84.087 84.218 84.130 13.462 14.013 11.428 +286 "P10" 130.92 131.27 131.19 27.055 28.014 23.007 +287 "Q10" 174.24 174.94 173.31 47.406 49.169 39.386 +288 "R10" 208.46 209.75 212.17 73.974 77.043 65.729 +289 "S10" 61.440 61.759 68.112 7.8358 8.0794 7.9176 +290 "T10" 189.59 154.63 195.61 54.395 42.563 48.165 +291 "U10" 70.065 139.76 58.155 11.113 22.841 7.7084 +292 "V10" 34.382 38.877 37.374 2.9394 3.4387 2.9247 +293 "W10" 81.185 148.91 88.683 13.284 25.973 11.867 +294 "X10" 31.337 30.706 30.647 2.4768 2.5120 2.1182 +295 "Y10" 132.10 124.54 122.36 27.102 26.481 19.829 +296 "Z10" 128.86 77.259 44.848 23.978 16.698 3.6586 +297 "2A10" 121.07 144.71 145.24 24.659 30.178 27.108 +298 "2B10" 91.404 54.498 76.524 13.618 8.1445 8.4106 +299 "2C10" 122.45 129.19 129.52 24.412 26.496 22.533 +300 "2D10" 52.091 43.712 85.349 5.2897 4.2252 10.803 +301 "A11" 95.121 56.945 109.13 15.662 9.9371 16.757 +302 "B11" 49.247 84.978 41.595 6.3528 11.756 4.1276 +303 "C11" 201.38 188.28 201.57 70.247 65.054 58.834 +304 "D11" 165.99 106.71 48.883 42.904 30.283 4.3741 +305 "E11" 142.45 151.87 140.77 33.675 37.292 27.259 +306 "F11" 59.895 43.373 70.686 7.3260 5.3398 8.4321 +307 "G11" 185.60 179.80 175.52 56.748 56.026 41.441 +308 "H11" 62.810 62.001 39.464 8.1585 8.7147 3.0001 +309 "I11" 182.38 181.99 177.01 54.512 56.195 42.466 +310 "J11" 44.613 62.579 56.523 4.9736 7.2275 6.1574 +311 "K11" 177.26 171.26 154.02 50.413 50.352 29.675 +312 "L11" 81.706 58.921 119.57 11.783 8.3671 18.993 +313 "M11" 30.648 29.769 29.464 2.4004 2.4632 1.9865 +314 "N11" 56.534 56.324 55.689 7.0502 7.2979 5.9348 +315 "O11" 89.911 89.936 88.980 15.157 15.663 12.643 +316 "P11" 140.77 141.41 140.88 30.809 31.935 26.037 +317 "Q11" 179.84 180.21 178.58 51.029 52.827 42.179 +318 "R11" 212.60 213.84 215.53 78.892 82.077 69.152 +319 "S11" 66.493 66.184 65.558 9.0391 9.3614 7.5795 +320 "T11" 187.32 160.61 146.99 54.688 46.067 27.270 +321 "U11" 59.842 44.929 41.517 7.0672 5.5203 3.1542 +322 "V11" 100.71 151.70 177.40 19.018 30.251 40.808 +323 "W11" 32.433 32.983 31.555 2.6438 2.7813 2.1741 +324 "X11" 103.41 161.56 150.03 20.294 33.254 28.954 +325 "Y11" 49.930 46.756 84.028 4.7917 4.3367 10.461 +326 "Z11" 157.24 187.57 185.20 39.678 51.335 44.730 +327 "2A11" 69.840 130.51 46.639 11.397 22.075 5.4606 +328 "2B11" 164.73 190.77 189.92 43.396 54.386 47.692 +329 "2C11" 67.660 57.565 50.639 9.0264 8.0855 4.5632 +330 "2D11" 146.88 73.255 46.894 29.263 17.239 3.6542 +331 "A12" 149.18 183.06 84.464 42.435 55.238 11.960 +332 "B12" 72.446 71.794 146.17 10.244 9.5241 28.550 +333 "C12" 111.58 163.80 82.344 25.557 39.490 11.397 +334 "D12" 67.115 62.023 67.669 9.5983 9.1448 8.3283 +335 "E12" 202.25 206.59 144.16 71.285 77.444 27.463 +336 "F12" 142.52 142.52 149.46 32.592 33.399 30.058 +337 "G12" 52.218 46.843 96.005 5.1430 4.3541 13.182 +338 "H12" 95.301 157.62 128.66 18.517 32.087 22.562 +339 "I12" 58.804 42.199 45.333 6.9977 5.1440 3.8014 +340 "J12" 201.67 207.01 112.57 69.246 76.042 17.844 +341 "K12" 76.878 56.433 113.86 10.642 7.6407 17.593 +342 "L12" 110.43 164.87 121.89 21.927 35.477 19.681 +343 "M12" 31.073 30.502 29.828 2.4287 2.4921 1.9949 +344 "N12" 60.863 60.999 60.221 7.9937 8.3172 6.7360 +345 "O12" 97.436 97.414 96.425 17.120 17.761 14.285 +346 "P12" 146.96 147.76 147.68 33.242 34.486 28.221 +347 "Q12" 186.04 186.49 184.52 55.136 57.000 45.303 +348 "R12" 217.03 217.69 217.80 84.047 87.070 71.496 +349 "S12" 173.81 166.67 164.48 46.799 45.618 34.284 +350 "T12" 61.998 59.133 126.43 6.6921 6.0185 19.773 +351 "U12" 133.08 178.53 107.01 31.583 45.365 15.646 +352 "V12" 159.59 92.307 67.569 35.975 22.808 7.0470 +353 "W12" 92.823 93.091 102.67 15.632 16.004 15.333 +354 "X12" 153.31 79.910 48.385 32.188 19.569 3.7849 +355 "Y12" 76.169 77.765 152.48 9.9981 9.6287 28.171 +356 "Z12" 80.867 145.82 55.209 14.429 27.348 6.4901 +357 "2A12" 88.726 84.091 155.13 13.822 12.446 29.936 +358 "2B12" 201.37 208.14 195.53 68.261 74.431 52.067 +359 "2C12" 32.004 31.705 30.813 2.4685 2.5621 2.0287 +360 "2D12" 135.53 145.08 187.78 28.798 30.974 45.549 +361 "A13" 86.415 69.301 138.07 14.129 10.884 26.286 +362 "B13" 104.58 136.42 46.559 21.280 29.662 4.6515 +363 "C13" 147.82 79.114 100.32 32.064 17.966 13.604 +364 "D13" 75.334 85.157 157.26 9.9611 10.733 32.277 +365 "E13" 178.81 179.96 148.24 51.845 54.927 28.181 +366 "F13" 55.482 72.327 100.16 6.3441 8.5421 15.068 +367 "G13" 200.09 199.75 184.43 68.699 71.452 46.387 +368 "H13" 76.688 84.710 151.41 10.374 10.902 29.169 +369 "I13" 129.73 107.35 52.022 26.203 23.997 4.3858 +370 "J13" 119.03 160.66 198.42 25.753 36.554 54.373 +371 "K13" 56.473 50.032 106.16 5.9068 4.9157 15.287 +372 "L13" 153.18 106.56 46.936 35.348 27.270 4.1933 +373 "M13" 32.264 31.978 31.289 2.6154 2.7053 2.1626 +374 "N13" 66.470 66.520 66.246 9.3637 9.6843 7.8391 +375 "O13" 105.28 105.86 104.76 19.359 20.106 16.147 +376 "P13" 153.75 154.63 154.12 36.624 37.957 30.671 +377 "Q13" 192.03 192.25 191.27 59.859 61.861 49.702 +378 "R13" 221.68 221.89 221.96 89.957 93.025 75.604 +379 "S13" 104.20 75.856 145.33 17.613 12.665 26.369 +380 "T13" 121.87 124.18 72.370 22.969 25.114 7.7873 +381 "U13" 91.392 55.886 72.021 13.623 8.3610 7.6135 +382 "V13" 193.01 176.53 161.70 59.661 54.433 33.140 +383 "W13" 97.047 61.496 44.638 15.045 10.609 3.4373 +384 "X13" 124.18 171.27 172.48 26.676 39.190 37.659 +385 "Y13" 100.95 103.55 45.932 16.770 18.831 3.7976 +386 "Z13" 98.719 76.722 108.03 16.243 13.004 15.620 +387 "2A13" 193.99 204.68 205.71 62.079 69.145 59.254 +388 "2B13" 77.619 94.368 167.50 9.8300 11.508 34.315 +389 "2C13" 91.512 53.191 50.701 13.378 8.4024 4.1065 +390 "2D13" 76.609 104.98 135.45 11.706 16.228 24.708 +391 "A14" 129.84 79.131 147.61 27.260 17.709 28.446 +392 "B14" 74.731 86.884 158.53 10.007 11.116 33.309 +393 "C14" 178.45 194.65 198.02 55.170 63.826 56.969 +394 "D14" 122.80 65.789 71.805 22.474 12.791 7.8220 +395 "E14" 99.529 101.15 66.691 17.833 19.340 7.6068 +396 "F14" 133.73 68.160 43.803 25.508 15.387 3.5019 +397 "G14" 130.31 174.28 137.87 28.674 42.244 25.294 +398 "H14" 110.49 77.413 145.63 20.013 14.167 27.201 +399 "I14" 30.999 29.764 29.587 2.4079 2.4331 1.9867 +400 "J14" 120.14 114.13 178.99 23.527 21.066 41.374 +401 "K14" 128.29 64.544 74.117 23.203 12.509 8.0121 +402 "L14" 176.70 157.34 183.40 48.486 42.511 43.112 +403 "M14" 59.777 105.00 45.141 8.6031 15.926 4.6200 +404 "N14" 182.00 181.11 190.30 53.107 53.884 48.977 +405 "O14" 42.651 40.749 62.042 3.9836 3.7404 6.5852 +406 "P14" 151.32 150.31 182.91 35.517 35.068 43.001 +407 "Q14" 162.51 94.932 125.82 37.782 22.314 19.042 +408 "R14" 99.745 94.301 93.467 17.467 17.105 13.104 +409 "S14" 107.25 159.78 58.090 22.370 35.508 5.9931 +410 "T14" 128.01 72.369 117.84 23.886 13.985 16.868 +411 "U14" 107.76 101.18 90.766 19.591 19.252 12.172 +412 "V14" 204.14 190.16 48.644 63.345 63.812 5.6645 +413 "W14" 82.597 65.626 44.970 12.028 10.481 3.3856 +414 "X14" 166.39 166.20 175.82 42.635 43.420 39.912 +415 "Y14" 100.69 152.17 51.384 19.856 32.192 5.1431 +416 "Z14" 91.650 100.20 90.746 15.570 17.641 12.711 +417 "2A14" 143.62 91.243 162.04 29.733 19.495 31.105 +418 "2B14" 214.71 215.34 214.31 81.209 84.285 67.959 +419 "2C14" 101.32 87.875 161.74 16.972 13.897 32.504 +420 "2D14" 105.18 138.75 68.497 20.262 27.906 7.7177 +421 "A15" 124.84 68.758 114.78 24.922 14.319 17.652 +422 "B15" 99.929 150.22 167.53 20.394 32.266 39.177 +423 "C15" 121.25 165.78 57.133 28.847 42.042 6.3345 +424 "D15" 129.49 121.04 130.58 27.579 26.553 23.681 +425 "E15" 161.27 95.254 123.97 38.874 23.290 19.357 +426 "F15" 148.20 174.03 142.22 36.703 46.352 27.027 +427 "G15" 150.41 98.923 167.42 34.061 22.803 34.531 +428 "H15" 75.180 91.615 158.04 10.113 11.921 31.879 +429 "I15" 196.22 179.25 172.32 64.423 58.008 39.281 +430 "J15" 66.558 62.105 60.696 9.4542 9.1717 6.7120 +431 "K15" 174.25 177.65 112.40 48.073 52.062 16.154 +432 "L15" 116.33 112.29 162.02 22.225 20.657 33.169 +433 "M15" 133.68 171.46 73.038 32.410 43.840 8.6168 +434 "N15" 102.47 146.49 198.15 19.932 29.141 53.896 +435 "O15" 64.715 46.574 43.032 8.2354 6.1612 3.2448 +436 "P15" 105.91 159.08 164.78 21.186 33.689 34.860 +437 "Q15" 34.379 33.754 36.003 2.8839 2.9372 2.7235 +438 "R15" 102.62 61.271 119.89 16.647 10.677 18.389 +439 "S15" 159.62 86.224 48.021 35.874 22.454 3.7685 +440 "T15" 95.611 158.57 127.45 18.024 31.495 21.231 +441 "U15" 133.03 87.140 157.87 26.027 17.635 30.172 +442 "V15" 48.894 77.368 43.484 5.7623 9.6302 3.8733 +443 "W15" 182.54 191.20 178.40 53.522 58.991 41.376 +444 "X15" 126.00 95.308 166.74 23.991 17.693 34.060 +445 "Y15" 38.376 39.986 33.590 3.5595 3.8688 2.3978 +446 "Z15" 148.30 148.94 147.37 34.055 35.265 28.241 +447 "2A15" 146.55 75.055 68.429 29.379 16.826 7.3609 +448 "2B15" 71.706 70.645 144.63 9.2107 8.5579 25.691 +449 "2C15" 133.02 80.816 44.452 25.707 18.129 3.6532 +450 "2D15" 82.777 113.54 117.52 13.875 19.568 19.948 +451 "A16" 147.43 75.104 45.417 32.441 19.582 3.7464 +452 "B16" 162.22 145.05 108.87 43.738 40.362 16.554 +453 "C16" 43.273 69.681 61.261 4.9159 8.3065 7.2559 +454 "D16" 154.15 106.72 65.606 37.197 27.832 7.4910 +455 "E16" 149.19 148.83 193.98 36.691 35.876 51.695 +456 "F16" 157.80 111.38 47.573 38.836 30.036 4.3338 +457 "G16" 100.61 79.449 149.13 17.555 13.363 28.888 +458 "H16" 206.92 207.61 211.44 75.466 77.836 67.216 +459 "I16" 97.895 82.272 66.348 16.954 15.112 7.2992 +460 "J16" 172.80 178.46 82.595 47.072 52.200 10.669 +461 "K16" 183.90 191.17 190.75 55.962 60.759 50.287 +462 "L16" 75.048 76.021 151.02 10.165 9.7715 28.705 +463 "M16" 159.42 88.282 47.938 36.859 23.500 3.8297 +464 "N16" 133.24 176.09 150.50 29.735 43.076 29.229 +465 "O16" 59.749 48.251 40.198 7.3545 6.2503 2.9745 +466 "P16" 171.06 168.69 161.58 46.114 46.965 33.568 +467 "Q16" 53.260 54.841 37.700 6.2218 6.8107 2.7776 +468 "R16" 147.03 76.735 66.424 29.663 17.214 6.8286 +469 "S16" 63.206 78.809 107.93 8.0381 10.138 16.410 +470 "T16" 150.22 77.352 47.226 31.088 18.734 3.6263 +471 "U16" 97.824 159.49 134.64 18.911 32.215 23.899 +472 "V16" 133.39 81.567 151.23 26.145 16.883 27.363 +473 "W16" 155.32 82.024 48.477 33.705 20.761 3.7986 +474 "X16" 81.301 147.86 56.013 14.361 27.487 7.1744 +475 "Y16" 141.53 112.75 178.08 29.882 22.982 39.138 +476 "Z16" 31.556 30.196 30.075 2.4233 2.4412 1.9648 +477 "2A16" 166.04 149.78 129.15 42.519 39.188 21.270 +478 "2B16" 53.939 48.402 100.70 5.2349 4.4461 13.823 +479 "2C16" 152.96 83.435 68.500 32.492 19.465 7.0806 +480 "2D16" 141.97 181.00 131.63 33.454 46.863 22.481 +481 "A17" 93.002 152.57 112.99 18.355 31.722 19.048 +482 "B17" 48.562 44.595 81.595 4.8626 4.2833 10.526 +483 "C17" 155.24 137.12 108.13 39.631 36.092 16.781 +484 "D17" 37.723 54.820 48.270 3.8471 5.8319 4.8962 +485 "E17" 163.04 158.68 133.73 43.491 44.349 22.904 +486 "F17" 155.10 81.151 47.477 35.028 21.444 3.8305 +487 "G17" 119.76 108.26 175.73 23.826 20.302 40.464 +488 "H17" 155.83 188.69 108.40 44.211 56.679 16.435 +489 "I17" 54.125 49.417 43.252 6.5115 6.2807 3.6004 +490 "J17" 146.89 182.65 155.76 35.464 48.530 31.500 +491 "K17" 148.71 77.345 50.119 31.217 18.833 4.2081 +492 "L17" 53.925 41.854 39.291 6.1796 5.0138 3.0160 +493 "M17" 105.46 156.83 167.45 21.355 33.511 36.981 +494 "N17" 149.16 79.222 103.08 31.382 17.339 13.539 +495 "O17" 109.98 107.89 138.78 20.515 20.076 24.934 +496 "P17" 151.99 78.765 47.620 32.143 19.447 3.7592 +497 "Q17" 195.13 169.06 200.08 60.501 50.532 52.708 +498 "R17" 73.599 136.55 49.271 12.657 24.420 5.6873 +499 "S17" 37.757 33.718 34.938 3.4355 3.1639 2.5372 +500 "T17" 132.61 142.77 197.68 28.192 29.771 51.322 +501 "U17" 181.82 145.93 103.48 52.660 42.651 15.019 +502 "V17" 204.10 203.91 210.35 69.823 71.393 63.731 +503 "W17" 175.82 179.36 52.229 44.995 50.413 5.2421 +504 "X17" 155.69 156.50 143.88 37.401 38.967 26.702 +505 "Y17" 65.731 44.495 80.654 8.0339 5.5483 9.9052 +506 "Z17" 67.930 138.21 88.916 10.382 21.829 11.599 +507 "2A17" 156.40 87.866 68.881 34.325 21.131 7.2263 +508 "2B17" 68.870 68.990 41.254 9.1863 9.9839 3.1512 +509 "2C17" 209.60 202.66 207.60 75.534 73.388 61.922 +510 "2D17" 108.97 87.062 152.98 19.258 14.916 29.290 +511 "A18" 200.70 204.40 197.90 74.089 78.770 59.424 +512 "B18" 164.93 117.44 177.68 42.903 30.204 40.715 +513 "C18" 61.227 72.827 56.013 8.7363 10.837 6.0872 +514 "D18" 204.51 199.19 195.95 75.509 74.636 56.066 +515 "E18" 73.692 73.322 148.06 10.413 9.8011 28.727 +516 "F18" 68.313 128.24 45.392 11.836 22.861 5.4226 +517 "G18" 131.14 85.288 152.52 26.954 18.177 29.358 +518 "H18" 89.609 153.68 93.128 16.220 29.699 13.154 +519 "I18" 30.179 29.676 28.922 2.3647 2.3980 1.9090 +520 "J18" 208.65 210.69 209.48 77.786 81.283 65.463 +521 "K18" 88.863 70.346 63.498 14.363 11.898 6.7644 +522 "L18" 197.92 177.16 54.602 60.378 57.128 5.2726 +523 "M18" 143.55 91.470 162.00 30.554 20.123 31.743 +524 "N18" 121.99 131.52 122.44 24.748 27.645 20.451 +525 "O18" 172.04 115.00 91.328 44.929 31.003 12.389 +526 "P18" 81.187 74.923 148.64 11.881 10.425 27.990 +527 "Q18" 117.91 169.48 101.12 25.737 39.690 14.823 +528 "R18" 183.93 145.62 52.297 52.300 42.856 4.6545 +529 "S18" 55.452 105.38 65.438 7.2126 14.429 7.1944 +530 "T18" 211.11 208.92 210.90 77.679 78.425 65.193 +531 "U18" 177.41 124.39 134.00 47.084 32.209 22.319 +532 "V18" 53.506 90.891 78.889 6.6683 11.848 10.189 +533 "W18" 197.65 205.13 206.81 65.207 70.970 60.729 +534 "X18" 51.396 86.860 43.674 6.2806 11.330 4.1095 +535 "Y18" 193.58 175.18 113.92 60.571 56.044 16.070 +536 "Z18" 96.313 103.94 178.60 15.673 16.045 40.153 +537 "2A18" 168.53 106.08 128.73 41.178 25.901 19.845 +538 "2B18" 85.496 104.15 136.89 13.693 16.674 24.407 +539 "2C18" 208.09 210.26 179.31 74.223 78.952 41.733 +540 "2D18" 161.94 92.492 50.116 38.135 24.817 4.1395 +541 "A19" 156.71 112.54 101.12 39.239 29.094 15.479 +542 "B19" 42.513 58.501 40.536 4.7416 7.0454 3.4644 +543 "C19" 172.17 152.13 143.40 49.395 43.657 28.522 +544 "D19" 159.73 183.13 54.703 42.332 52.372 5.7052 +545 "E19" 119.21 105.48 95.518 24.242 22.424 14.026 +546 "F19" 30.235 29.764 29.269 2.4551 2.5226 2.0256 +547 "G19" 88.689 134.99 136.69 16.677 25.667 25.825 +548 "H19" 86.392 53.901 45.566 13.124 8.8453 3.5763 +549 "I19" 126.88 158.15 160.78 28.527 37.076 34.358 +550 "J19" 120.42 79.125 64.241 22.891 16.490 6.9749 +551 "K19" 108.34 160.80 164.56 22.666 35.279 35.631 +552 "L19" 49.327 39.952 38.592 5.4212 4.5484 2.9627 +553 "M19" 67.917 128.27 44.976 11.199 21.925 5.4425 +554 "N19" 127.84 62.080 45.945 22.708 12.897 3.6335 +555 "O19" 74.380 138.45 130.11 12.507 23.738 22.498 +556 "P19" 30.060 29.337 28.817 2.3442 2.3896 1.9267 +557 "Q19" 147.97 73.539 46.480 30.303 17.749 3.5777 +558 "R19" 75.153 76.608 151.15 10.104 9.7374 28.448 +559 "S19" 78.339 144.41 52.936 13.901 26.685 6.3873 +560 "T19" 31.312 30.556 30.767 2.4391 2.4780 2.0610 +561 "U19" 169.32 177.98 203.35 45.972 49.473 57.247 +562 "V19" 44.471 72.376 45.634 4.8275 8.3485 3.9886 +563 "W19" 199.02 205.39 55.979 63.154 70.855 7.5811 +564 "X19" 90.125 81.954 73.039 14.863 14.166 8.5770 +565 "Y19" 207.33 211.44 212.22 74.340 78.986 66.286 +566 "Z19" 182.95 126.85 175.69 49.996 33.344 36.894 +567 "2A19" 77.857 90.598 163.13 10.165 11.287 33.081 +568 "2B19" 202.16 204.23 49.052 62.642 69.515 6.2139 +569 "2C19" 162.94 96.440 68.740 38.429 24.741 7.3479 +570 "2D19" 83.952 84.116 160.97 12.944 12.283 32.608 +END_DATA diff --git a/scanin/CMP_Digital_Target-3.ti2 b/scanin/CMP_Digital_Target-3.ti2 new file mode 100644 index 0000000..e4b15e9 --- /dev/null +++ b/scanin/CMP_Digital_Target-3.ti2 @@ -0,0 +1,601 @@ +CTI2 + +DESCRIPTOR "Argyll Calibration Target chart information 2 for Christopher Metarie Digital Target 3" +ORIGINATOR "Argyll printtarg" +CREATED "Wed Sep 12 00:02:26 2007" +KEYWORD "TARGET_INSTRUMENT" +TARGET_INSTRUMENT "GretagMacbeth i1 Pro" +KEYWORD "ACCURATE_EXPECTED_VALUES" +ACCURATE_EXPECTED_VALUES "true" +KEYWORD "COLOR_REP" +COLOR_REP "RGB" +KEYWORD "STEPS_IN_PASS" +STEPS_IN_PASS "30" +KEYWORD "PASSES_IN_STRIPS2" +PASSES_IN_STRIPS2 "19" +KEYWORD "STRIP_INDEX_PATTERN" +STRIP_INDEX_PATTERN "0-9,@-9,@-9;1-999" +KEYWORD "PATCH_INDEX_PATTERN" +PATCH_INDEX_PATTERN "A-Z, 2-9" +KEYWORD "INDEX_ORDER" +INDEX_ORDER "PATCH_THEN_STRIP" + +KEYWORD "SAMPLE_LOC" +NUMBER_OF_FIELDS 8 +BEGIN_DATA_FORMAT +SAMPLE_ID SAMPLE_LOC RGB_R RGB_G RGB_B XYZ_X XYZ_Y XYZ_Z +END_DATA_FORMAT + +NUMBER_OF_SETS 570 +BEGIN_DATA +1 "A1" 106.60 73.896 140.50 19.991 14.120 27.886 +2 "B1" 101.22 157.76 91.298 19.926 34.054 14.005 +3 "C1" 56.474 54.712 116.20 6.2319 5.6339 19.078 +4 "D1" 142.23 143.96 106.67 32.785 35.198 16.672 +5 "E1" 161.58 92.303 143.82 38.996 22.658 25.805 +6 "F1" 90.405 96.497 94.153 16.011 17.612 14.561 +7 "G1" 163.39 98.124 88.178 39.496 24.997 12.003 +8 "H1" 63.278 55.370 115.21 7.4905 6.2468 18.358 +9 "I1" 71.385 133.64 49.363 11.987 23.286 6.5928 +10 "J1" 97.757 75.383 143.28 16.591 12.444 27.331 +11 "K1" 194.49 193.52 200.39 63.038 64.179 58.403 +12 "L1" 43.729 37.037 36.612 4.3513 3.8393 2.7750 +13 "M1" 128.36 143.53 178.51 27.386 30.873 42.527 +14 "N1" 136.71 176.12 173.90 31.789 44.281 40.439 +15 "O1" 190.25 190.03 173.26 59.453 61.985 40.335 +16 "P1" 139.89 69.074 45.054 26.783 15.713 3.5833 +17 "Q1" 34.433 40.188 37.667 3.0238 3.6843 3.0876 +18 "R1" 87.362 153.04 89.833 15.462 28.885 12.776 +19 "S1" 124.79 84.048 151.84 23.694 16.421 29.352 +20 "T1" 201.42 206.76 79.283 65.900 73.381 11.377 +21 "U1" 59.875 104.70 93.370 8.3333 15.036 13.749 +22 "V1" 205.39 208.60 159.63 72.416 77.985 33.423 +23 "W1" 91.572 136.12 167.03 16.393 25.254 38.122 +24 "X1" 30.336 29.306 28.957 2.3144 2.3581 1.9303 +25 "Y1" 132.60 110.17 107.91 27.102 23.276 16.813 +26 "Z1" 32.956 33.215 31.185 2.6994 2.8850 2.2332 +27 "2A1" 70.282 129.32 46.946 10.757 20.588 4.8216 +28 "2B1" 159.00 173.65 202.91 40.765 45.919 58.857 +29 "2C1" 121.19 88.150 161.84 22.864 16.381 33.839 +30 "2D1" 136.59 101.50 125.83 28.289 21.404 20.483 +31 "A2" 75.414 80.525 150.43 10.412 10.567 30.978 +32 "B2" 128.64 63.027 42.872 24.139 14.085 3.5857 +33 "C2" 101.62 116.40 166.26 19.473 21.752 38.376 +34 "D2" 129.62 78.772 146.55 26.280 16.991 28.035 +35 "E2" 164.20 144.75 82.589 42.573 39.671 9.6556 +36 "F2" 96.904 110.83 179.21 17.113 18.705 43.690 +37 "G2" 157.24 84.071 46.359 35.850 22.548 3.8554 +38 "H2" 84.439 70.424 140.26 13.037 10.392 26.425 +39 "I2" 81.661 147.44 58.864 14.946 28.262 8.1825 +40 "J2" 35.433 35.856 32.072 3.1780 3.3914 2.3047 +41 "K2" 150.66 144.08 140.58 35.880 35.178 26.683 +42 "L2" 158.35 93.379 154.74 36.434 22.147 28.386 +43 "M2" 100.38 93.492 99.897 17.689 17.022 15.072 +44 "N2" 158.93 93.968 95.921 36.396 23.022 13.623 +45 "O2" 102.60 137.21 171.09 19.884 26.988 39.544 +46 "P2" 74.932 50.703 44.902 10.294 7.4271 3.4839 +47 "Q2" 115.12 165.78 166.70 24.415 37.008 36.288 +48 "R2" 157.97 92.663 150.58 36.078 21.682 26.898 +49 "S2" 83.913 88.787 161.27 12.232 12.247 33.412 +50 "T2" 72.772 133.20 48.154 12.486 23.920 5.4357 +51 "U2" 155.64 177.45 175.23 38.913 47.091 40.794 +52 "V2" 65.311 50.797 44.712 8.3779 6.8387 3.7119 +53 "W2" 30.304 29.389 28.630 2.3401 2.3804 1.9157 +54 "X2" 98.383 112.57 76.501 17.501 20.678 9.7225 +55 "Y2" 196.95 176.56 81.174 60.324 56.490 9.7029 +56 "Z2" 106.87 76.461 64.020 18.340 14.257 6.9452 +57 "2A2" 149.29 180.57 55.756 39.051 50.700 6.0515 +58 "2B2" 46.850 72.093 42.887 5.3134 8.7205 3.7883 +59 "2C2" 126.21 86.097 104.74 24.040 16.842 14.641 +60 "2D2" 68.443 138.05 59.668 10.963 22.720 8.1563 +61 "A3" 40.703 34.668 43.170 3.2215 2.8069 3.1344 +62 "B3" 140.80 177.61 130.47 35.703 49.122 24.276 +63 "C3" 71.422 72.467 144.63 9.6710 9.2674 28.141 +64 "D3" 157.83 159.05 109.87 39.368 42.329 16.693 +65 "E3" 74.511 78.412 148.91 9.8448 9.8037 29.501 +66 "F3" 172.35 192.98 167.60 50.040 60.997 38.371 +67 "G3" 72.505 72.322 146.66 9.8731 9.2375 28.216 +68 "H3" 132.85 167.63 50.020 31.926 43.409 5.2962 +69 "I3" 99.822 132.27 193.48 18.889 24.530 52.235 +70 "J3" 158.78 88.817 87.144 36.271 22.167 11.952 +71 "K3" 146.32 156.61 192.38 34.281 37.060 50.573 +72 "L3" 30.978 30.641 29.826 2.4511 2.5353 2.0398 +73 "M3" 146.27 153.30 150.57 34.120 37.136 30.510 +74 "N3" 144.16 70.919 46.534 28.309 16.461 3.7229 +75 "O3" 85.091 72.947 144.27 12.851 10.508 27.052 +76 "P3" 122.91 131.12 67.881 24.532 27.910 7.4170 +77 "Q3" 140.27 116.77 178.48 29.800 23.719 40.761 +78 "R3" 73.020 103.31 46.082 11.420 17.249 4.2060 +79 "S3" 148.58 74.828 46.145 30.098 17.923 3.6411 +80 "T3" 92.676 106.61 179.17 15.102 16.455 41.548 +81 "U3" 89.067 149.36 56.522 16.816 29.880 6.2892 +82 "V3" 104.27 103.98 177.68 19.054 17.886 40.635 +83 "W3" 122.27 64.970 44.965 21.160 13.146 3.6418 +84 "X3" 190.80 157.08 167.65 56.827 44.647 36.033 +85 "Y3" 55.033 94.759 44.077 7.3224 13.350 4.3645 +86 "Z3" 157.08 85.576 87.558 34.447 20.515 11.595 +87 "2A3" 79.250 88.578 159.52 10.795 11.448 32.464 +88 "2B3" 108.15 127.71 55.172 20.617 25.691 5.5795 +89 "2C3" 78.102 75.847 150.05 11.126 10.174 28.914 +90 "2D3" 202.83 194.20 199.16 68.724 66.102 56.410 +91 "A4" 105.09 86.729 157.14 19.671 15.554 33.919 +92 "B4" 99.696 102.26 43.923 17.501 19.753 3.8498 +93 "C4" 107.26 130.81 190.72 21.509 25.734 51.674 +94 "D4" 178.30 141.51 75.719 51.958 42.451 9.1213 +95 "E4" 86.201 111.97 176.39 14.112 17.806 42.697 +96 "F4" 192.41 193.92 143.50 61.487 65.884 27.427 +97 "G4" 161.20 95.317 155.94 38.420 23.239 29.457 +98 "H4" 74.863 77.945 149.59 9.8759 9.7311 29.126 +99 "I4" 207.61 208.23 184.16 75.793 79.718 46.695 +100 "J4" 70.931 101.90 131.71 10.595 15.480 24.653 +101 "K4" 147.01 94.545 162.80 32.187 21.331 32.814 +102 "L4" 81.586 103.83 104.84 13.777 17.753 16.663 +103 "M4" 141.06 69.848 45.247 27.339 16.027 3.5603 +104 "N4" 90.494 151.07 150.65 16.922 28.995 29.336 +105 "O4" 55.294 41.016 63.313 6.3066 4.7610 6.9921 +106 "P4" 111.84 140.47 103.22 22.390 29.210 15.592 +107 "Q4" 144.45 93.249 162.31 30.657 20.369 32.268 +108 "R4" 105.31 104.82 101.31 19.152 19.807 15.592 +109 "S4" 79.325 137.68 48.973 13.948 25.671 5.2122 +110 "T4" 84.189 150.82 120.01 14.991 27.898 19.745 +111 "U4" 81.413 52.379 93.432 11.486 7.6381 12.484 +112 "V4" 76.459 77.531 42.048 10.749 11.899 3.2945 +113 "W4" 211.28 212.44 213.00 77.699 80.782 67.995 +114 "X4" 125.79 102.06 67.469 24.430 21.610 7.1800 +115 "Y4" 36.736 36.340 46.306 3.2104 3.1999 4.2513 +116 "Z4" 83.114 150.29 61.891 14.450 27.763 8.5197 +117 "2A4" 117.71 90.574 160.37 21.679 16.235 32.574 +118 "2B4" 89.463 153.87 72.494 15.737 29.267 10.078 +119 "2C4" 42.498 47.832 65.570 3.9226 4.4418 7.5674 +120 "2D4" 115.91 156.34 101.73 24.022 34.375 15.022 +121 "A5" 100.43 57.576 43.875 16.920 10.945 3.6233 +122 "B5" 139.57 140.52 191.37 32.876 32.373 51.547 +123 "C5" 106.24 157.82 63.346 23.454 37.144 7.5202 +124 "D5" 120.63 119.68 128.56 24.762 25.266 23.702 +125 "E5" 144.32 70.530 44.643 29.192 16.958 3.5359 +126 "F5" 112.12 164.88 139.23 23.640 37.186 26.447 +127 "G5" 103.37 136.87 47.413 20.387 28.842 4.7028 +128 "H5" 36.251 41.780 35.395 3.3636 4.0809 2.6833 +129 "I5" 111.24 162.80 164.26 23.272 35.820 35.198 +130 "J5" 143.56 87.562 156.55 30.642 19.573 30.103 +131 "K5" 109.54 163.06 164.19 22.753 35.416 35.064 +132 "L5" 79.627 52.133 45.354 11.209 7.8786 3.5144 +133 "M5" 92.456 152.33 153.19 17.513 29.721 30.234 +134 "N5" 34.714 33.013 32.281 2.9935 2.9559 2.2837 +135 "O5" 166.35 175.94 163.99 44.139 49.035 35.423 +136 "P5" 89.669 79.549 47.144 14.200 13.959 3.6761 +137 "Q5" 191.24 182.85 188.48 59.021 56.831 48.262 +138 "R5" 51.675 70.899 41.770 6.3401 9.2262 3.4989 +139 "S5" 170.53 177.54 173.76 45.700 49.818 40.124 +140 "T5" 63.890 93.942 45.687 9.3142 14.437 4.0636 +141 "U5" 30.168 29.299 28.940 2.3535 2.3975 1.9290 +142 "V5" 133.08 133.14 122.05 27.766 28.925 20.091 +143 "W5" 36.054 32.923 33.276 3.0887 2.9300 2.3596 +144 "X5" 61.314 111.77 45.755 8.7239 16.803 5.0276 +145 "Y5" 203.39 209.40 208.06 70.161 75.882 63.247 +146 "Z5" 76.353 77.670 109.77 11.191 11.244 16.654 +147 "2A5" 193.86 202.18 186.73 62.394 68.771 47.096 +148 "2B5" 84.630 73.965 145.61 12.640 10.459 27.333 +149 "2C5" 68.392 129.05 45.336 11.160 21.761 5.5099 +150 "2D5" 210.46 210.49 195.89 77.413 80.592 53.936 +151 "A6" 156.79 90.614 148.03 37.703 22.453 27.499 +152 "B6" 88.481 111.82 178.46 14.943 18.301 44.058 +153 "C6" 167.90 108.82 66.983 44.282 30.956 7.9185 +154 "D6" 66.578 110.85 54.360 10.440 18.144 6.5076 +155 "E6" 148.31 87.735 154.80 32.892 20.486 29.274 +156 "F6" 93.611 155.13 115.73 17.819 31.263 19.184 +157 "G6" 40.190 39.280 58.763 3.7468 3.6058 6.3752 +158 "H6" 170.89 152.59 147.19 45.907 41.132 28.818 +159 "I6" 46.469 44.545 75.326 4.4472 4.1158 9.1204 +160 "J6" 102.48 151.18 180.03 20.388 31.549 44.358 +161 "K6" 30.872 30.164 29.516 2.3970 2.4515 1.9961 +162 "L6" 83.294 137.00 98.315 14.323 24.343 14.536 +163 "M6" 30.722 30.150 29.446 2.3623 2.4293 1.9541 +164 "N6" 163.74 151.67 194.83 41.190 36.767 50.714 +165 "O6" 199.83 203.65 49.970 62.357 69.847 6.3069 +166 "P6" 77.512 86.873 159.07 10.124 10.811 31.915 +167 "Q6" 200.99 194.31 190.45 67.127 65.762 49.352 +168 "R6" 165.39 100.99 154.68 39.128 23.959 27.822 +169 "S6" 69.496 98.026 61.986 10.413 15.222 6.7952 +170 "T6" 167.68 124.93 146.98 41.195 30.074 26.292 +171 "U6" 62.706 68.483 60.211 8.4099 9.5591 6.5834 +172 "V6" 174.63 108.06 166.14 43.942 26.976 32.439 +173 "W6" 138.60 174.02 106.27 33.397 44.263 15.513 +174 "X6" 192.12 161.59 197.05 56.629 45.672 50.137 +175 "Y6" 71.207 70.503 63.173 10.198 10.583 6.9283 +176 "Z6" 171.42 121.85 182.26 42.782 29.822 40.386 +177 "2A6" 193.77 197.98 207.14 61.567 65.013 61.274 +178 "2B6" 117.80 82.965 151.94 21.335 15.115 28.916 +179 "2C6" 36.305 39.517 34.462 3.2203 3.7212 2.6005 +180 "2D6" 152.48 145.44 148.89 35.799 34.854 29.422 +181 "A7" 93.637 153.35 73.710 19.123 33.078 10.667 +182 "B7" 83.277 73.755 144.52 12.915 10.831 28.225 +183 "C7" 206.85 206.70 197.33 77.518 80.587 57.622 +184 "D7" 77.454 73.349 146.72 11.348 10.154 28.703 +185 "E7" 70.809 132.64 47.023 12.442 24.254 5.6475 +186 "F7" 91.049 88.345 163.10 15.345 13.969 34.910 +187 "G7" 177.87 190.87 53.018 52.703 61.988 5.9513 +188 "H7" 75.960 87.720 159.98 9.9056 10.888 32.881 +189 "I7" 199.48 192.77 181.55 67.471 66.483 44.705 +190 "J7" 64.713 68.090 67.610 8.8426 9.6268 8.1730 +191 "K7" 193.08 175.48 139.54 61.925 56.855 24.968 +192 "L7" 75.430 87.876 159.79 9.6349 10.726 32.427 +193 "M7" 133.24 173.17 56.742 32.435 45.157 6.1480 +194 "N7" 148.49 75.098 46.216 30.427 18.146 3.6270 +195 "O7" 97.134 97.177 86.559 16.928 17.695 11.911 +196 "P7" 191.20 160.30 54.685 56.094 48.894 4.9467 +197 "Q7" 80.068 80.251 125.32 11.934 11.778 20.573 +198 "R7" 83.368 147.19 55.358 15.285 28.434 6.3346 +199 "S7" 37.747 44.719 36.907 3.5054 4.3615 2.7830 +200 "T7" 146.52 175.26 205.50 35.099 44.589 58.771 +201 "U7" 133.97 82.941 152.98 26.155 17.005 28.079 +202 "V7" 63.182 103.22 97.125 8.9086 14.924 14.071 +203 "W7" 144.22 147.07 76.384 30.611 33.536 8.6858 +204 "X7" 212.78 213.19 211.89 79.113 81.784 66.503 +205 "Y7" 77.896 86.298 158.37 10.240 10.764 31.229 +206 "Z7" 71.313 133.52 47.389 11.976 23.218 5.4228 +207 "2A7" 75.926 78.650 151.98 9.9976 9.7574 28.929 +208 "2B7" 118.08 168.98 98.781 25.572 39.297 14.262 +209 "2C7" 207.34 198.34 43.623 66.257 69.908 5.8960 +210 "2D7" 92.639 108.26 179.66 14.893 16.603 41.626 +211 "A8" 69.904 137.36 58.325 12.100 24.359 8.4071 +212 "B8" 167.09 144.55 49.599 42.436 39.900 4.7260 +213 "C8" 111.10 78.672 121.83 20.574 15.216 20.136 +214 "D8" 74.340 141.34 56.829 12.701 25.255 8.1803 +215 "E8" 104.13 74.055 141.65 18.324 13.039 26.409 +216 "F8" 90.075 154.61 90.911 16.724 30.035 13.212 +217 "G8" 36.341 33.896 36.868 3.3200 3.1831 3.0291 +218 "H8" 101.65 159.66 134.07 20.304 33.570 24.443 +219 "I8" 34.216 33.499 37.712 2.9169 2.9009 3.0168 +220 "J8" 174.41 165.56 173.38 48.038 46.099 39.891 +221 "K8" 46.252 66.300 42.397 5.2241 8.0427 3.5985 +222 "L8" 152.69 184.12 182.69 38.619 50.368 44.407 +223 "M8" 30.240 29.863 28.939 2.3428 2.3959 1.9273 +224 "N8" 35.593 35.467 34.190 3.1956 3.3116 2.6415 +225 "O8" 71.728 71.553 70.937 10.494 10.847 8.8081 +226 "P8" 115.92 116.10 114.68 22.233 23.005 18.548 +227 "Q8" 159.85 160.38 159.13 39.317 40.778 33.056 +228 "R8" 196.60 197.21 197.12 63.147 65.480 53.862 +229 "S8" 137.57 112.53 140.33 28.252 23.514 24.400 +230 "T8" 80.940 142.13 50.952 14.520 26.909 5.4756 +231 "U8" 99.365 133.93 196.43 18.057 24.054 51.817 +232 "V8" 30.957 30.566 29.813 2.3402 2.3911 1.9209 +233 "W8" 212.09 210.69 210.55 77.838 79.255 64.883 +234 "X8" 90.920 71.799 46.751 14.232 12.342 3.5677 +235 "Y8" 137.72 177.30 175.40 31.451 43.594 39.472 +236 "Z8" 39.524 49.911 38.685 3.8429 5.0881 3.0661 +237 "2A8" 130.39 176.13 127.05 27.844 41.491 21.140 +238 "2B8" 31.904 31.437 30.690 2.4921 2.5648 2.0613 +239 "2C8" 149.77 158.18 196.00 34.635 36.777 50.964 +240 "2D8" 30.719 29.824 29.600 2.3436 2.3905 1.9440 +241 "A9" 160.64 188.72 135.75 46.811 59.109 25.406 +242 "B9" 151.09 113.48 161.82 35.695 26.905 33.928 +243 "C9" 56.378 101.12 44.028 8.0578 15.313 4.8058 +244 "D9" 200.86 192.61 183.06 70.562 68.540 46.575 +245 "E9" 77.639 89.149 161.20 10.633 11.656 33.787 +246 "F9" 183.43 148.52 132.23 54.113 43.360 23.933 +247 "G9" 53.868 83.869 77.703 7.1200 11.358 10.328 +248 "H9" 144.68 93.693 163.06 31.237 20.786 32.756 +249 "I9" 80.625 147.05 117.46 14.469 27.174 19.553 +250 "J9" 82.612 53.093 45.342 11.813 8.1727 3.4750 +251 "K9" 179.05 178.11 205.03 51.613 51.265 59.093 +252 "L9" 68.256 128.21 45.397 11.232 21.889 5.3482 +253 "M9" 30.122 29.559 28.786 2.3389 2.3932 1.9205 +254 "N9" 44.132 44.030 43.113 4.6543 4.8363 3.9004 +255 "O9" 77.603 77.496 77.212 11.973 12.444 10.082 +256 "P9" 123.38 123.35 123.35 24.548 25.410 20.720 +257 "Q9" 167.61 168.12 167.11 43.270 44.842 36.215 +258 "R9" 202.61 204.17 205.53 68.113 71.034 59.864 +259 "S9" 152.34 81.269 59.657 31.468 18.903 5.4734 +260 "T9" 36.525 39.233 37.120 3.2297 3.6435 2.9170 +261 "U9" 147.79 112.59 105.57 31.779 25.042 15.321 +262 "V9" 128.85 175.42 85.449 30.098 43.673 10.856 +263 "W9" 202.12 182.11 203.04 65.360 57.273 55.175 +264 "X9" 58.841 111.22 46.014 7.8261 15.682 5.0934 +265 "Y9" 150.27 74.574 46.780 30.151 17.603 3.5424 +266 "Z9" 91.373 72.814 142.15 14.169 10.872 25.545 +267 "2A9" 178.42 178.87 165.68 49.740 51.961 35.295 +268 "2B9" 110.21 82.066 150.83 19.293 14.167 28.533 +269 "2C9" 115.57 141.00 82.227 23.305 29.469 10.465 +270 "2D9" 120.44 87.308 156.62 22.420 16.254 30.792 +271 "A10" 54.278 98.104 59.100 7.4766 14.316 6.7672 +272 "B10" 141.49 142.92 50.130 30.693 34.185 4.8132 +273 "C10" 69.545 135.98 93.417 11.568 23.235 13.773 +274 "D10" 30.772 30.009 29.471 2.4307 2.4999 2.0171 +275 "E10" 140.52 89.479 159.03 30.140 19.949 31.751 +276 "F10" 88.149 135.62 165.23 15.810 25.353 37.521 +277 "G10" 30.508 30.075 29.389 2.4272 2.4936 1.9887 +278 "H10" 75.794 144.13 86.030 12.549 25.096 11.562 +279 "I10" 29.881 29.286 28.915 2.3402 2.3788 1.9223 +280 "J10" 78.427 139.08 135.09 13.387 24.235 23.958 +281 "K10" 127.69 103.24 52.122 25.478 22.853 4.3681 +282 "L10" 47.518 38.484 37.887 5.0366 4.2550 2.8902 +283 "M10" 30.202 29.466 28.978 2.3374 2.3915 1.9194 +284 "N10" 50.671 50.438 49.901 5.8942 6.1054 4.9143 +285 "O10" 84.087 84.218 84.130 13.462 14.013 11.428 +286 "P10" 130.92 131.27 131.19 27.055 28.014 23.007 +287 "Q10" 174.24 174.94 173.31 47.406 49.169 39.386 +288 "R10" 208.46 209.75 212.17 73.974 77.043 65.729 +289 "S10" 61.440 61.759 68.112 7.8358 8.0794 7.9176 +290 "T10" 189.59 154.63 195.61 54.395 42.563 48.165 +291 "U10" 70.065 139.76 58.155 11.113 22.841 7.7084 +292 "V10" 34.382 38.877 37.374 2.9394 3.4387 2.9247 +293 "W10" 81.185 148.91 88.683 13.284 25.973 11.867 +294 "X10" 31.337 30.706 30.647 2.4768 2.5120 2.1182 +295 "Y10" 132.10 124.54 122.36 27.102 26.481 19.829 +296 "Z10" 128.86 77.259 44.848 23.978 16.698 3.6586 +297 "2A10" 121.07 144.71 145.24 24.659 30.178 27.108 +298 "2B10" 91.404 54.498 76.524 13.618 8.1445 8.4106 +299 "2C10" 122.45 129.19 129.52 24.412 26.496 22.533 +300 "2D10" 52.091 43.712 85.349 5.2897 4.2252 10.803 +301 "A11" 95.121 56.945 109.13 15.662 9.9371 16.757 +302 "B11" 49.247 84.978 41.595 6.3528 11.756 4.1276 +303 "C11" 201.38 188.28 201.57 70.247 65.054 58.834 +304 "D11" 165.99 106.71 48.883 42.904 30.283 4.3741 +305 "E11" 142.45 151.87 140.77 33.675 37.292 27.259 +306 "F11" 59.895 43.373 70.686 7.3260 5.3398 8.4321 +307 "G11" 185.60 179.80 175.52 56.748 56.026 41.441 +308 "H11" 62.810 62.001 39.464 8.1585 8.7147 3.0001 +309 "I11" 182.38 181.99 177.01 54.512 56.195 42.466 +310 "J11" 44.613 62.579 56.523 4.9736 7.2275 6.1574 +311 "K11" 177.26 171.26 154.02 50.413 50.352 29.675 +312 "L11" 81.706 58.921 119.57 11.783 8.3671 18.993 +313 "M11" 30.648 29.769 29.464 2.4004 2.4632 1.9865 +314 "N11" 56.534 56.324 55.689 7.0502 7.2979 5.9348 +315 "O11" 89.911 89.936 88.980 15.157 15.663 12.643 +316 "P11" 140.77 141.41 140.88 30.809 31.935 26.037 +317 "Q11" 179.84 180.21 178.58 51.029 52.827 42.179 +318 "R11" 212.60 213.84 215.53 78.892 82.077 69.152 +319 "S11" 66.493 66.184 65.558 9.0391 9.3614 7.5795 +320 "T11" 187.32 160.61 146.99 54.688 46.067 27.270 +321 "U11" 59.842 44.929 41.517 7.0672 5.5203 3.1542 +322 "V11" 100.71 151.70 177.40 19.018 30.251 40.808 +323 "W11" 32.433 32.983 31.555 2.6438 2.7813 2.1741 +324 "X11" 103.41 161.56 150.03 20.294 33.254 28.954 +325 "Y11" 49.930 46.756 84.028 4.7917 4.3367 10.461 +326 "Z11" 157.24 187.57 185.20 39.678 51.335 44.730 +327 "2A11" 69.840 130.51 46.639 11.397 22.075 5.4606 +328 "2B11" 164.73 190.77 189.92 43.396 54.386 47.692 +329 "2C11" 67.660 57.565 50.639 9.0264 8.0855 4.5632 +330 "2D11" 146.88 73.255 46.894 29.263 17.239 3.6542 +331 "A12" 149.18 183.06 84.464 42.435 55.238 11.960 +332 "B12" 72.446 71.794 146.17 10.244 9.5241 28.550 +333 "C12" 111.58 163.80 82.344 25.557 39.490 11.397 +334 "D12" 67.115 62.023 67.669 9.5983 9.1448 8.3283 +335 "E12" 202.25 206.59 144.16 71.285 77.444 27.463 +336 "F12" 142.52 142.52 149.46 32.592 33.399 30.058 +337 "G12" 52.218 46.843 96.005 5.1430 4.3541 13.182 +338 "H12" 95.301 157.62 128.66 18.517 32.087 22.562 +339 "I12" 58.804 42.199 45.333 6.9977 5.1440 3.8014 +340 "J12" 201.67 207.01 112.57 69.246 76.042 17.844 +341 "K12" 76.878 56.433 113.86 10.642 7.6407 17.593 +342 "L12" 110.43 164.87 121.89 21.927 35.477 19.681 +343 "M12" 31.073 30.502 29.828 2.4287 2.4921 1.9949 +344 "N12" 60.863 60.999 60.221 7.9937 8.3172 6.7360 +345 "O12" 97.436 97.414 96.425 17.120 17.761 14.285 +346 "P12" 146.96 147.76 147.68 33.242 34.486 28.221 +347 "Q12" 186.04 186.49 184.52 55.136 57.000 45.303 +348 "R12" 217.03 217.69 217.80 84.047 87.070 71.496 +349 "S12" 173.81 166.67 164.48 46.799 45.618 34.284 +350 "T12" 61.998 59.133 126.43 6.6921 6.0185 19.773 +351 "U12" 133.08 178.53 107.01 31.583 45.365 15.646 +352 "V12" 159.59 92.307 67.569 35.975 22.808 7.0470 +353 "W12" 92.823 93.091 102.67 15.632 16.004 15.333 +354 "X12" 153.31 79.910 48.385 32.188 19.569 3.7849 +355 "Y12" 76.169 77.765 152.48 9.9981 9.6287 28.171 +356 "Z12" 80.867 145.82 55.209 14.429 27.348 6.4901 +357 "2A12" 88.726 84.091 155.13 13.822 12.446 29.936 +358 "2B12" 201.37 208.14 195.53 68.261 74.431 52.067 +359 "2C12" 32.004 31.705 30.813 2.4685 2.5621 2.0287 +360 "2D12" 135.53 145.08 187.78 28.798 30.974 45.549 +361 "A13" 86.415 69.301 138.07 14.129 10.884 26.286 +362 "B13" 104.58 136.42 46.559 21.280 29.662 4.6515 +363 "C13" 147.82 79.114 100.32 32.064 17.966 13.604 +364 "D13" 75.334 85.157 157.26 9.9611 10.733 32.277 +365 "E13" 178.81 179.96 148.24 51.845 54.927 28.181 +366 "F13" 55.482 72.327 100.16 6.3441 8.5421 15.068 +367 "G13" 200.09 199.75 184.43 68.699 71.452 46.387 +368 "H13" 76.688 84.710 151.41 10.374 10.902 29.169 +369 "I13" 129.73 107.35 52.022 26.203 23.997 4.3858 +370 "J13" 119.03 160.66 198.42 25.753 36.554 54.373 +371 "K13" 56.473 50.032 106.16 5.9068 4.9157 15.287 +372 "L13" 153.18 106.56 46.936 35.348 27.270 4.1933 +373 "M13" 32.264 31.978 31.289 2.6154 2.7053 2.1626 +374 "N13" 66.470 66.520 66.246 9.3637 9.6843 7.8391 +375 "O13" 105.28 105.86 104.76 19.359 20.106 16.147 +376 "P13" 153.75 154.63 154.12 36.624 37.957 30.671 +377 "Q13" 192.03 192.25 191.27 59.859 61.861 49.702 +378 "R13" 221.68 221.89 221.96 89.957 93.025 75.604 +379 "S13" 104.20 75.856 145.33 17.613 12.665 26.369 +380 "T13" 121.87 124.18 72.370 22.969 25.114 7.7873 +381 "U13" 91.392 55.886 72.021 13.623 8.3610 7.6135 +382 "V13" 193.01 176.53 161.70 59.661 54.433 33.140 +383 "W13" 97.047 61.496 44.638 15.045 10.609 3.4373 +384 "X13" 124.18 171.27 172.48 26.676 39.190 37.659 +385 "Y13" 100.95 103.55 45.932 16.770 18.831 3.7976 +386 "Z13" 98.719 76.722 108.03 16.243 13.004 15.620 +387 "2A13" 193.99 204.68 205.71 62.079 69.145 59.254 +388 "2B13" 77.619 94.368 167.50 9.8300 11.508 34.315 +389 "2C13" 91.512 53.191 50.701 13.378 8.4024 4.1065 +390 "2D13" 76.609 104.98 135.45 11.706 16.228 24.708 +391 "A14" 129.84 79.131 147.61 27.260 17.709 28.446 +392 "B14" 74.731 86.884 158.53 10.007 11.116 33.309 +393 "C14" 178.45 194.65 198.02 55.170 63.826 56.969 +394 "D14" 122.80 65.789 71.805 22.474 12.791 7.8220 +395 "E14" 99.529 101.15 66.691 17.833 19.340 7.6068 +396 "F14" 133.73 68.160 43.803 25.508 15.387 3.5019 +397 "G14" 130.31 174.28 137.87 28.674 42.244 25.294 +398 "H14" 110.49 77.413 145.63 20.013 14.167 27.201 +399 "I14" 30.999 29.764 29.587 2.4079 2.4331 1.9867 +400 "J14" 120.14 114.13 178.99 23.527 21.066 41.374 +401 "K14" 128.29 64.544 74.117 23.203 12.509 8.0121 +402 "L14" 176.70 157.34 183.40 48.486 42.511 43.112 +403 "M14" 59.777 105.00 45.141 8.6031 15.926 4.6200 +404 "N14" 182.00 181.11 190.30 53.107 53.884 48.977 +405 "O14" 42.651 40.749 62.042 3.9836 3.7404 6.5852 +406 "P14" 151.32 150.31 182.91 35.517 35.068 43.001 +407 "Q14" 162.51 94.932 125.82 37.782 22.314 19.042 +408 "R14" 99.745 94.301 93.467 17.467 17.105 13.104 +409 "S14" 107.25 159.78 58.090 22.370 35.508 5.9931 +410 "T14" 128.01 72.369 117.84 23.886 13.985 16.868 +411 "U14" 107.76 101.18 90.766 19.591 19.252 12.172 +412 "V14" 204.14 190.16 48.644 63.345 63.812 5.6645 +413 "W14" 82.597 65.626 44.970 12.028 10.481 3.3856 +414 "X14" 166.39 166.20 175.82 42.635 43.420 39.912 +415 "Y14" 100.69 152.17 51.384 19.856 32.192 5.1431 +416 "Z14" 91.650 100.20 90.746 15.570 17.641 12.711 +417 "2A14" 143.62 91.243 162.04 29.733 19.495 31.105 +418 "2B14" 214.71 215.34 214.31 81.209 84.285 67.959 +419 "2C14" 101.32 87.875 161.74 16.972 13.897 32.504 +420 "2D14" 105.18 138.75 68.497 20.262 27.906 7.7177 +421 "A15" 124.84 68.758 114.78 24.922 14.319 17.652 +422 "B15" 99.929 150.22 167.53 20.394 32.266 39.177 +423 "C15" 121.25 165.78 57.133 28.847 42.042 6.3345 +424 "D15" 129.49 121.04 130.58 27.579 26.553 23.681 +425 "E15" 161.27 95.254 123.97 38.874 23.290 19.357 +426 "F15" 148.20 174.03 142.22 36.703 46.352 27.027 +427 "G15" 150.41 98.923 167.42 34.061 22.803 34.531 +428 "H15" 75.180 91.615 158.04 10.113 11.921 31.879 +429 "I15" 196.22 179.25 172.32 64.423 58.008 39.281 +430 "J15" 66.558 62.105 60.696 9.4542 9.1717 6.7120 +431 "K15" 174.25 177.65 112.40 48.073 52.062 16.154 +432 "L15" 116.33 112.29 162.02 22.225 20.657 33.169 +433 "M15" 133.68 171.46 73.038 32.410 43.840 8.6168 +434 "N15" 102.47 146.49 198.15 19.932 29.141 53.896 +435 "O15" 64.715 46.574 43.032 8.2354 6.1612 3.2448 +436 "P15" 105.91 159.08 164.78 21.186 33.689 34.860 +437 "Q15" 34.379 33.754 36.003 2.8839 2.9372 2.7235 +438 "R15" 102.62 61.271 119.89 16.647 10.677 18.389 +439 "S15" 159.62 86.224 48.021 35.874 22.454 3.7685 +440 "T15" 95.611 158.57 127.45 18.024 31.495 21.231 +441 "U15" 133.03 87.140 157.87 26.027 17.635 30.172 +442 "V15" 48.894 77.368 43.484 5.7623 9.6302 3.8733 +443 "W15" 182.54 191.20 178.40 53.522 58.991 41.376 +444 "X15" 126.00 95.308 166.74 23.991 17.693 34.060 +445 "Y15" 38.376 39.986 33.590 3.5595 3.8688 2.3978 +446 "Z15" 148.30 148.94 147.37 34.055 35.265 28.241 +447 "2A15" 146.55 75.055 68.429 29.379 16.826 7.3609 +448 "2B15" 71.706 70.645 144.63 9.2107 8.5579 25.691 +449 "2C15" 133.02 80.816 44.452 25.707 18.129 3.6532 +450 "2D15" 82.777 113.54 117.52 13.875 19.568 19.948 +451 "A16" 147.43 75.104 45.417 32.441 19.582 3.7464 +452 "B16" 162.22 145.05 108.87 43.738 40.362 16.554 +453 "C16" 43.273 69.681 61.261 4.9159 8.3065 7.2559 +454 "D16" 154.15 106.72 65.606 37.197 27.832 7.4910 +455 "E16" 149.19 148.83 193.98 36.691 35.876 51.695 +456 "F16" 157.80 111.38 47.573 38.836 30.036 4.3338 +457 "G16" 100.61 79.449 149.13 17.555 13.363 28.888 +458 "H16" 206.92 207.61 211.44 75.466 77.836 67.216 +459 "I16" 97.895 82.272 66.348 16.954 15.112 7.2992 +460 "J16" 172.80 178.46 82.595 47.072 52.200 10.669 +461 "K16" 183.90 191.17 190.75 55.962 60.759 50.287 +462 "L16" 75.048 76.021 151.02 10.165 9.7715 28.705 +463 "M16" 159.42 88.282 47.938 36.859 23.500 3.8297 +464 "N16" 133.24 176.09 150.50 29.735 43.076 29.229 +465 "O16" 59.749 48.251 40.198 7.3545 6.2503 2.9745 +466 "P16" 171.06 168.69 161.58 46.114 46.965 33.568 +467 "Q16" 53.260 54.841 37.700 6.2218 6.8107 2.7776 +468 "R16" 147.03 76.735 66.424 29.663 17.214 6.8286 +469 "S16" 63.206 78.809 107.93 8.0381 10.138 16.410 +470 "T16" 150.22 77.352 47.226 31.088 18.734 3.6263 +471 "U16" 97.824 159.49 134.64 18.911 32.215 23.899 +472 "V16" 133.39 81.567 151.23 26.145 16.883 27.363 +473 "W16" 155.32 82.024 48.477 33.705 20.761 3.7986 +474 "X16" 81.301 147.86 56.013 14.361 27.487 7.1744 +475 "Y16" 141.53 112.75 178.08 29.882 22.982 39.138 +476 "Z16" 31.556 30.196 30.075 2.4233 2.4412 1.9648 +477 "2A16" 166.04 149.78 129.15 42.519 39.188 21.270 +478 "2B16" 53.939 48.402 100.70 5.2349 4.4461 13.823 +479 "2C16" 152.96 83.435 68.500 32.492 19.465 7.0806 +480 "2D16" 141.97 181.00 131.63 33.454 46.863 22.481 +481 "A17" 93.002 152.57 112.99 18.355 31.722 19.048 +482 "B17" 48.562 44.595 81.595 4.8626 4.2833 10.526 +483 "C17" 155.24 137.12 108.13 39.631 36.092 16.781 +484 "D17" 37.723 54.820 48.270 3.8471 5.8319 4.8962 +485 "E17" 163.04 158.68 133.73 43.491 44.349 22.904 +486 "F17" 155.10 81.151 47.477 35.028 21.444 3.8305 +487 "G17" 119.76 108.26 175.73 23.826 20.302 40.464 +488 "H17" 155.83 188.69 108.40 44.211 56.679 16.435 +489 "I17" 54.125 49.417 43.252 6.5115 6.2807 3.6004 +490 "J17" 146.89 182.65 155.76 35.464 48.530 31.500 +491 "K17" 148.71 77.345 50.119 31.217 18.833 4.2081 +492 "L17" 53.925 41.854 39.291 6.1796 5.0138 3.0160 +493 "M17" 105.46 156.83 167.45 21.355 33.511 36.981 +494 "N17" 149.16 79.222 103.08 31.382 17.339 13.539 +495 "O17" 109.98 107.89 138.78 20.515 20.076 24.934 +496 "P17" 151.99 78.765 47.620 32.143 19.447 3.7592 +497 "Q17" 195.13 169.06 200.08 60.501 50.532 52.708 +498 "R17" 73.599 136.55 49.271 12.657 24.420 5.6873 +499 "S17" 37.757 33.718 34.938 3.4355 3.1639 2.5372 +500 "T17" 132.61 142.77 197.68 28.192 29.771 51.322 +501 "U17" 181.82 145.93 103.48 52.660 42.651 15.019 +502 "V17" 204.10 203.91 210.35 69.823 71.393 63.731 +503 "W17" 175.82 179.36 52.229 44.995 50.413 5.2421 +504 "X17" 155.69 156.50 143.88 37.401 38.967 26.702 +505 "Y17" 65.731 44.495 80.654 8.0339 5.5483 9.9052 +506 "Z17" 67.930 138.21 88.916 10.382 21.829 11.599 +507 "2A17" 156.40 87.866 68.881 34.325 21.131 7.2263 +508 "2B17" 68.870 68.990 41.254 9.1863 9.9839 3.1512 +509 "2C17" 209.60 202.66 207.60 75.534 73.388 61.922 +510 "2D17" 108.97 87.062 152.98 19.258 14.916 29.290 +511 "A18" 200.70 204.40 197.90 74.089 78.770 59.424 +512 "B18" 164.93 117.44 177.68 42.903 30.204 40.715 +513 "C18" 61.227 72.827 56.013 8.7363 10.837 6.0872 +514 "D18" 204.51 199.19 195.95 75.509 74.636 56.066 +515 "E18" 73.692 73.322 148.06 10.413 9.8011 28.727 +516 "F18" 68.313 128.24 45.392 11.836 22.861 5.4226 +517 "G18" 131.14 85.288 152.52 26.954 18.177 29.358 +518 "H18" 89.609 153.68 93.128 16.220 29.699 13.154 +519 "I18" 30.179 29.676 28.922 2.3647 2.3980 1.9090 +520 "J18" 208.65 210.69 209.48 77.786 81.283 65.463 +521 "K18" 88.863 70.346 63.498 14.363 11.898 6.7644 +522 "L18" 197.92 177.16 54.602 60.378 57.128 5.2726 +523 "M18" 143.55 91.470 162.00 30.554 20.123 31.743 +524 "N18" 121.99 131.52 122.44 24.748 27.645 20.451 +525 "O18" 172.04 115.00 91.328 44.929 31.003 12.389 +526 "P18" 81.187 74.923 148.64 11.881 10.425 27.990 +527 "Q18" 117.91 169.48 101.12 25.737 39.690 14.823 +528 "R18" 183.93 145.62 52.297 52.300 42.856 4.6545 +529 "S18" 55.452 105.38 65.438 7.2126 14.429 7.1944 +530 "T18" 211.11 208.92 210.90 77.679 78.425 65.193 +531 "U18" 177.41 124.39 134.00 47.084 32.209 22.319 +532 "V18" 53.506 90.891 78.889 6.6683 11.848 10.189 +533 "W18" 197.65 205.13 206.81 65.207 70.970 60.729 +534 "X18" 51.396 86.860 43.674 6.2806 11.330 4.1095 +535 "Y18" 193.58 175.18 113.92 60.571 56.044 16.070 +536 "Z18" 96.313 103.94 178.60 15.673 16.045 40.153 +537 "2A18" 168.53 106.08 128.73 41.178 25.901 19.845 +538 "2B18" 85.496 104.15 136.89 13.693 16.674 24.407 +539 "2C18" 208.09 210.26 179.31 74.223 78.952 41.733 +540 "2D18" 161.94 92.492 50.116 38.135 24.817 4.1395 +541 "A19" 156.71 112.54 101.12 39.239 29.094 15.479 +542 "B19" 42.513 58.501 40.536 4.7416 7.0454 3.4644 +543 "C19" 172.17 152.13 143.40 49.395 43.657 28.522 +544 "D19" 159.73 183.13 54.703 42.332 52.372 5.7052 +545 "E19" 119.21 105.48 95.518 24.242 22.424 14.026 +546 "F19" 30.235 29.764 29.269 2.4551 2.5226 2.0256 +547 "G19" 88.689 134.99 136.69 16.677 25.667 25.825 +548 "H19" 86.392 53.901 45.566 13.124 8.8453 3.5763 +549 "I19" 126.88 158.15 160.78 28.527 37.076 34.358 +550 "J19" 120.42 79.125 64.241 22.891 16.490 6.9749 +551 "K19" 108.34 160.80 164.56 22.666 35.279 35.631 +552 "L19" 49.327 39.952 38.592 5.4212 4.5484 2.9627 +553 "M19" 67.917 128.27 44.976 11.199 21.925 5.4425 +554 "N19" 127.84 62.080 45.945 22.708 12.897 3.6335 +555 "O19" 74.380 138.45 130.11 12.507 23.738 22.498 +556 "P19" 30.060 29.337 28.817 2.3442 2.3896 1.9267 +557 "Q19" 147.97 73.539 46.480 30.303 17.749 3.5777 +558 "R19" 75.153 76.608 151.15 10.104 9.7374 28.448 +559 "S19" 78.339 144.41 52.936 13.901 26.685 6.3873 +560 "T19" 31.312 30.556 30.767 2.4391 2.4780 2.0610 +561 "U19" 169.32 177.98 203.35 45.972 49.473 57.247 +562 "V19" 44.471 72.376 45.634 4.8275 8.3485 3.9886 +563 "W19" 199.02 205.39 55.979 63.154 70.855 7.5811 +564 "X19" 90.125 81.954 73.039 14.863 14.166 8.5770 +565 "Y19" 207.33 211.44 212.22 74.340 78.986 66.286 +566 "Z19" 182.95 126.85 175.69 49.996 33.344 36.894 +567 "2A19" 77.857 90.598 163.13 10.165 11.287 33.081 +568 "2B19" 202.16 204.23 49.052 62.642 69.515 6.2139 +569 "2C19" 162.94 96.440 68.740 38.429 24.741 7.3479 +570 "2D19" 83.952 84.116 160.97 12.944 12.283 32.608 +END_DATA diff --git a/scanin/ColorChecker.cht b/scanin/ColorChecker.cht new file mode 100644 index 0000000..1da441b --- /dev/null +++ b/scanin/ColorChecker.cht @@ -0,0 +1,59 @@ + +BOXES 25 + F _ _ 10.0 9.75 321.25 9.75 321.26 217 10.0 217 + D ALL ALL _ _ 330 228 0 0 0 0 + Y 1 6 A D 46.0 46.0 12.0 11.5 52.5 52.5 + +BOX_SHRINK 6.0 + +REF_ROTATION 0.0 + +XLIST 12 + 12.0 1.0 1.0 + 58.5 1.0 1.0 + 64.5 1.0 1.0 + 110.5 1.0 1.0 + 117.0 1.0 1.0 + 163.0 1.0 1.0 + 169.5 1.0 1.0 + 215.5 1.0 1.0 + 221.5 1.0 1.0 + 267.5 1.0 1.0 + 274.0 1.0 1.0 + 320.0 1.0 1.0 + +YLIST 8 + 11.5 1.0 1.0 + 58.0 1.0 1.0 + 64.0 1.0 1.0 + 110.0 1.0 1.0 + 116.5 1.0 1.0 + 163.0 1.0 1.0 + 169.0 1.0 1.0 + 215.0 1.0 1.0 + +EXPECTED XYZ 24 + A1 11.773 10.213 4.9219 + A2 40.174 36.201 20.217 + A3 17.675 19.409 26.983 + A4 11.121 13.530 5.5615 + A5 25.551 24.404 34.847 + A6 31.744 43.164 35.249 + B1 40.056 30.947 4.8180 + B2 12.544 11.700 28.648 + B3 30.675 20.352 10.837 + B4 8.3961 6.5047 10.849 + B5 36.036 44.991 8.9494 + B6 50.203 44.570 6.2773 + C1 7.4590 6.0952 23.518 + C2 15.439 23.986 7.7482 + C3 22.850 13.022 4.1188 + C4 59.637 60.332 7.3520 + C5 30.450 20.015 22.947 + C6 13.591 19.466 30.479 + D1 86.776 90.361 70.642 + D2 56.865 59.038 48.218 + D3 34.763 36.036 29.378 + D4 18.884 19.603 16.309 + D5 8.4332 8.7464 7.1022 + D6 3.0110 3.0971 2.5475 diff --git a/scanin/ColorChecker.cie b/scanin/ColorChecker.cie new file mode 100644 index 0000000..8c78ff6 --- /dev/null +++ b/scanin/ColorChecker.cie @@ -0,0 +1,39 @@ +IT8.7/2 +ORIGINATOR "Graeme Gill, ArgyllCMS from Gretag Macbeth reference" +DESCRIPTOR "ColorChecker 24" +CREATED "Feb 18, 2008" +MANUFACTURER "X-Rite/Gretag Macbeth" + +NUMBER_OF_FIELDS 4 +BEGIN_DATA_FORMAT +SAMPLE_ID LAB_L LAB_A LAB_B +END_DATA_FORMAT + +NUMBER_OF_SETS 24 +BEGIN_DATA +A01 37.99 13.56 14.06 +A02 65.71 18.13 17.81 +A03 49.93 -4.88 -21.93 +A04 43.14 -13.10 21.91 +A05 55.11 8.84 -25.40 +A06 70.72 -33.40 -0.20 +B01 62.66 36.07 57.10 +B02 40.02 10.41 -45.96 +B03 51.12 48.24 16.25 +B04 30.33 22.98 -21.59 +B05 72.53 -23.71 57.26 +B06 71.94 19.36 67.86 +C01 28.78 14.18 -50.30 +C02 55.26 -38.34 31.37 +C03 42.10 53.38 28.19 +C04 81.73 4.04 79.82 +C05 51.94 49.99 -14.57 +C06 51.04 -28.63 -28.64 +D01 96.54 -0.43 1.19 +D02 81.26 -0.64 -0.34 +D03 66.77 -0.73 -0.50 +D04 50.87 -0.15 -0.27 +D05 35.66 -0.42 -1.23 +D06 20.46 -0.08 -0.97 +END_DATA + diff --git a/scanin/ColorCheckerDC.cht b/scanin/ColorCheckerDC.cht new file mode 100644 index 0000000..ad7ea29 --- /dev/null +++ b/scanin/ColorCheckerDC.cht @@ -0,0 +1,318 @@ + +BOXES 241 + F _ _ 26.09 18.7 330.2 18.7 330.2 202.4 26.09 202.4 + D ALL ALL _ _ 355 216 0 0 0 0 + X A T 01 12 12.675 12.75 27.5 20.0 15.175 15.25 + +BOX_SHRINK 1.6 + +XLIST 40 + 27.5 1.0 1.0 + 40.175 1.0 1.0 + 42.675 1.0 1.0 + 55.35 1.0 1.0 + 57.85 1.0 1.0 + 70.525 1.0 1.0 + 73.025 1.0 1.0 + 85.7 1.0 1.0 + 88.2 1.0 1.0 + 100.875 1.0 1.0 + 103.375 1.0 1.0 + 116.05 1.0 1.0 + 118.55 1.0 1.0 + 131.225 1.0 1.0 + 133.725 1.0 1.0 + 146.4 1.0 1.0 + 148.9 1.0 1.0 + 161.575 1.0 1.0 + 164.075 1.0 1.0 + 176.75 1.0 1.0 + 179.25 1.0 1.0 + 191.925 1.0 1.0 + 194.425 1.0 1.0 + 207.1 1.0 1.0 + 209.6 1.0 1.0 + 222.275 1.0 1.0 + 224.775 1.0 1.0 + 237.45 1.0 1.0 + 239.95 1.0 1.0 + 252.625 1.0 1.0 + 255.125 1.0 1.0 + 267.8 1.0 1.0 + 270.3 1.0 1.0 + 282.975 1.0 1.0 + 285.475 1.0 1.0 + 298.15 1.0 1.0 + 300.65 1.0 1.0 + 313.325 1.0 1.0 + 315.825 1.0 1.0 + 328.5 1.0 1.0 + +YLIST 24 + 20.0 1.0 1.0 + 32.75 1.0 1.0 + 35.25 1.0 1.0 + 48.0 1.0 1.0 + 50.5 1.0 1.0 + 63.25 1.0 1.0 + 65.75 1.0 1.0 + 78.5 1.0 1.0 + 81.0 1.0 1.0 + 93.75 1.0 1.0 + 96.25 1.0 1.0 + 109.0 1.0 1.0 + 111.5 1.0 1.0 + 124.25 1.0 1.0 + 126.75 1.0 1.0 + 139.5 1.0 1.0 + 142.0 1.0 1.0 + 154.75 1.0 1.0 + 157.25 1.0 1.0 + 170.0 1.0 1.0 + 172.5 1.0 1.0 + 185.25 1.0 1.0 + 187.75 1.0 1.0 + 200.5 1.0 1.0 + +EXPECTED XYZ 240 +A01 74.79 77.56 64.46 +A02 3.08 3.19 2.77 +A03 18.98 19.71 16.53 +A04 74.57 77.34 64.38 +A05 3.1 3.21 2.78 +A06 18.88 19.62 16.44 +A07 74.65 77.43 64.37 +A08 3.05 3.16 2.74 +A09 18.86 19.59 16.42 +A10 74.33 77.13 64.18 +A11 3.05 3.16 2.74 +A12 18.94 19.67 16.48 +B01 18.98 19.71 16.53 +B02 9.28 6.32 3.27 +B03 7.34 6.63 3.64 +B04 19.71 19.69 11.13 +B05 10.69 11.58 6.54 +B06 5.55 6.26 3.53 +B07 4.69 6.4 3.88 +B08 4.45 6.24 5.6 +B09 5.26 6.13 6.71 +B10 4.16 4.4 7.55 +B11 7.13 6.18 5.2 +B12 74.68 77.45 64.31 +C01 3.03 3.14 2.72 +C02 22.27 12.45 5.91 +C03 13.73 11.57 5.26 +C04 12.35 11.83 4.46 +C05 16.62 19.15 7.75 +C06 8.81 11.49 5.72 +C07 7.38 11.51 5.94 +C08 7.96 11.09 9.57 +C09 5.61 6.35 9.68 +C10 5.49 6.22 12.37 +C11 8.5 6.58 6.19 +C12 3.04 3.15 2.73 +D01 74.7 77.48 64.38 +D02 23.6 12.43 3.41 +D03 15.71 12.25 4.16 +D04 19.85 19.78 4.3 +D05 15.7 19.2 4.89 +D06 22.07 30.17 8.05 +D07 6.22 11.44 6.34 +D08 11.56 19.31 16.65 +D09 5.69 6.13 12.53 +D10 5.6 5.88 14.72 +D11 9.13 6.35 7.28 +D12 18.91 19.64 16.46 +E01 18.95 19.69 16.5 +E02 35.41 20.25 6.45 +E03 28.25 20.38 3.83 +E04 20.73 19.59 4.47 +E05 16.4 19.03 4.34 +E06 34.81 43.02 17.75 +E07 11.78 19.58 11.32 +E08 6.88 11.75 14.39 +E09 7.88 11.31 19.64 +E10 9.22 11.09 27.08 +E11 17.84 11.47 13.98 +E12 74.56 77.32 64.24 +F01 3.04 3.15 2.73 +F02 48.3 30.25 11.41 +F03 16.14 10.93 3.9 +F04 31.33 29.91 8.52 +F05 14.11 18.71 6.4 +F06 38.16 43.99 9.51 +F07 10.52 19.33 8.14 +F08 7.96 11.49 16.13 +F09 8.63 11.3 17.86 +F10 10.41 11.24 27.64 +F11 21.49 12.15 9.52 +F12 3.04 3.15 2.73 +G01 74.73 77.5 64.38 +G02 44.51 29.8 15.52 +G03 24.34 19.34 8.11 +G04 25.26 19.88 4.38 +G05 13.65 19.52 4.62 +G06 36.49 43.18 5.73 +G07 19.42 29.58 14.51 +G08 19.86 28.9 37.67 +G09 14.15 18.75 25.13 +G10 10.69 11.62 23.13 +G11 31.57 19.76 17.91 +G12 18.91 19.64 16.46 +H01 18.98 19.71 16.53 +H02 33.5 20.33 9.91 +H03 34.67 28.65 13.17 +H04 16.86 12.12 2.75 +H05 21.16 30.06 6.66 +H06 52.08 58.65 19.39 +H07 22.63 29.16 10.83 +H08 21.74 29.15 34.08 +H09 13.59 18.65 33.2 +H10 17.32 18.86 39.16 +H11 29.3 19.82 17.88 +H12 74.65 77.41 64.27 +I01 3.05 3.16 2.74 +I02 22.03 19.1 15.09 +I03 31.97 28.79 15.9 +I04 42.69 29.41 6.24 +I05 82.21 85.41 69.86 +I06 30.96 32.15 26.58 +I07 16.49 17.18 14.34 +I08 7.03 7.28 6.15 +I09 24.91 29.34 38.48 +I10 29.04 29.31 45.2 +I11 41.09 29.82 26.18 +I12 3.05 3.16 2.75 +J01 74.72 77.5 64.44 +J02 26.91 19.35 14.94 +J03 34.54 29.66 11.16 +J04 58.1 42.93 8.71 +J05 64.14 66.75 54.99 +J06 87.06 90.39 72.76 +J07 86.82 90.15 72.56 +J08 4.28 4.47 3.84 +J09 24.87 28.59 45.17 +J10 41.47 42.2 57.7 +J11 53.38 42.55 36.49 +J12 18.92 19.65 16.47 +K01 18.97 19.7 16.52 +K02 36.7 29.69 19.45 +K03 36.83 30.22 8.83 +K04 53.42 43.05 10.13 +K05 51.78 53.86 44.86 +K06 86.85 90.18 72.55 +K07 86.91 90.25 72.64 +K08 3.45 3.59 3.07 +K09 21.49 28.73 46.46 +K10 21.85 19.42 36.39 +K11 32.48 29.05 24.22 +K12 74.63 77.39 64.28 +L01 3.03 3.14 2.73 +L02 53.85 42.1 29.27 +L03 58.21 42.93 21.15 +L04 40.96 30.79 3.87 +L05 40.79 42.45 35.04 +L06 23.51 24.47 20.31 +L07 11.1 11.62 9.8 +L08 3.02 3.13 2.71 +L09 31.86 41.84 53.57 +L10 7.9 6.16 10.17 +L11 62.34 57.68 47.93 +L12 3.03 3.14 2.72 +M01 74.74 77.52 64.43 +M02 68.21 58.76 45.3 +M03 54.32 42.79 26.91 +M04 68.17 58.65 13.41 +M05 76.51 80.88 14.08 +M06 15.06 19.36 18.82 +M07 16.03 29.31 11.79 +M08 52.05 57.11 51.73 +M09 32.54 42.52 46.33 +M10 7.2 6.19 8.57 +M11 78.01 78.48 67.07 +M12 18.93 19.67 16.48 +N01 18.97 19.7 16.51 +N02 65.97 60.13 42.01 +N03 50.5 42.33 28.58 +N04 63.78 59.07 15.95 +N05 62.58 58.72 7.2 +N06 21.33 29.57 29.73 +N07 17.06 29.9 17.13 +N08 54.05 58.63 61.58 +N09 49.41 57.82 58.22 +N10 16.9 12.02 19.29 +N11 41.76 29.82 32.52 +N12 74.67 77.43 64.28 +O01 3.02 3.13 2.71 +O02 47.1 42.51 31.08 +O03 51.87 42.51 15.81 +O04 77.2 77.91 50.55 +O05 45.99 42.6 4.49 +O06 23.64 29.5 29.06 +O07 26.97 42.73 19.28 +O08 27.97 29.35 28.33 +O09 50.32 57.45 48.38 +O10 23.06 19.58 23.21 +O11 32.18 29.25 34.95 +O12 3.01 3.12 2.7 +P01 74.64 77.41 64.32 +P02 44.39 42.98 33.4 +P03 71.49 59.42 23.1 +P04 79.86 78.26 38.44 +P05 31.59 29.6 5.37 +P06 20.07 28.76 23.92 +P07 31.22 42.07 27.31 +P08 17.15 18.99 23.19 +P09 37.97 42.95 38.15 +P10 19.91 19.24 17.99 +P11 44.36 43.41 45.48 +P12 18.95 19.68 16.49 +Q01 18.96 19.69 16.51 +Q02 59.99 58.87 41.85 +Q03 67.98 58.85 30.96 +Q04 82.15 79.03 48.34 +Q05 33.18 29.48 5.74 +Q06 18.92 29.39 27.97 +Q07 44.1 58.65 39.14 +Q08 37.51 41.38 26.69 +Q09 40.27 42.04 17.38 +Q10 24.86 28.48 22.3 +Q11 9.43 11.28 9.5 +Q12 74.61 77.37 64.24 +R01 3.05 3.16 2.74 +R02 31.16 30.09 20.86 +R03 56.92 56.98 36.53 +R04 79.37 78.57 56.95 +R05 42.68 42.54 8.26 +R06 28.15 41.91 31.53 +R07 48.61 58.02 33.46 +R08 26.81 28.91 16.95 +R09 39.83 43.08 12.47 +R10 11.8 11.72 5.87 +R11 17.1 19.71 16.41 +R12 3.02 3.13 2.71 +S01 74.66 77.43 64.34 +S02 40.67 42.42 26.09 +S03 65.09 68.67 41.71 +S04 3.01 3.34 15.4 +S05 3.26 11.22 2.89 +S06 17.7 8.11 0.42 +S07 89.01 92.27 74.63 +S08 0.28 0.29 0.24 +S09 72.92 74.82 4.56 +S10 17.03 7.57 3.05 +S11 6.56 11.29 24.29 +S12 18.91 19.64 16.46 +T01 18.91 19.64 16.46 +T02 3.05 3.16 2.73 +T03 74.38 77.15 64.2 +T04 18.94 19.68 16.48 +T05 3.12 3.24 2.79 +T06 74.2 76.97 63.98 +T07 18.87 19.61 16.43 +T08 3.04 3.16 2.73 +T09 74.41 77.19 64.05 +T10 18.9 19.63 16.46 +T11 3.09 3.2 2.78 +T12 74.57 77.32 64.19 + diff --git a/scanin/ColorCheckerPassport.cht b/scanin/ColorCheckerPassport.cht new file mode 100644 index 0000000..758cad7 --- /dev/null +++ b/scanin/ColorCheckerPassport.cht @@ -0,0 +1,122 @@ +BOXES 51 + F _ _ 97.0 17.0 157.3 17.0 157.3 107.0 97.0 107.0 + D ALL ALL _ _ 59.0 5.0 98.0 11.0 0.0 0.0 + X SAT SAT 1 8 10.0 10.0 13.5 102.1 0.0 -12.9 + X WBP WBP 1 5 13.4 13.4 26.4 87.0 0.0 -16.0 + X WBL WBL 1 5 13.4 13.4 42.5 87.0 0.0 -16.0 + X NEU NEU 1 8 10.0 10.0 58.6 102.1 0.0 -12.9 + X A D 1 6 12.4 12.4 98.5 93.4 15.0 -15.0 + +BOX_SHRINK 2.0 + +REF_ROTATION 0.0 + +XLIST 16 + 13.5 1.0 1.0 + 23.5 1.0 1.0 + 26.4 1.0 1.0 + 39.8 1.0 1.0 + 42.5 1.0 1.0 + 55.9 1.0 1.0 + 58.6 1.0 1.0 + 68.6 1.0 1.0 + 98.5 1.0 1.0 + 110.9 1.0 1.0 + 113.5 1.0 1.0 + 125.9 1.0 1.0 + 128.5 1.0 1.0 + 140.9 1.0 1.0 + 143.5 1.0 1.0 + 155.9 1.0 1.0 + +YLIST 38 + 11.5 1.0 1.0 + 18.5 1.0 1.0 + 21.6 1.0 1.0 + 23.4 1.0 1.0 + 24.3 1.0 1.0 + 30.9 1.0 1.0 + 33.5 1.0 1.0 + 34.6 1.0 1.0 + 36.5 1.0 1.0 + 37.2 1.0 1.0 + 39.2 1.0 1.0 + 45.8 1.0 1.0 + 47.5 1.0 1.0 + 48.4 1.0 1.0 + 50.2 1.0 1.0 + 52.5 1.0 1.0 + 55.2 1.0 1.0 + 60.4 1.0 1.0 + 60.7 1.0 1.0 + 63.1 1.0 1.0 + 63.4 1.0 1.0 + 68.4 1.0 1.0 + 71.1 1.0 1.0 + 73.3 1.0 1.0 + 75.7 1.0 1.0 + 76.1 1.0 1.0 + 78.4 1.0 1.0 + 84.3 1.0 1.0 + 86.3 1.0 1.0 + 87.0 1.0 1.0 + 89.0 1.0 1.0 + 90.6 1.0 1.0 + 93.4 1.0 1.0 + 99.4 1.0 1.0 + 100.4 1.0 1.0 + 102.1 1.0 1.0 + 105.7 1.0 1.0 + 112.4 1.0 1.0 + +EXPECTED XYZ +SAT1 31.444334 19.286094 6.888559 +SAT2 56.064662 44.030373 6.427599 +SAT3 67.324242 67.447159 7.468562 +SAT4 15.570651 29.465796 11.20434 +SAT5 21.619963 29.778971 41.25516 +SAT6 17.456572 19.372800 46.61877 +SAT7 24.114288 18.910816 30.96444 +SAT8 30.360635 18.858573 16.93814 +WBP1 55.603171 57.729295 46.42132 +WBP2 57.049606 60.324512 49.89966 +WBP3 53.811668 58.177050 49.42470 +WBP4 52.378305 57.343255 49.64556 +WBP5 52.469763 58.680177 51.97625 +WBL1 59.661034 59.332741 48.55177 +WBL2 59.041480 59.368909 48.29234 +WBL3 55.920447 58.052670 47.03935 +WBL4 55.083575 58.526581 51.10275 +WBL5 53.892264 58.200472 53.59833 +NEU1 3.151107 3.263644 2.737095 +NEU2 3.610326 3.768524 3.225077 +NEU3 4.585675 4.814770 4.063276 +NEU4 5.242110 5.523981 4.582603 +NEU5 44.365128 46.364955 37.75652 +NEU6 55.836099 58.281967 47.53593 +NEU7 70.627230 73.603361 59.69403 +NEU8 88.638466 92.368156 71.51666 +A1 11.411919 10.072672 5.112897 +A2 38.118655 34.074205 18.53409 +A3 16.687521 18.224488 25.41503 +A4 11.119565 13.272712 5.165291 +A5 23.995041 23.022599 32.25695 +A6 29.864887 41.242607 33.61720 +B1 40.774497 30.980646 4.853984 +B2 12.786912 11.654674 29.31582 +B3 29.900282 19.631992 10.31426 +B4 8.854344 6.750602 10.88177 +B5 35.445183 44.094908 8.863355 +B6 49.113465 43.647237 6.214123 +C1 6.659992 5.799339 20.11315 +C2 15.407588 23.700772 7.772715 +C3 21.254733 12.710445 3.970060 +C4 58.616280 59.203678 6.871706 +C5 31.444170 20.458848 23.34756 +C6 13.290512 19.046913 29.20373 +D1 87.016740 90.636247 69.99650 +D2 57.632418 59.860806 48.52846 +D3 35.434916 36.927843 30.23039 +D4 18.558911 19.319142 15.73822 +D5 8.770657 9.165214 7.636996 +D6 3.216922 3.320339 2.732945 diff --git a/scanin/ColorCheckerPassport.cie b/scanin/ColorCheckerPassport.cie new file mode 100644 index 0000000..f25c019 --- /dev/null +++ b/scanin/ColorCheckerPassport.cie @@ -0,0 +1,64 @@ +CTI3 +DESCRIPTOR "ColorChecker Passport CIE data" +ORIGINATOR "Ben Goren " +CREATED "Fri Aug 3 15:35:05 MST 2012" + +KEYWORD "SAMPLE_LOC" +NUMBER_OF_FIELDS 7 +BEGIN_DATA_FORMAT +SAMPLE_LOC XYZ_X XYZ_Y XYZ_Z LAB_L LAB_A LAB_B +END_DATA_FORMAT + +NUMBER_OF_SETS 50 +BEGIN_DATA +SAT1 31.444334 19.286094 6.888559 51.020256 55.280672 28.133194 +SAT2 56.064662 44.030373 6.427599 72.248793 36.945117 66.729238 +SAT3 67.324242 67.447159 7.468562 85.729258 5.091307 85.588609 +SAT4 15.570651 29.465796 11.204340 61.190534 -60.437314 30.279584 +SAT5 21.619963 29.778971 41.255169 61.463043 -30.131006 -25.196180 +SAT6 17.456572 19.372800 46.618774 51.120542 -6.455450 -49.629615 +SAT7 24.114288 18.910816 30.964446 50.582702 28.026310 -29.474885 +SAT8 30.360635 18.858573 16.938149 50.521331 53.431168 -3.299773 +WBP1 55.603171 57.729295 46.421327 80.588052 -0.148185 1.410213 +WBP2 57.049606 60.324512 49.899666 82.014259 -2.717710 -0.156044 +WBP3 53.811668 58.177050 49.424708 80.837125 -5.740350 -1.647214 +WBP4 52.378305 57.343255 49.645561 80.372273 -7.424711 -2.699450 +WBP5 52.469763 58.680177 51.976257 81.115480 -10.390873 -4.020205 +WBL1 59.661034 59.332741 48.551776 81.474151 5.919789 0.449649 +WBL2 59.041480 59.368909 48.292349 81.493953 4.354460 0.782852 +WBL3 55.920447 58.052670 47.039351 80.768065 -0.134018 0.991035 +WBL4 55.083575 58.526581 51.102758 81.030672 -3.356452 -3.200486 +WBL5 53.892264 58.200472 53.598335 80.850119 -5.590938 -6.243136 +NEU1 3.151107 3.263644 2.737095 21.070257 0.072763 -0.353478 +NEU2 3.610326 3.768524 3.225077 22.890939 -0.358852 -0.826826 +NEU3 4.585675 4.814770 4.063276 26.200395 -0.743922 -0.554941 +NEU4 5.242110 5.523981 4.582603 28.178271 -1.007717 -0.143878 +NEU5 44.365128 46.364955 37.756524 73.781723 -0.983457 0.663808 +NEU6 55.836099 58.281967 47.535933 80.895303 -0.892210 0.628840 +NEU7 70.627230 73.603361 59.694037 88.734687 -0.724494 1.018307 +NEU8 88.638466 92.368156 71.516660 96.970594 -0.771975 4.070471 +A1 11.411919 10.072672 5.112897 37.972545 12.849750 13.905933 +A2 38.118655 34.074205 18.534096 65.021429 17.736538 18.105244 +A3 16.687521 18.224488 25.415039 49.767263 -4.838656 -21.688821 +A4 11.119565 13.272712 5.165291 43.171313 -11.673243 22.599880 +A5 23.995041 23.022599 32.256955 55.095608 8.054000 -23.674108 +A6 29.864887 41.242607 33.617201 70.345563 -33.879730 0.591375 +B1 40.774497 30.980646 4.853984 62.491292 36.974257 57.538878 +B2 12.786912 11.654674 29.315826 40.661930 10.745627 -43.972357 +B3 29.900282 19.631992 10.314269 51.418556 47.835790 16.229131 +B4 8.854344 6.750602 10.881778 31.232269 21.992198 -20.376399 +B5 35.445183 44.094908 8.863355 72.291888 -22.389553 57.145982 +B6 49.113465 43.647237 6.214123 71.992078 20.037754 67.243006 +C1 6.659992 5.799339 20.113152 28.900464 11.613838 -47.531575 +C2 15.407588 23.700772 7.772715 55.786947 -38.099805 32.761011 +C3 21.254733 12.710445 3.970060 42.323678 50.646029 27.808803 +C4 58.616280 59.203678 6.871706 81.403423 3.722966 80.589317 +C5 31.444170 20.458848 23.347563 52.352077 49.539466 -13.465303 +C6 13.290512 19.046913 29.203736 50.742046 -29.398805 -26.412062 +D1 87.016740 90.636247 69.996509 96.260066 -0.692605 4.206323 +D2 57.632418 59.860806 48.528468 81.762472 -0.207864 0.973581 +D3 35.434916 36.927843 30.230398 67.222860 -0.574879 0.364223 +D4 18.558911 19.319142 15.738222 51.058515 -0.355289 0.481164 +D5 8.770657 9.165214 7.636996 36.300462 -0.566396 -0.303560 +D6 3.216922 3.320339 2.732945 21.283684 0.258119 0.046995 +END_DATA diff --git a/scanin/ColorCheckerSG.cht b/scanin/ColorCheckerSG.cht new file mode 100644 index 0000000..1836f73 --- /dev/null +++ b/scanin/ColorCheckerSG.cht @@ -0,0 +1,203 @@ + +BOXES 141 + F _ _ 26.09 18.7 239.15 18.7 239.15 171.9 26.09 171.9 + D ALL ALL _ _ 263.95 185.5 0 0 0 0 + X A N 1 10 12.675 12.75 27.5 20.0 15.175 15.25 + +BOX_SHRINK 1.6 + +XLIST 28 + 27.5 1.0 1.0 + 40.175 1.0 1.0 + 42.675 1.0 1.0 + 55.35 1.0 1.0 + 57.85 1.0 1.0 + 70.525 1.0 1.0 + 73.025 1.0 1.0 + 85.7 1.0 1.0 + 88.2 1.0 1.0 + 100.875 1.0 1.0 + 103.375 1.0 1.0 + 116.05 1.0 1.0 + 118.55 1.0 1.0 + 131.225 1.0 1.0 + 133.725 1.0 1.0 + 146.4 1.0 1.0 + 148.9 1.0 1.0 + 161.575 1.0 1.0 + 164.075 1.0 1.0 + 176.75 1.0 1.0 + 179.25 1.0 1.0 + 191.925 1.0 1.0 + 194.425 1.0 1.0 + 207.1 1.0 1.0 + 209.6 1.0 1.0 + 222.275 1.0 1.0 + 224.775 1.0 1.0 + 237.45 1.0 1.0 + +YLIST 20 + 20.0 1.0 1.0 + 32.75 1.0 1.0 + 35.25 1.0 1.0 + 48.0 1.0 1.0 + 50.5 1.0 1.0 + 63.25 1.0 1.0 + 65.75 1.0 1.0 + 78.5 1.0 1.0 + 81.0 1.0 1.0 + 93.75 1.0 1.0 + 96.25 1.0 1.0 + 109.0 1.0 1.0 + 111.5 1.0 1.0 + 124.25 1.0 1.0 + 126.75 1.0 1.0 + 139.5 1.0 1.0 + 142.0 1.0 1.0 + 154.75 1.0 1.0 + 157.25 1.0 1.0 + 170.0 1.0 1.0 + + +EXPECTED XYZ 140 + A1 88.25 87.51 67.62 + A2 0.79 0.79 0.62 + A3 18.38 18.15 14.12 + A4 88.68 87.94 68.1 + A5 0.82 0.81 0.66 + A6 18.44 18.2 14.18 + A7 88.65 87.9 67.95 + A8 0.83 0.82 0.66 + A9 18.12 17.89 13.95 + A10 88.87 88.13 68.08 + B1 18.02 17.8 13.91 + B2 13.95 7.23 8.27 + B3 35.63 27.85 32.84 + B4 10.67 5.28 15.25 + B5 14.41 15.79 39.4 + B6 20.68 26.24 36.89 + B7 1.45 2.35 2.56 + B8 18.04 25.72 27.04 + B9 3.38 3.27 1.58 + B10 18.48 18.24 14.19 + C1 0.83 0.81 0.66 + C2 4.58 3.29 5.62 + C3 14.6 11.31 24.29 + C4 2.74 2.49 8.91 + C5 22.92 25.79 40.25 + C6 1.84 2.4 5.03 + C7 26.45 26.69 42.35 + C8 10.25 16.92 17.28 + C9 19.05 27.21 12.27 + C10 0.81 0.8 0.64 + D1 88.5 87.75 67.91 + D2 61.95 61.45 55.8 + D3 70.83 63.53 49.33 + D4 55.96 62.69 49.91 + D5 71.17 64.56 44.57 + D6 58.43 62.22 28.86 + D7 38.57 30.13 8.72 + D8 38.93 32.31 15.64 + D9 9.71 17.25 8.69 + D10 88.85 88.1 68.15 + E1 18.14 17.91 13.97 + E2 8.92 6.95 2.01 + E3 39.66 29.42 2.06 + E4 3.85 2.22 16.31 + E5 88.54 87.8 67.91 + E6 0.8 0.79 0.64 + E7 57.95 50.11 24.14 + E8 55.65 45.09 20.47 + E9 1.8 2.87 1.55 + E10 18.29 18.05 14.05 + F1 0.82 0.81 0.65 + F2 37.55 31.16 14.86 + F3 9.34 7.46 25.35 + F4 12.16 19.3 4.13 + F5 54.56 53.71 42.14 + F6 6.41 6.34 5.07 + F7 35.94 31.61 12.54 + F8 37.12 32.69 16.79 + F9 17.63 26.21 16.52 + F10 0.82 0.8 0.65 + G1 88.12 87.38 67.64 + G2 14.14 14.42 21.78 + G3 27.07 16.15 6.53 + G4 19.38 9.32 1.23 + G5 33.43 32.97 25.94 + G6 11.06 10.95 8.66 + G7 16.15 13.52 3.95 + G8 37.66 32.45 16.85 + G9 21.4 28.64 6.94 + G10 88.76 88.01 68.03 + H1 18.23 18 14.03 + H2 7.94 10.03 2.21 + H3 5.33 3.13 7.61 + H4 58.28 57.39 3.84 + H5 18.06 17.83 13.93 + H6 27.87 27.48 21.66 + H7 40.98 36.13 18.85 + H8 38.13 32.77 16.09 + H9 10.91 18.91 3.26 + H10 18.32 18.08 14.08 + I1 0.88 0.87 0.69 + I2 20.96 18.51 28.03 + I3 33.58 40.91 5.29 + I4 28.76 16.58 19.42 + I5 8.34 8.25 6.47 + I6 47.53 46.8 36.74 + I7 18.56 14.28 2.54 + I8 10.92 8.92 2.27 + I9 17.44 28.57 5.55 + I10 0.82 0.81 0.65 + J1 88.45 87.71 67.89 + J2 28.25 36.79 28.98 + J3 46.48 40.82 3.05 + J4 10.73 14.67 25.45 + J5 1.95 1.94 1.63 + J6 72.43 71.6 56.6 + J7 39 31.84 12.66 + J8 41.29 34.62 13.36 + J9 34.26 30.19 5.4 + J10 88.69 87.94 67.95 + K1 18.29 18.06 14.09 + K2 69.8 64.78 36.61 + K3 65.69 71.95 50.54 + K4 65.74 62.36 54.38 + K5 56.64 60.89 55.78 + K6 40.88 40.32 31.77 + K7 14.74 14.56 11.28 + K8 2.93 2.89 2.29 + K9 26.26 30.23 4.54 + K10 18.27 18.04 14.06 + L1 0.86 0.85 0.69 + L2 6.16 3.5 1.81 + L3 26.34 13.44 1.4 + L4 38.55 28.09 19.93 + L5 39.77 29.23 14.66 + L6 46.55 31.09 1.68 + L7 40.32 44.89 2.28 + L8 30.88 30.54 4.31 + L9 34.35 43.52 4.2 + L10 0.8 0.79 0.64 + M1 18.19 17.97 14.01 + M2 23.95 12.47 6.9 + M3 4.92 2.88 3.25 + M4 22.84 11.31 2.24 + M5 37.86 20.94 3.23 + M6 68.62 59.75 4.77 + M7 62.14 60.57 3.46 + M8 36.4 42.08 3.08 + M9 3.85 2.98 0.82 + M10 18.24 18.01 14.03 + N1 88.23 87.51 67.77 + N2 18.24 18.01 14.03 + N3 0.9 0.89 0.72 + N4 88.57 87.82 67.97 + N5 18.12 17.9 13.96 + N6 0.91 0.9 0.73 + N7 88.71 87.96 67.97 + N8 18.2 17.97 14 + N9 0.84 0.83 0.67 + N10 88.82 88.07 68.12 + diff --git a/scanin/Hutchcolor.cht b/scanin/Hutchcolor.cht new file mode 100644 index 0000000..fcc5135 --- /dev/null +++ b/scanin/Hutchcolor.cht @@ -0,0 +1,597 @@ + +BOXES 639 + F _ _ 99.5 25.5 815.5 25.5 816.5 565.5 99.5 565.5 + D ALL ALL _ _ 716 540 99.5 25.5 0 0 + Y 01 29 A V 24.689655 24.545454 99.5 25.5 24.689655 24.545454 + +BOX_SHRINK 3.0 + +REF_ROTATION 0.0 + +XLIST 29 + 100.0 0.362323 0.148148 + 110.211740 0.039102 0.222222 + 125.481836 0.971171 0.333333 + 150.418808 0.792286 0.925926 + 174.477814 0.734537 0.962963 + 199.527718 0.787966 1.000000 + 224.576901 0.650620 0.925926 + 248.755279 0.417736 0.888889 + 274.032480 0.613223 0.888889 + 298.327154 0.543354 0.925926 + 323.197333 0.847712 0.925926 + 347.120895 0.812650 0.925926 + 372.370502 0.860240 0.777778 + 396.353101 0.679006 0.703704 + 421.201328 1.000000 0.814815 + 446.684199 0.456817 0.703704 + 470.550542 0.508343 0.740741 + 495.397842 0.625561 0.703704 + 520.420248 0.386812 0.777778 + 544.869239 0.452824 0.777778 + 569.748767 0.547266 0.666667 + 594.755774 0.465053 0.666667 + 618.496351 0.477468 0.703704 + 644.014919 0.454719 0.703704 + 668.040606 0.479467 0.666667 + 693.095409 0.514558 0.666667 + 717.270886 0.882612 0.666667 + 791.542805 0.771497 0.444444 + 817.003432 0.882693 0.111111 + +YLIST 24 + 25.546595 1.000000 0.071429 + 49.424472 0.975749 0.392857 + 75.392921 0.738973 0.964286 + 99.186517 0.910072 1.000000 + 124.186786 0.852166 0.964286 + 149.214757 0.795826 0.892857 + 173.106047 0.641529 0.857143 + 198.089764 0.742257 0.928571 + 223.213674 0.604765 0.928571 + 246.745099 0.949854 1.000000 + 271.506325 0.862745 0.857143 + 294.880215 0.786340 0.571429 + 320.004798 0.644361 0.750000 + 344.432584 0.421439 0.857143 + 369.861483 0.378724 0.678571 + 393.074962 0.877958 0.964286 + 418.078441 0.680991 1.000000 + 442.078222 0.783297 1.000000 + 466.901848 0.648933 0.678571 + 491.506012 0.239702 0.642857 + 515.663175 0.154566 0.285714 + 524.564065 0.106932 0.250000 + 540.560259 0.769595 0.250000 + 565.915658 0.797211 0.178571 + +EXPECTED XYZ 528 + A01 76.63 79.337 62.787 + A15 0.049 0.047 0.04 + A16 76.799 79.369 62.869 + A29 76.788 79.423 62.902 + B01 0.051 0.046 0.042 + B02 23.742 12.069 27.69 + B03 29.571 17.273 33.401 + B04 36.377 24.341 39.101 + B05 46.402 36.285 46.046 + B06 60.163 54.778 54.102 + B07 76.815 79.257 62.889 + B08 70.22 73.135 37.781 + B09 52.398 46.914 32.877 + B10 37.18 27.08 27.417 + B11 25.856 14.882 21.359 + B12 19.163 9.224 17.005 + B13 12.41 5.017 11.384 + B14 68.099 66.231 58.21 + B15 64.604 64.824 58.092 + B16 58.787 61.057 57.489 + B17 60.985 65.447 59.249 + B18 62.617 69.06 60.756 + B19 61.499 67.999 56.83 + B20 59.996 66.835 49.738 + B21 66.383 71.172 50.262 + B22 72.856 75.172 50.47 + B23 68.187 68.027 48.999 + B24 63.438 60.952 47.208 + B25 65.486 62.759 54.536 + B26 74.738 77.87 62.671 + B27 76.752 79.251 62.956 + B28 72.734 74.343 59.875 + B29 0.046 0.043 0.032 + C01 21.633 22.888 20.349 + C02 18.412 9.88 27.737 + C03 22.631 14.555 33.706 + C04 27.389 20.594 38.954 + C05 34.465 30.776 45.359 + C06 43.817 46.079 52.702 + C07 51.156 60.04 58.504 + C08 46.443 56.25 36.915 + C09 37.868 39.579 33.063 + C10 27.157 22.631 27.438 + C11 19.372 12.293 21.901 + C12 14.769 7.361 17.468 + C13 9.986 4.001 11.409 + C14 53.009 44.867 50.025 + C15 43.073 40.486 49.663 + C16 33.474 35.535 49.096 + C17 39.616 46.653 54.254 + C18 43.877 54.8 57.684 + C19 39.842 51.529 40.856 + C20 37.241 49.298 27.293 + C21 49.103 57.6 26.678 + C22 68.052 71.088 26.663 + C23 54.158 50.585 23.324 + C24 42.126 34.204 20.788 + C25 44.759 35.882 34.073 + C26 63.526 65.924 58.034 + C27 66.134 68.606 57.21 + C28 66.402 69.263 52.556 + C29 21.945 23.311 20.081 + D02 11.393 6.774 27.149 + D03 14.898 11.118 33.316 + D04 18.919 16.908 38.782 + D05 25.042 26.809 45.487 + D06 32.814 40.626 52.643 + D07 38.506 50.724 57.005 + D08 34.084 47.3 37.959 + D09 27.203 34.516 34.19 + D10 18.226 18.563 28.41 + D11 11.924 8.905 22.544 + D12 8.489 4.576 17.784 + D13 5.402 2.081 11.094 + D14 41.275 29.968 42.582 + D15 28.108 24.154 42.115 + D16 20.099 21.735 43.019 + D17 29.182 37.879 52.109 + D18 35.153 47.891 56.53 + D19 30.314 44.189 35.897 + D20 26.406 40.305 16.077 + D21 38.111 48.316 13.175 + D22 65.451 67.965 13.429 + D23 43.805 37.363 9.249 + D24 27.598 18.034 7.037 + D25 30.174 19.545 20.547 + D26 58.48 57.966 51.192 + D27 54.554 56.734 46.744 + D28 53.009 56.386 44.417 + E02 8.386 5.781 27.763 + E03 11.574 10.412 34.225 + E04 15.311 16.641 40.002 + E05 21.099 27.099 47.037 + E06 27.464 38.835 53.265 + E07 30.583 43.614 55.324 + E08 27.553 41.253 43.72 + E09 23.131 33.91 40.619 + E10 15.049 18.612 33.316 + E11 9.165 8.213 26.012 + E12 5.821 3.476 19.352 + E13 3.178 1.134 11.065 + E14 32.772 20.441 36.137 + E15 18.574 14.486 36.000 + E16 12.165 13.283 37.532 + E17 20.936 30.082 49.114 + E18 26.179 39.081 53.662 + E19 21.215 35.148 32.511 + E20 16.763 30.052 8.608 + E21 30.574 41.333 6.293 + E22 63.883 65.154 6.804 + E23 36.079 27.5 3.064 + E24 18.426 9.673 1.782 + E25 20.328 10.668 11.479 + E26 47.129 50.747 43.494 + E27 45.528 47.626 39.123 + E28 44.554 44.762 35.204 + F02 6.368 4.959 27.103 + F03 8.954 9.421 33.626 + F04 12.046 15.412 39.432 + F05 16.445 24.385 45.858 + F06 20.113 31.659 50.153 + F07 22.051 34.426 51.578 + F08 19.632 32.109 44.547 + F09 17.001 27.957 42.024 + F10 11.577 16.618 35.22 + F11 6.918 7.101 27.029 + F12 4.309 2.758 19.695 + F13 2.222 0.731 10.705 + F14 26.945 14.78 30.904 + F15 12.401 8.777 30.923 + F16 6.658 6.438 29.4 + F17 12.797 19.297 42.136 + F18 18.427 29.885 49.126 + F19 12.294 24.337 23.523 + F20 8.47 18.427 2.954 + F21 25.113 35.116 2.692 + F22 62.917 62.389 3.348 + F23 29.138 19.14 0.691 + F24 12.647 5.718 0.185 + F25 14.014 6.371 5.555 + F26 35.636 36.998 34.385 + F27 37.357 39.073 32.505 + F28 39.18 41.212 29.994 + G02 4.654 3.718 23.728 + G03 6.283 6.908 29.334 + G04 8.163 11.056 34.327 + G05 10.842 17.236 39.952 + G06 13.027 21.956 43.616 + G07 14.821 24.858 45.838 + G08 12.501 21.969 39.898 + G09 10.848 18.953 37.473 + G10 7.763 11.612 31.571 + G11 5.023 5.215 24.355 + G12 3.357 2.126 17.864 + G13 1.743 0.552 9.45 + G14 13.383 5.464 14.796 + G15 4.308 1.645 13.987 + G16 2.167 0.77 11.785 + G17 6.278 7.264 29.187 + G18 12.468 21.262 42.54 + G19 7.159 16.892 13.939 + G20 4.6 10.846 0.834 + G21 19.409 27.107 1.076 + G22 47.378 44.339 1.058 + G23 22.289 13.428 0.239 + G24 8.959 3.816 0.018 + G25 9.579 4.041 2.544 + G26 31.736 31.893 28.491 + G27 30.165 31.682 26.269 + G28 29.662 31.861 25.568 + H02 0.461 0.186 2.441 + H03 0.941 0.992 4.564 + H04 1.756 3.154 6.521 + H05 3.582 8.288 8.926 + H06 6.013 14.762 11.175 + H07 7.642 17.876 13.524 + H08 9.843 19.999 25.663 + H09 8.177 16.912 23.1 + H10 5.372 9.823 18.883 + H11 3.192 4.082 14.531 + H12 2.003 1.475 10.492 + H13 1.061 0.343 5.739 + H14 6.674 2.663 8.453 + H15 2.34 0.823 8.659 + H16 1.424 0.443 7.72 + H17 3.7 3.583 18.392 + H18 8.309 14.901 28.931 + H19 4.341 11.205 6.88 + H20 3.147 7.651 0.625 + H21 10.944 16.126 0.762 + H22 21.411 20.364 0.606 + H23 9.9 6.02 0.151 + H24 5.002 2.171 0.019 + H25 5.207 2.252 1.331 + H26 26.152 28.536 24.809 + H27 24.71 26.089 21.71 + H28 23.442 23.841 19.131 + I02 0.623 0.275 2.27 + I03 1.358 1.348 4.048 + I04 2.894 4.478 5.928 + I05 6.469 12.434 8.339 + I06 11.078 22.462 10.722 + I07 13.785 26.952 13.421 + I08 16.457 29.743 27.76 + I09 13.658 25.303 24.605 + I10 8.595 14.351 20.015 + I11 4.549 5.587 14.961 + I12 2.594 1.929 10.771 + I13 1.342 0.462 6.167 + I14 2.562 1.067 3.842 + I15 1.095 0.427 4.104 + I16 0.725 0.257 3.88 + I17 1.545 1.606 7.557 + I18 3.219 6.001 11.357 + I19 1.747 4.545 2.842 + I20 1.353 3.291 0.356 + I21 4.249 6.369 0.411 + I22 7.927 7.76 0.334 + I23 3.799 2.502 0.109 + I24 1.902 0.861 0.02 + I25 1.978 0.901 0.681 + I26 19.442 20.5 19.781 + I27 19.851 21.168 17.794 + I28 20.769 22.202 16.051 + J02 1.401 0.622 2.136 + J03 2.702 2.007 3.488 + J04 5.051 5.588 5.045 + J05 9.951 14.434 7.059 + J06 16.982 27.791 9.331 + J07 21.361 35.241 11.98 + J08 23.982 38.364 25.345 + J09 19.362 30.687 21.964 + J10 11.868 16.245 17.578 + J11 6.56 6.591 13.379 + J12 3.902 2.573 9.871 + J13 2.147 0.819 6.098 + J14 0.76 0.365 1.233 + J15 0.36 0.181 1.226 + J16 0.239 0.122 1.194 + J17 0.451 0.554 1.991 + J18 0.797 1.511 2.705 + J19 0.492 1.178 0.84 + J20 0.405 0.916 0.16 + J21 0.959 1.409 0.164 + J22 2.126 2.146 0.166 + J23 1.144 0.84 0.077 + J24 0.574 0.286 0.025 + J25 0.588 0.301 0.282 + J26 15.996 16.353 15.287 + J27 15.535 16.669 14.029 + J28 15.219 16.756 13.611 + K02 3.453 1.498 2.025 + K03 5.457 3.199 3.005 + K04 8.24 6.666 4.026 + K05 13.803 15.032 5.462 + K06 22.068 29.259 7.331 + K07 28.861 41.569 10.129 + K08 30.536 43.905 20.585 + K09 23.641 31.285 17.109 + K10 15.215 16.368 13.852 + K11 9.442 7.446 10.876 + K12 6.523 3.691 8.576 + K13 4.218 1.708 5.864 + K14 0.11 0.08 0.178 + K15 0.057 0.052 0.165 + K16 0.056 0.05 0.163 + K17 0.084 0.11 0.219 + K18 0.12 0.202 0.266 + K19 0.097 0.169 0.114 + K20 0.092 0.152 0.055 + K21 0.091 0.149 0.054 + K22 0.176 0.204 0.055 + K23 0.118 0.109 0.036 + K24 0.083 0.058 0.024 + K25 0.084 0.062 0.055 + K26 13.207 14.81 13.496 + K27 11.931 12.895 11.183 + K28 11.35 11.769 9.683 + L01 76.732 79.364 62.827 + L02 7.664 3.259 1.993 + L03 11.545 5.898 2.9 + L04 15.727 10.146 3.785 + L05 23.087 19.47 4.953 + L06 33.342 35.063 6.642 + L07 41.546 50.533 9.282 + L08 43.151 53.11 19.221 + L09 34.773 37.02 16.135 + L10 24.286 20.62 13.122 + L11 16.886 10.882 10.491 + L12 12.652 6.416 8.353 + L13 8.532 3.519 5.826 + L14 76.675 79.226 62.699 + L15 0.038 0.035 0.025 + L16 21.288 22.639 19.359 + L26 9.11 9.854 9.906 + L27 9.204 10.05 8.65 + L28 9.602 10.532 7.77 + L29 0.04 0.037 0.028 + M02 9.87 4.175 1.899 + M03 15.719 7.67 2.788 + M04 22.009 12.713 3.541 + M05 32.688 23.723 4.613 + M06 47.45 42.107 6.039 + M07 64.575 66.511 9.359 + M08 66.43 69.356 18.887 + M09 48.955 44.07 15.064 + M10 34.018 24.945 12.469 + M11 23.221 13.444 9.974 + M12 16.908 8.226 8.018 + M13 10.7 4.424 5.556 + M14 37.403 32.664 35.56 + M15 32.819 30.306 35.072 + M16 26.055 26.69 34.653 + M17 31.517 36.319 38.023 + M18 34.22 41.544 39.547 + M19 33.174 40.732 33.899 + M20 31.317 39.16 23.785 + M21 39.198 43.977 23.638 + M22 45.035 47.614 23.798 + M23 41.489 41.406 22.88 + M24 34.664 30.711 20.744 + M25 36.343 31.891 30.185 + M26 7.308 7.575 7.29 + M27 7.054 7.689 6.661 + M28 6.736 7.597 6.317 + N02 9.564 4.071 0.433 + N03 15.244 7.361 0.692 + N04 21.49 12.159 0.981 + N05 32.074 22.601 1.513 + N06 46.699 40.175 2.375 + N07 63.358 63.683 4.666 + N08 61.976 59.689 1.924 + N09 46.634 38.442 0.816 + N10 32.085 21.804 0.415 + N11 21.453 11.832 0.181 + N12 15.04 7.149 0.074 + N13 9.388 3.991 0.02 + N14 35.079 32.892 32.747 + N15 32.606 31.487 32.409 + N16 28.131 29.186 32.205 + N17 31.664 35.404 34.064 + N18 33.404 38.542 34.958 + N19 32.65 37.87 31.68 + N20 31.542 36.992 25.464 + N21 36.414 39.679 25.151 + N22 39.129 41.364 25.394 + N23 37.199 38.042 24.882 + N24 33.221 31.488 23.357 + N25 34.4 32.364 29.693 + N26 5.531 6.401 6.067 + N27 4.987 5.505 4.891 + N28 4.581 4.801 4.063 + O02 7.307 3.137 0.433 + O03 11.063 5.574 0.707 + O04 15.275 9.584 1.061 + O05 22.42 18.23 1.628 + O06 32.349 32.649 2.497 + O07 40.54 47.841 4.313 + O08 40.237 44.49 1.571 + O09 32.794 30.944 0.812 + O10 22.853 17.525 0.434 + O11 15.44 9.303 0.194 + O12 11.054 5.451 0.077 + O13 7.224 3.094 0.021 + O14 34.294 34.203 31.000 + O15 33.121 33.542 30.87 + O16 31.021 32.405 30.573 + O17 32.709 35.229 31.551 + O18 33.535 36.782 31.879 + O19 33.11 36.372 30.011 + O20 32.623 35.989 27.478 + O21 34.678 37.087 27.421 + O22 35.836 37.705 27.441 + O23 35.015 36.226 27.209 + O24 33.385 33.432 26.6 + O25 34.104 34.07 29.423 + O26 3.264 3.634 3.923 + O27 3.356 3.715 3.454 + O28 3.505 3.974 3.077 + P02 3.123 1.387 0.434 + P03 4.978 2.868 0.72 + P04 7.69 6.024 1.097 + P05 13.026 13.656 1.794 + P06 20.866 26.635 2.733 + P07 27.647 38.762 4.545 + P08 26.873 34.908 1.482 + P09 20.633 24.173 0.833 + P10 13.01 12.581 0.452 + P11 7.668 5.626 0.201 + P12 4.955 2.744 0.083 + P13 3.065 1.355 0.022 + P14 11.506 6.825 13.879 + P15 7.899 5.228 14.444 + P16 5.052 4.19 17.555 + P17 10.715 14.734 26.092 + P18 15.327 24.08 30.67 + P19 13.062 22.129 18.974 + P20 10.514 18.873 5.22 + P21 16.35 20.537 3.911 + P22 21.802 22.81 3.581 + P23 16.148 14.308 2.827 + P24 9.332 5.626 1.729 + P25 10.413 6.295 7.89 + P26 2.481 2.647 2.748 + P27 2.24 2.556 2.402 + P28 2.085 2.463 2.166 + Q02 1.092 0.522 0.456 + Q03 2.16 1.621 0.814 + Q04 4.314 4.723 1.353 + Q05 8.882 12.573 2.169 + Q06 15.507 24.675 3.276 + Q07 19.737 32.052 4.983 + Q08 18.787 28.048 1.414 + Q09 15.056 21.662 0.911 + Q10 8.8 11.263 0.541 + Q11 4.288 4.253 0.241 + Q12 2.144 1.488 0.093 + Q13 1.037 0.489 0.025 + Q14 9.661 6.986 11.373 + Q15 7.814 6.216 12.03 + Q16 5.87 5.682 14.411 + Q17 9.735 12.66 18.551 + Q18 12.576 18.175 20.725 + Q19 11.486 17.281 14.793 + Q20 9.913 15.513 6.281 + Q21 13.03 15.869 5.096 + Q22 15.405 16.598 4.712 + Q23 12.441 11.949 4.157 + Q24 8.247 6.088 3.129 + Q25 9.056 6.64 7.831 + Q26 1.635 1.969 1.965 + Q27 1.464 1.693 1.616 + Q28 1.358 1.499 1.326 + R02 0.299 0.171 0.464 + R03 0.8 0.952 0.9 + R04 2.08 3.512 1.535 + R05 5.297 10.401 2.45 + R06 9.536 19.375 3.545 + R07 12.138 24.003 5.201 + R08 11.159 20.153 1.28 + R09 9.046 16.391 0.89 + R10 5.192 9.04 0.572 + R11 2.019 3.032 0.264 + R12 0.731 0.781 0.098 + R13 0.242 0.135 0.024 + R14 9.08 8.401 9.714 + R15 8.492 8.242 10.094 + R16 7.625 8.08 10.952 + R17 9.408 11.104 12.207 + R18 10.351 12.767 12.774 + R19 9.979 12.455 10.779 + R20 9.358 11.859 7.552 + R21 10.401 11.969 6.926 + R22 11.128 12.163 6.697 + R23 10.211 10.67 6.45 + R24 8.438 7.916 5.779 + R25 8.908 8.293 8.294 + R26 0.824 0.967 1.118 + R27 0.892 1.044 0.995 + R28 0.898 1.066 0.866 + S02 0.108 0.076 0.463 + S03 0.314 0.595 0.923 + S04 0.895 2.271 1.497 + S05 2.381 6.453 2.317 + S06 4.54 12.112 3.23 + S07 6 15.207 4.627 + S08 5.164 12.038 1.021 + S09 3.972 9.549 0.735 + S10 2.102 5.137 0.479 + S11 0.748 1.782 0.243 + S12 0.201 0.412 0.099 + S13 0.034 0.033 0.023 + S14 1.725 1.253 2.271 + S15 1.29 1.041 2.329 + S16 0.733 0.725 2.351 + S17 1.231 1.755 3.158 + S18 1.614 2.609 3.588 + S19 1.41 2.414 2.387 + S20 1.173 2.065 0.872 + S21 2.237 2.832 0.862 + S22 2.94 3.185 0.824 + S23 2.319 2.239 0.688 + S24 1.415 1.023 0.463 + S25 1.59 1.165 1.443 + S26 0.517 0.577 0.634 + S27 0.418 0.508 0.509 + S28 0.389 0.49 0.474 + T01 20.906 22.173 18.934 + T14 1.673 1.457 2.146 + T15 1.39 1.301 2.148 + T16 0.95 1.044 2.135 + T17 1.331 1.79 2.561 + T18 1.571 2.278 2.786 + T19 1.464 2.181 2.147 + T20 1.302 1.983 1.137 + T21 1.948 2.412 1.151 + T22 2.312 2.604 1.125 + T23 1.997 2.087 1.027 + T24 1.446 1.262 0.839 + T25 1.578 1.38 1.593 + T26 0.226 0.308 0.356 + T27 0.189 0.243 0.247 + T28 0.177 0.205 0.205 + T29 76.694 79.235 62.936 + U01 0.04 0.037 0.026 + U14 1.521 1.579 1.795 + U15 1.449 1.541 1.83 + U16 1.215 1.388 1.789 + U17 1.372 1.691 1.882 + U18 1.47 1.863 1.965 + U19 1.436 1.833 1.767 + U20 1.377 1.769 1.375 + U21 1.604 1.908 1.358 + U22 1.702 1.968 1.36 + U23 1.61 1.806 1.34 + U24 1.417 1.476 1.246 + U25 1.493 1.552 1.626 + U26 0.045 0.043 0.088 + U27 0.044 0.048 0.036 + U28 0.059 0.074 0.038 + U29 0.042 0.039 0.029 + V01 76.341 78.885 62.676 + V14 21.197 22.447 19.277 + V15 76.612 79.131 62.823 + V26 0.039 0.036 0.025 + V27 0.04 0.037 0.026 + V28 0.039 0.037 0.026 + V29 0.038 0.035 0.027 + diff --git a/scanin/Jamfile b/scanin/Jamfile new file mode 100644 index 0000000..b6e58f1 --- /dev/null +++ b/scanin/Jamfile @@ -0,0 +1,33 @@ + + +#PREF_CCFLAGS += $(CCOPTFLAG) ; # Turn optimisation on +PREF_CCFLAGS += $(CCDEBUGFLAG) ; # Debugging flags +PREF_LINKFLAGS += $(LINKDEBUGFLAG) ; + +#Products +Libraries = libscanrd ; +Executables = scanin ; +Headers = scanrd.h ; +Samples = it8.cht ColorChecker.cht ColorChecker.cie ColorCheckerDC.cht + ColorCheckerSG.cht Hutchcolor.cht i1_RGB_Scan_1.4.cht + ColorCheckerPassport.cht ColorCheckerPassport.cie + QPcard_201.cht QPcard_201.cie QPcard_202.cht QPcard_202.cie CMP_DT_003.cht + CMP_Digital_Target-3.cht CMP_Digital_Target-3.ti2 CMP_Digital_Target-3.cie + LaserSoftDCPro.cht SpyderChecker.cht SpyderChecker.cie ; + +#Install +InstallBin $(DESTDIR)$(PREFIX)/bin : $(Executables) ; +InstallFile $(DESTDIR)$(PREFIX)/$(REFSUBDIR) : $(Samples) ; +#InstallFile $(DESTDIR)$(PREFIX)/h : $(Headers) ; +#InstallLib $(DESTDIR)$(PREFIX)/lib : $(Libraries) ; + +# Chart recognition library +Library libscanrd : scanrd.c : : : ../numlib ; + +# IT8 chart reader - sucks in tiff file and spits out cgats file +Main scanin : scanin.c ; +# ObjectHdrs scanin : ../h ../cgats ../numlib ../icc ../rspl ../gamut ../xicc $(TIFFINC) ; +ObjectHdrs scanin : ../h ../numlib ../icc ../cgats ../rspl ../xicc ../gamut ../spectro $(TIFFINC) ; +LinkLibraries scanin : libscanrd ../xicc/libxicc ../spectro/libinsttypes + ../gamut/libgamut ../rspl/librspl ../cgats/libcgats + ../icc/libicc ../numlib/libnum ../plot/libplot ../plot/libvrml $(TIFFLIB) $(JPEGLIB) ; diff --git a/scanin/LaserSoftDCPro.cht b/scanin/LaserSoftDCPro.cht new file mode 100644 index 0000000..e5df741 --- /dev/null +++ b/scanin/LaserSoftDCPro.cht @@ -0,0 +1,202 @@ + +BOXES 141 + F _ _ 26.09 18.7 239.15 18.7 239.15 171.9 26.09 171.9 + D ALL ALL _ _ 263.95 185.5 0 0 0 0 + Y 1 14 A J 12.675 12.75 27.5 20.0 15.175 15.25 + +BOX_SHRINK 1.6 + +XLIST 28 + 27.5 1.0 1.0 + 40.175 1.0 1.0 + 42.675 1.0 1.0 + 55.35 1.0 1.0 + 57.85 1.0 1.0 + 70.525 1.0 1.0 + 73.025 1.0 1.0 + 85.7 1.0 1.0 + 88.2 1.0 1.0 + 100.875 1.0 1.0 + 103.375 1.0 1.0 + 116.05 1.0 1.0 + 118.55 1.0 1.0 + 131.225 1.0 1.0 + 133.725 1.0 1.0 + 146.4 1.0 1.0 + 148.9 1.0 1.0 + 161.575 1.0 1.0 + 164.075 1.0 1.0 + 176.75 1.0 1.0 + 179.25 1.0 1.0 + 191.925 1.0 1.0 + 194.425 1.0 1.0 + 207.1 1.0 1.0 + 209.6 1.0 1.0 + 222.275 1.0 1.0 + 224.775 1.0 1.0 + 237.45 1.0 1.0 + +YLIST 20 + 20.0 1.0 1.0 + 32.75 1.0 1.0 + 35.25 1.0 1.0 + 48.0 1.0 1.0 + 50.5 1.0 1.0 + 63.25 1.0 1.0 + 65.75 1.0 1.0 + 78.5 1.0 1.0 + 81.0 1.0 1.0 + 93.75 1.0 1.0 + 96.25 1.0 1.0 + 109.0 1.0 1.0 + 111.5 1.0 1.0 + 124.25 1.0 1.0 + 126.75 1.0 1.0 + 139.5 1.0 1.0 + 142.0 1.0 1.0 + 154.75 1.0 1.0 + 157.25 1.0 1.0 + 170.0 1.0 1.0 + +EXPECTED XYZ 140 + A1 95.054 99.997 108.93 + A2 1.1997 1.1177 1.8435 + A3 6.7205 6.2574 11.555 + A4 95.054 99.997 108.93 + A5 95.054 99.997 108.93 + A6 95.054 99.997 108.93 + A7 0.49927 0.43693 0.87678 + A8 95.054 99.997 108.93 + A9 95.054 99.997 108.93 + A10 95.054 99.997 108.93 + A11 95.054 99.997 108.93 + A12 5.5560 5.1972 9.8224 + A13 1.0432 0.94378 1.8118 + A14 95.054 99.997 108.93 + B1 95.054 99.997 108.93 + B2 67.091 47.876 87.898 + B3 11.506 12.701 30.786 + B4 58.530 82.881 29.773 + B5 51.017 26.596 49.038 + B6 13.118 10.105 52.231 + B7 81.415 94.542 37.089 + B8 44.474 25.101 11.115 + B9 21.340 12.736 95.969 + B10 66.377 85.211 107.59 + B11 42.717 22.847 6.6395 + B12 95.054 99.997 108.93 + B13 78.392 91.406 108.15 + B14 95.054 99.997 108.93 + C1 0.91819 0.83268 1.3889 + C2 78.242 93.273 20.381 + C3 39.945 21.012 96.586 + C4 95.054 99.997 108.93 + C5 8.0062 6.3371 5.5237 + C6 95.054 99.997 108.93 + C7 95.054 99.997 108.93 + C8 95.054 99.997 108.93 + C9 95.054 99.997 108.93 + C10 26.464 19.481 13.094 + C11 55.073 48.678 101.13 + C12 77.003 92.778 13.853 + C13 43.434 22.924 11.065 + C14 0.78528 0.68981 1.5301 + D1 5.7964 5.4769 9.7970 + D2 72.996 88.624 107.90 + D3 86.456 96.558 63.644 + D4 62.452 84.629 42.335 + D5 92.459 98.959 95.262 + D6 35.935 71.602 11.974 + D7 60.015 81.931 107.29 + D8 59.633 29.164 97.123 + D9 20.716 10.192 95.511 + D10 95.054 99.997 108.93 + D11 77.045 92.795 14.074 + D12 43.764 31.444 13.884 + D13 95.054 99.997 108.93 + D14 5.4327 5.0906 9.4972 + E1 95.054 99.997 108.93 + E2 93.580 97.048 108.44 + E3 95.054 99.997 108.93 + E4 95.054 99.997 108.93 + E5 95.054 99.997 108.93 + E6 95.054 99.997 108.93 + E7 0.56064 0.49941 0.85338 + E8 95.054 99.997 108.93 + E9 55.394 48.320 10.491 + E10 95.054 99.997 108.93 + E11 18.067 9.9172 10.525 + E12 95.054 99.997 108.93 + E13 51.153 77.999 78.081 + E14 95.054 99.997 108.93 + F1 95.054 99.997 108.93 + F2 77.003 92.778 13.854 + F3 95.054 99.997 108.93 + F4 34.402 22.375 97.141 + F5 95.054 99.997 108.93 + F6 53.813 78.733 107.00 + F7 95.054 99.997 108.93 + F8 0.67207 0.58997 1.0828 + F9 60.272 30.442 97.336 + F10 52.097 40.728 12.472 + F11 77.003 92.778 13.853 + F12 95.054 99.997 108.93 + F13 10.781 6.4490 18.321 + F14 95.054 99.997 108.93 + G1 95.054 99.997 108.93 + G2 55.324 79.512 107.07 + G3 95.054 99.997 108.93 + G4 83.272 95.285 46.871 + G5 58.118 49.046 25.961 + G6 42.215 22.651 3.9825 + G7 35.762 71.514 11.921 + G8 19.846 9.7483 95.471 + G9 77.003 92.778 13.853 + G10 95.054 99.997 108.93 + G11 77.003 92.778 13.853 + G12 95.054 99.997 108.93 + G13 60.898 82.386 107.33 + G14 95.054 99.997 108.93 + H1 0.54264 0.48279 0.79835 + H2 89.532 88.954 107.09 + H3 77.759 93.080 17.834 + H4 42.861 43.829 100.84 + H5 36.752 71.940 15.774 + H6 95.054 99.997 108.93 + H7 95.054 99.997 108.93 + H8 95.054 99.997 108.93 + H9 95.054 99.997 108.93 + H10 53.813 78.733 107.00 + H11 15.498 10.161 46.468 + H12 54.711 27.778 69.401 + H13 46.548 76.933 18.826 + H14 0.62698 0.56386 0.99911 + I1 95.054 99.997 108.93 + I2 78.269 93.284 20.520 + I3 79.484 91.969 108.20 + I4 95.054 99.997 108.93 + I5 7.1761 7.4119 9.1084 + I6 68.605 86.360 107.69 + I7 49.882 38.374 5.3364 + I8 6.2853 7.7839 9.5291 + I9 95.054 99.997 108.93 + I10 71.643 79.666 19.448 + I11 61.032 72.662 49.370 + I12 54.931 79.309 107.05 + I13 79.147 93.635 25.144 + I14 95.054 99.997 108.93 + J1 95.054 99.997 108.93 + J2 0.42397 0.37158 0.62164 + J3 95.054 99.997 108.93 + J4 95.054 99.997 108.93 + J5 95.054 99.997 108.93 + J6 95.054 99.997 108.93 + J7 95.054 99.997 108.93 + J8 95.054 99.997 108.93 + J9 94.564 99.017 108.77 + J10 50.473 49.809 73.299 + J11 17.292 16.601 26.910 + J12 3.7657 3.5269 5.6717 + J13 0.50304 0.44681 0.73017 + J14 95.054 99.997 108.93 + diff --git a/scanin/License.txt b/scanin/License.txt new file mode 100644 index 0000000..a871fcf --- /dev/null +++ b/scanin/License.txt @@ -0,0 +1,662 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. + diff --git a/scanin/Makefile.am b/scanin/Makefile.am new file mode 100644 index 0000000..0e4f65a --- /dev/null +++ b/scanin/Makefile.am @@ -0,0 +1,19 @@ +include $(top_srcdir)/Makefile.shared + +privatelib_LTLIBRARIES = libscanrd.la +privatelibdir = $(pkglibdir) + +libscanrd_la_SOURCES = scanrd.h scanrd_.h scanrd.c +libscanrd_la_LIBADD = ../rspl/librspl.la ../numlib/libargyllnum.la + +LDADD = ./libscanrd.la ../numlib/libargyllnum.la $(ICC_LIBS) \ + ../cgats/libcgats.la ../xicc/libxicc.la $(TIFF_LIBS) \ + ../libargyll.la + +bin_PROGRAMS = scanin + +refdir = $(datadir)/color/argyll/ref + +ref_DATA = $(wildcard *.cht) $(wildcard *.cie) $(wildcard *.ti2) + +EXTRA_DIST = $(ref_DATA) License.txt Readme.txt diff --git a/scanin/QPcard_201.cht b/scanin/QPcard_201.cht new file mode 100644 index 0000000..a9d9542 --- /dev/null +++ b/scanin/QPcard_201.cht @@ -0,0 +1,76 @@ + +BOXES 31 + F _ _ 0.0 0.0 1654.0 0.0 1654.0 478.0 0.0 478.0 + D ALL ALL _ _ 1654.0 478.0 0.0 0.0 0 0 + Y 1 10 A C 118.0 119.0 239.0 66.0 141.5 142.0 + +BOX_SHRINK 15.0 + +REF_ROTATION 0.0 + +XLIST 22 + 150.618062 0.144363 0.166667 + 161.602137 0.245110 0.333333 + 238.956434 0.946427 1.000000 + 357.016882 0.855510 1.000000 + 379.969304 0.948635 1.000000 + 497.948383 0.927859 1.000000 + 521.902072 1.000000 1.000000 + 640.004059 0.922588 1.000000 + 662.964760 0.948369 1.000000 + 782.052769 0.951028 1.000000 + 804.971146 0.886492 1.000000 + 923.008950 0.922731 1.000000 + 946.989395 0.865832 1.000000 + 1066.007371 0.876333 1.000000 + 1088.986522 0.865792 1.000000 + 1208.017128 0.871015 1.000000 + 1229.826796 0.868345 1.000000 + 1349.181703 0.847707 1.000000 + 1372.210921 0.767835 1.000000 + 1490.553264 0.783286 1.000000 + 1513.822380 0.891664 1.000000 + 1633.171522 0.868381 1.000000 + +YLIST 8 + 65.941330 0.342831 1.000000 + 184.978043 0.345580 1.000000 + 207.991441 0.442638 1.000000 + 325.524788 1.000000 1.000000 + 348.940333 0.208095 1.000000 + 366.421405 0.090483 0.647059 + 378.396408 0.079155 0.617647 + 466.955243 0.226972 0.000000 + +EXPECTED XYZ 30 + A1 47.8 50.5 53.2 + A2 9.3 9.6 27.6 + A3 60.7 62.1 11.2 + A4 4.4 4.6 4.9 + A5 10.5 11.1 11.9 + A6 16.8 17.8 19.5 + A7 32.9 34.7 36.8 + A8 65.1 68.9 72.5 + A9 81.8 86.6 91.0 + A10 47.8 50.5 53.2 + B1 36.9 43.1 7.0 + B2 15.7 26.5 17.4 + B3 29.8 19.5 20.8 + B4 6.2 5.7 7.9 + B5 10.1 12.3 6.8 + B6 19.9 20.5 6.5 + B7 11.0 9.9 6.8 + B8 36.2 34.2 25.0 + B9 60.7 67.5 73.7 + B10 56.3 56.5 70.3 + C1 47.8 50.5 53.2 + C2 14.5 8.9 4.3 + C3 18.6 24.8 52.5 + C4 9.6 7.2 6.1 + C5 18.0 19.8 34.8 + C6 43.0 30.9 5.8 + C7 57.0 49.6 6.6 + C8 69.3 68.9 47.9 + C9 64.5 69.9 59.9 + C10 47.8 50.5 53.2 + diff --git a/scanin/QPcard_201.cie b/scanin/QPcard_201.cie new file mode 100644 index 0000000..ecd1a3a --- /dev/null +++ b/scanin/QPcard_201.cie @@ -0,0 +1,42 @@ +IT8.7/2 +ORIGINATOR "Graeme Gill, ArgyllCMS" +DESCRIPTOR "QPCard 201" +CREATED "Nov 29, 2007" +MANUFACTURER "QPcard AB" +NUMBER_OF_FIELDS 4 +BEGIN_DATA_FORMAT +SAMPLE_ID XYZ_X XYZ_Y XYZ_Z +END_DATA_FORMAT +NUMBER_OF_SETS 30 +BEGIN_DATA +A1 47.8 50.5 53.2 +A2 9.3 9.6 27.6 +A3 60.7 62.1 11.2 +A4 4.4 4.6 4.9 +A5 10.5 11.1 11.9 +A6 16.8 17.8 19.5 +A7 32.9 34.7 36.8 +A8 65.1 68.9 72.5 +A9 81.8 86.6 91.0 +A10 47.8 50.5 53.2 +B1 36.9 43.1 7.0 +B2 15.7 26.5 17.4 +B3 29.8 19.5 20.8 +B4 6.2 5.7 7.9 +B5 10.1 12.3 6.8 +B6 19.9 20.5 6.5 +B7 11.0 9.9 6.8 +B8 36.2 34.2 25.0 +B9 60.7 67.5 73.7 +B10 56.3 56.5 70.3 +C1 47.8 50.5 53.2 +C2 14.5 8.9 4.3 +C3 18.6 24.8 52.5 +C4 9.6 7.2 6.1 +C5 18.0 19.8 34.8 +C6 43.0 30.9 5.8 +C7 57.0 49.6 6.6 +C8 69.3 68.9 47.9 +C9 64.5 69.9 59.9 +C10 47.8 50.5 53.2 +END_DATA diff --git a/scanin/QPcard_202.cht b/scanin/QPcard_202.cht new file mode 100644 index 0000000..4d10406 --- /dev/null +++ b/scanin/QPcard_202.cht @@ -0,0 +1,80 @@ +BOXES 36 + F _ _ 22 20 638 22 638 440 20 440 + D ALL ALL _ _ 655 455 0 0 0 0 + Y 1 7 A E 68 68 45 30 83 83 + +BOX_SHRINK 4.0 + +REF_ROTATION 0.0 + +XLIST 19 + 43.608721 0.740781 0.800000 + 114.976109 0.783190 0.800000 + 126.951628 0.918228 0.900000 + 198.016123 0.974824 0.900000 + 210.073338 0.901194 1.000000 + 281.139260 0.985920 1.000000 + 294.215088 0.898482 1.000000 + 364.783383 0.991485 1.000000 + 377.849374 0.904129 1.000000 + 448.984652 1.000000 1.000000 + 460.979320 0.954860 1.000000 + 532.024333 0.997190 1.000000 + 544.239647 0.898460 1.000000 + 615.407960 0.946305 1.000000 + 631.910471 0.186078 0.000000 + 636.058422 0.233922 0.000000 + 642.588462 0.132382 0.000000 + 643.533506 0.270593 0.000000 + 644.296155 0.191706 0.000000 + +YLIST 12 + 26.695891 1.000000 0.875000 + 98.238688 0.936512 1.000000 + 110.194036 0.994019 1.000000 + 181.442800 0.892945 1.000000 + 194.417673 0.992089 0.937500 + 264.518175 0.877113 0.875000 + 277.701905 0.986234 1.000000 + 347.941384 0.877209 1.000000 + 360.406157 0.132648 0.312500 + 361.033254 0.706971 0.875000 + 431.983255 0.253427 0.750000 + 432.622344 0.399964 0.000000 + +EXPECTED XYZ 35 +A1 67.856459 69.512840 9.015609 +A2 67.076305 59.459332 7.827210 +A3 58.305183 45.461038 7.748888 +A4 52.785392 65.096997 59.594305 +A5 45.322673 55.739548 35.288307 +A6 58.323014 65.546227 28.470190 +A7 75.997301 76.369564 28.920869 +B1 27.185068 21.163573 31.661582 +B2 19.566090 10.470287 2.899649 +B3 7.735493 16.256731 8.259450 +B4 7.305847 10.044629 23.599855 +B5 38.157321 40.254508 6.905462 +B6 12.286120 18.850102 28.606420 +B7 70.618705 63.122300 27.332985 +C1 27.875888 20.161730 25.953035 +C2 21.562223 11.180011 4.672983 +C3 9.915698 19.077936 6.906382 +C4 9.400751 9.282240 29.346924 +C5 33.030305 38.085875 6.761389 +C6 12.379400 21.440342 24.610384 +C7 68.775747 59.666057 36.778798 +D1 30.312295 21.545103 20.899732 +D2 19.513673 10.562642 7.925905 +D3 9.957248 17.257178 4.623671 +D4 9.916827 8.308213 24.940996 +D5 24.060360 31.480055 7.467898 +D6 11.633929 19.652104 17.324887 +D7 64.052575 58.473280 56.362590 +E1 81.660435 84.707213 65.484182 +E2 61.845146 64.255877 51.551387 +E3 35.051455 36.358983 29.400605 +E4 22.483519 23.314508 19.344460 +E5 10.265340 10.652815 8.624928 +E6 5.291836 5.472343 4.344900 +E7 3.074245 3.153171 2.547055 diff --git a/scanin/QPcard_202.cie b/scanin/QPcard_202.cie new file mode 100644 index 0000000..683b6c0 --- /dev/null +++ b/scanin/QPcard_202.cie @@ -0,0 +1,48 @@ +IT8.7/2 +ORIGINATOR "jose pereira jpereira.net" +DESCRIPTOR "QPCARD 202" +CREATED "may 2012" +MANUFACTURER "QPcard" +NUMBER_OF_FIELDS 7 +BEGIN_DATA_FORMAT +SAMPLE_ID XYZ_X XYZ_Y XYZ_Z LAB_L LAB_A LAB_B +END_DATA_FORMAT +NUMBER_OF_SETS 35 +BEGIN_DATA +A01 67.856459 69.512840 9.015609 86.757375 1.825575 81.545134 +A02 67.076305 59.459332 7.827210 81.543425 22.588491 76.956535 +A03 58.305183 45.461038 7.748888 73.194438 38.355857 62.867015 +A04 52.785392 65.096997 59.594305 84.533694 -24.307666 -6.124730 +A05 45.322673 55.739548 35.288307 79.465357 -22.724528 13.897787 +A06 58.323014 65.546227 28.470190 84.764423 -11.471673 33.441882 +A07 75.997301 76.369564 28.920869 90.030651 4.834878 41.785201 +B01 27.185068 21.163573 31.661582 53.128052 29.896273 -26.161046 +B02 19.566090 10.470287 2.899649 38.673581 58.158660 28.749194 +B03 7.735493 16.256731 8.259450 47.309526 -57.238786 16.283396 +B04 7.305847 10.044629 23.599855 37.922410 -20.845869 -38.815336 +B05 38.157321 40.254508 6.905462 69.650420 -2.091972 60.182723 +B06 12.286120 18.850102 28.606420 50.511369 -35.081968 -25.838514 +B07 70.618705 63.122300 27.332985 83.506686 21.791859 33.166706 +C01 27.875888 20.161730 25.953035 52.019576 37.428172 -18.752022 +C02 21.562223 11.180011 4.672983 39.882016 62.620005 19.536557 +C03 9.915698 19.077936 6.906382 50.778263 -53.582415 27.640637 +C04 9.400751 9.282240 29.346924 36.522120 3.739027 -51.160034 +C05 33.030305 38.085875 6.761389 68.083859 -12.577785 58.094494 +C06 12.379400 21.440342 24.610384 53.428091 -47.018893 -13.936155 +C07 68.775747 59.666057 36.778798 81.656338 25.812200 15.582830 +D01 30.312295 21.545103 20.899732 53.540986 40.234784 -6.655919 +D02 19.513673 10.562642 7.925905 38.833864 57.205173 2.937550 +D03 9.957248 17.257178 4.623671 48.582459 -43.791000 34.808467 +D04 9.916827 8.308213 24.940996 34.616704 16.088365 -46.965354 +D05 24.060360 31.480055 7.467898 62.910807 -25.347082 46.249115 +D06 11.633929 19.652104 17.324887 51.441570 -43.624665 -2.604415 +D07 64.052575 58.473280 56.362590 81.001208 18.165842 -8.910822 +E01 81.660435 84.707213 65.484182 93.756804 -0.027533 4.049779 +E02 61.845146 64.255877 51.551387 84.098816 -0.256360 1.591948 +E03 35.051455 36.358983 29.400605 66.793307 -0.019940 0.945311 +E04 22.483519 23.314508 19.344460 55.394826 0.016750 -0.239174 +E05 10.265340 10.652815 8.624928 38.989459 -0.046959 0.588338 +E06 5.291836 5.472343 4.344900 28.040182 0.184525 0.961005 +E07 3.074245 3.153171 2.547055 20.647174 0.585930 0.440283 + +END_DATA diff --git a/scanin/Readme.txt b/scanin/Readme.txt new file mode 100644 index 0000000..2976595 --- /dev/null +++ b/scanin/Readme.txt @@ -0,0 +1,8 @@ + +This directory contains the code to extract charts from +TIFF scan files, and output the patch values using the +CGATS file format. Typically this is used to get the +patch information from a scan of an IT8 calibration +chart. + +scanin.exe processes a TIFF file into a CGATS file. diff --git a/scanin/SpyderChecker.cht b/scanin/SpyderChecker.cht new file mode 100644 index 0000000..1c0ef3a --- /dev/null +++ b/scanin/SpyderChecker.cht @@ -0,0 +1,115 @@ +BOXES 49 + F _ _ 5 4 470 5 470 307 5 307 + + D ALL ALL _ _ 475 315 0 0 0 0 + + X A D 1 6 42 42 11 10 49 50 + X E H 1 6 42 42 274 10 49 50 + + +BOX_SHRINK 3.0 + +REF_ROTATION 0.0 + +XLIST 27 + 4.984973 0.109746 0.076923 + 9.286927 0.952526 1.000000 + 52.887948 0.925344 1.000000 + 59.167435 1.000000 0.923077 + 102.212773 0.458586 0.923077 + 102.919173 0.494117 0.384615 + 108.965439 0.995672 1.000000 + 152.335524 0.929079 1.000000 + 158.540776 0.956677 1.000000 + 202.023990 0.948802 1.000000 + 207.819679 0.348860 0.076923 + 213.309915 0.948588 0.000000 + 230.603930 0.364584 0.000000 + 234.074857 0.305779 0.000000 + 240.406366 0.419481 0.000000 + 243.970119 0.780089 0.000000 + 260.767091 0.913272 0.000000 + 266.441147 0.117583 0.076923 + 271.869223 0.913611 1.000000 + 315.052562 0.921224 1.000000 + 321.439873 0.976014 1.000000 + 364.747788 0.940719 1.000000 + 371.336194 0.968158 1.000000 + 414.647393 0.874415 1.000000 + 420.992026 0.882322 1.000000 + 464.404335 0.944708 1.000000 + 469.433263 0.121537 0.076923 + +YLIST 22 + 4.526138 1.000000 0.000000 + 9.908960 0.796520 0.730769 + 53.044496 0.103192 0.730769 + 53.524920 0.636430 0.576923 + 60.203792 0.830553 0.730769 + 103.048172 0.307118 0.730769 + 103.492169 0.530702 0.615385 + 109.526018 0.312034 0.153846 + 109.974584 0.523340 0.730769 + 153.023131 0.597133 0.730769 + 153.456869 0.213758 0.461538 + 159.493872 0.317053 0.115385 + 159.963940 0.430105 0.884615 + 202.530321 0.801088 0.884615 + 209.038198 0.511082 0.115385 + 209.470794 0.321862 0.846154 + 252.013363 0.513537 0.884615 + 252.528335 0.297345 0.538462 + 258.522376 0.203926 0.076923 + 258.989151 0.557818 1.000000 + 301.519003 0.098341 1.000000 + 302.011325 0.695429 0.000000 + +EXPECTED XYZ 48 + A1 35.76 28.63 20.95 + A2 45.15 47.41 16.97 + A3 26.68 36.02 22.61 + A4 24.43 30.51 49.72 + A5 27.36 28.54 55.85 + A6 33.51 26.53 34.35 + B1 58.65 60.38 64.15 + B2 55.22 59.80 62.04 + B3 57.62 60.06 69.00 + B4 5.28 5.14 5.28 + B5 4.44 5.04 5.06 + B6 5.12 5.19 6.86 + C1 64.60 65.02 55.99 + C2 45.46 45.77 29.03 + C3 33.13 32.26 14.73 + C4 15.61 13.92 7.09 + C5 5.16 5.03 3.92 + C6 4.01 4.17 4.76 + D1 77.89 81.93 87.49 + D2 70.10 73.80 78.79 + D3 43.43 45.76 48.92 + D4 24.24 25.51 27.51 + D5 12.32 12.98 13.91 + D6 5.22 5.50 6.02 + E1 85.00 89.31 96.33 + E2 54.09 56.94 61.35 + E3 32.55 34.33 36.79 + E4 17.72 18.68 20.09 + E5 7.89 8.30 8.87 + E6 2.65 2.78 3.12 + F1 12.84 18.14 36.39 + F2 28.20 18.34 29.84 + F3 57.08 61.01 8.56 + F4 19.63 11.29 4.87 + F5 13.70 22.39 9.24 + F6 7.32 5.35 26.41 + G1 35.76 28.16 5.45 + G2 12.71 11.07 36.60 + G3 27.74 18.51 13.48 + G4 9.34 6.93 16.38 + G5 33.22 43.77 10.98 + G6 46.49 42.42 7.53 + H1 30.35 42.13 42.95 + H2 24.45 23.05 44.34 + H3 9.73 12.51 6.59 + H4 17.28 18.47 34.69 + H5 36.71 34.18 24.66 + H6 10.43 9.32 6.27 diff --git a/scanin/SpyderChecker.cie b/scanin/SpyderChecker.cie new file mode 100644 index 0000000..302e416 --- /dev/null +++ b/scanin/SpyderChecker.cie @@ -0,0 +1,62 @@ +IT8.7/2 +ORIGINATOR "Jose Pereira" +DESCRIPTOR "Datacolor SpyderCheckr (D65)" +CREATED "dec, 19. 2011" +MANUFACTURER "DataColor" + +NUMBER_OF_FIELDS 7 +BEGIN_DATA_FORMAT +SAMPLE_ID XYZ_X XYZ_Y XYZ_Z +END_DATA_FORMAT + +NUMBER_OF_SETS 48 +BEGIN_DATA +A1 35.76 28.63 20.95 +A2 45.15 47.41 16.97 +A3 26.68 36.02 22.61 +A4 24.43 30.51 49.72 +A5 27.36 28.54 55.85 +A6 33.51 26.53 34.35 +B1 58.65 60.38 64.15 +B2 55.22 59.80 62.04 +B3 57.62 60.06 69.00 +B4 5.28 5.14 5.28 +B5 4.44 5.04 5.06 +B6 5.12 5.19 6.86 +C1 64.60 65.02 55.99 +C2 45.46 45.77 29.03 +C3 33.13 32.26 14.73 +C4 15.61 13.92 7.09 +C5 5.16 5.03 3.92 +C6 4.01 4.17 4.76 +D1 77.89 81.93 87.49 +D2 70.10 73.80 78.79 +D3 43.43 45.76 48.92 +D4 24.24 25.51 27.51 +D5 12.32 12.98 13.91 +D6 5.22 5.50 6.02 +E1 85.00 89.31 96.33 +E2 54.09 56.94 61.35 +E3 32.55 34.33 36.79 +E4 17.72 18.68 20.09 +E5 7.89 8.30 8.87 +E6 2.65 2.78 3.12 +F1 12.84 18.14 36.39 +F2 28.20 18.34 29.84 +F3 57.08 61.01 8.56 +F4 19.63 11.29 4.87 +F5 13.70 22.39 9.24 +F6 7.32 5.35 26.41 +G1 35.76 28.16 5.45 +G2 12.71 11.07 36.60 +G3 27.74 18.51 13.48 +G4 9.34 6.93 16.38 +G5 33.22 43.77 10.98 +G6 46.49 42.42 7.53 +H1 30.35 42.13 42.95 +H2 24.45 23.05 44.34 +H3 9.73 12.51 6.59 +H4 17.28 18.47 34.69 +H5 36.71 34.18 24.66 +H6 10.43 9.32 6.27 +END_DATA diff --git a/scanin/afiles b/scanin/afiles new file mode 100644 index 0000000..bc4d9c7 --- /dev/null +++ b/scanin/afiles @@ -0,0 +1,28 @@ +Readme.txt +License.txt +afiles +Jamfile +scanin.c +scanrd.c +scanrd.h +scanrd_.h +it8.cht +ColorChecker.cht +ColorChecker.cie +ColorCheckerDC.cht +ColorCheckerSG.cht +Hutchcolor.cht +i1_RGB_Scan_1.4.cht +ColorCheckerPassport.cht +ColorCheckerPassport.cie +QPcard_201.cht +QPcard_201.cie +QPcard_202.cht +QPcard_202.cie +CMP_DT_003.cht +CMP_Digital_Target-3.cht +CMP_Digital_Target-3.ti2 +CMP_Digital_Target-3.cie +LaserSoftDCPro.cht +SpyderChecker.cht +SpyderChecker.cie diff --git a/scanin/i1_RGB_Scan_1.4.cht b/scanin/i1_RGB_Scan_1.4.cht new file mode 100644 index 0000000..3a3d7c9 --- /dev/null +++ b/scanin/i1_RGB_Scan_1.4.cht @@ -0,0 +1,341 @@ + +BOXES 289 + F _ _ 49 33 662 33 662 466 49 466 + D ALL ALL _ _ 613 433 49.0 33.0 0 0 + X A R 1 16 34.0 27.0 49.0 33.0 34.0 27.0 + +BOX_SHRINK 3.3 + +REF_ROTATION 0.0 + +XLIST 19 + 49.0 1.0 1.0 + 83.0 1.0 1.0 + 117.0 1.0 1.0 + 151.0 1.0 1.0 + 185.0 1.0 1.0 + 219.0 1.0 1.0 + 253.0 1.0 1.0 + 287.0 1.0 1.0 + 321.0 1.0 1.0 + 355.0 1.0 1.0 + 389.0 1.0 1.0 + 423.0 1.0 1.0 + 457.0 1.0 1.0 + 491.0 1.0 1.0 + 525.0 1.0 1.0 + 559.0 1.0 1.0 + 593.0 1.0 1.0 + 627.0 1.0 1.0 + 662.0 1.0 1.0 + +YLIST 17 + 33.0 1.0 1.0 + 60.0 1.0 1.0 + 87.0 1.0 1.0 + 114.0 1.0 1.0 + 141.0 1.0 1.0 + 168.0 1.0 1.0 + 195.0 1.0 1.0 + 222.0 1.0 1.0 + 249.0 1.0 1.0 + 276.0 1.0 1.0 + 303.0 1.0 1.0 + 330.0 1.0 1.0 + 357.0 1.0 1.0 + 384.0 1.0 1.0 + 411.0 1.0 1.0 + 439.0 1.0 1.0 + 466.0 1.0 1.0 + +EXPECTED XYZ 288 + A1 0.52 0.59 0.56 + A2 10.27 10 32.62 + A3 13.89 7.3 2.84 + A4 33.34 23.69 4.75 + A5 31.79 33.22 28.61 + A6 13.85 14.51 12.72 + A7 35.52 25.53 10.91 + A8 27.16 27.04 25.26 + A9 6.12 6.42 5.76 + A10 6.04 6.8 6.75 + A11 4.4 3.47 20.55 + A12 6.34 3.41 11.34 + A13 9.03 7.05 14.88 + A14 7.91 6.52 8.41 + A15 16.18 10.77 24.37 + A16 1.97 1.1 8.66 + B1 27.55 34.83 6.23 + B2 17.94 11.4 1.02 + B3 34.87 35.19 5.79 + B4 13.05 19.54 29.87 + B5 6.88 9.15 27.74 + B6 70.59 73.69 44.02 + B7 2.04 2.19 1.41 + B8 1.35 2.84 0.94 + B9 49.51 40.62 36.32 + B10 43.26 35.61 12.01 + B11 2.65 3.13 3.25 + B12 17.77 24.45 21.08 + B13 8.51 14.13 31.85 + B14 7.84 11.93 30.12 + B15 5.81 12.04 16.38 + B16 11.49 8.06 0.99 + C1 34.5 19.81 37.1 + C2 42.27 43.99 33.47 + C3 4.36 7.54 14.12 + C4 58.73 57.76 6.5 + C5 11.22 5.5 17.82 + C6 1.55 1.89 2.09 + C7 37.5 39.03 33.61 + C8 23.67 18.54 4.44 + C9 8.12 14.07 4.81 + C10 2.9 7.38 1.41 + C11 34.09 35.82 26.91 + C12 9.45 9.34 9.05 + C13 41.11 33.34 5.29 + C14 27.38 21.65 19.2 + C15 27.38 28.66 24.61 + C16 48.58 49.16 58.53 + D1 7.47 12.02 1.86 + D2 17.27 8.47 18.91 + D3 24.86 14.78 0.99 + D4 8.61 4.81 2.74 + D5 28.85 26.03 5.07 + D6 20.34 26.75 33.64 + D7 5.39 3.09 6.34 + D8 7.42 3.7 17.12 + D9 60.57 66.88 64.61 + D10 4.42 4.33 4.38 + D11 2.63 2.73 10.91 + D12 46.48 54.19 25.5 + D13 1.24 2.02 2.92 + D14 2.43 5.58 3.81 + D15 4.46 2.69 0.72 + D16 23.58 11.3 19.67 + E1 18.33 16.26 18.07 + E2 13.25 17.2 1.73 + E3 16.1 22.52 11.75 + E4 50.7 52.96 40.49 + E5 0.93 1.03 0.98 + E6 2.58 1.28 12.24 + E7 61.11 63.67 49.46 + E8 9.69 16.36 11.19 + E9 19.64 20.4 5.14 + E10 68.63 71.55 34.47 + E11 33.86 33.75 30.83 + E12 18.65 9.44 0.83 + E13 12.88 22.5 20.49 + E14 40.57 35.97 51.8 + E15 25.89 26.22 33.39 + E16 30.29 39.21 13.78 + F1 3.2 7.65 4.38 + F2 3.71 3.35 16.24 + F3 23.31 14.61 25.55 + F4 20.14 13.3 9.05 + F5 19.65 21.55 20.22 + F6 1.21 1.33 0.75 + F7 5.8 8.65 21.51 + F8 20.82 10.37 7.25 + F9 12.98 6.05 24.77 + F10 15.96 14.23 4.62 + F11 54.03 50.45 2.31 + F12 23.38 24.4 20.86 + F13 4.42 5.8 1.14 + F14 17.42 25.87 5.81 + F15 1.8 3.63 3.4 + F16 12.33 9.08 3.65 + G1 41.01 28.98 32.18 + G2 14.7 24.18 31.92 + G3 4.63 5.68 19.04 + G4 73.8 76.63 58.3 + G5 25.16 11.63 27.13 + G6 23.64 27.52 5.74 + G7 40.74 42.65 24.74 + G8 5.04 6.8 4 + G9 15.6 21.51 42.53 + G10 47.5 50.89 46.6 + G11 11.95 13.23 12.63 + G12 0.74 0.68 2.21 + G13 20.56 17.42 28.91 + G14 3.34 3.61 2.24 + G15 15.88 7.93 12.58 + G16 32.76 42.79 24.95 + H1 1.99 1.85 1.96 + H2 5.23 4.73 13.17 + H3 35.1 45.5 39.54 + H4 15.44 16.22 14.02 + H5 18.85 19.72 16.96 + H6 19.88 10.01 3.06 + H7 12.31 8.36 31.05 + H8 37.11 33.66 35.77 + H9 31.4 29.01 12.25 + H10 5.92 7.65 8.81 + H11 65.82 68.12 58.73 + H12 15.16 18.34 19.38 + H13 14.99 12.73 1.65 + H14 56.71 60.58 54.75 + H15 9.34 13.22 17.86 + H16 14.91 7.72 6.98 + I1 25.37 20.12 10.52 + I2 49.34 51.3 44.11 + I3 6.63 6.47 6.58 + I4 1.07 0.94 1.24 + I5 8.34 4.69 0.92 + I6 23.16 18.65 41.02 + I7 6.72 10.56 4.53 + I8 27.97 23.98 1.71 + I9 3.27 1.46 15.75 + I10 55.74 51.88 24.53 + I11 7.7 11.77 9.88 + I12 1.57 1.7 1.49 + I13 28.92 28.09 47.66 + I14 28.27 17.22 9.16 + I15 72.13 75.17 50.99 + I16 3.58 5.09 12.93 + J1 13.14 15.8 38.03 + J2 9.81 17.93 5.25 + J3 68.6 65.82 63.75 + J4 43.83 30.19 45.87 + J5 18.39 8.6 26.07 + J6 5.36 10.17 15.84 + J7 55.67 57.15 61.71 + J8 17.35 19.86 30.55 + J9 9.34 5.12 6.56 + J10 4.06 4.65 4.46 + J11 59.67 55.56 40.66 + J12 49.63 49.42 45.4 + J13 41.62 45.81 6.35 + J14 4.44 4.57 7.21 + J15 12.73 12.57 11.83 + J16 33.9 31.33 21.78 + K1 39.02 40.41 2.14 + K2 6.59 5.47 20 + K3 11 14.42 27.43 + K4 1.86 2.4 6.45 + K5 18.68 28.5 12.59 + K6 75.76 78.23 67.4 + K7 7.32 7.87 5.36 + K8 18.49 18.14 1.64 + K9 37.54 38.95 13.07 + K10 55.35 62.8 63.8 + K11 8.76 9.83 9.34 + K12 8.38 8.86 7.56 + K13 21.69 14.04 16.27 + K14 16.19 22.43 2.19 + K15 62.66 63.7 14.84 + K16 7.22 13.33 24.18 + L1 4.75 2.89 2.62 + L2 38.93 48.68 58.9 + L3 65.92 71 57.4 + L4 66.52 69 26.91 + L5 15.55 13.99 36.92 + L6 17.18 15.48 10.42 + L7 51.65 59.75 43.16 + L8 18.25 11.8 33.47 + L9 3.47 3.71 3.23 + L10 12.9 9.35 8.48 + L11 64.65 59.55 61.46 + L12 45.13 38.69 1.96 + L13 6.43 10.92 22.75 + L14 21.35 21.35 19.83 + L15 33.05 24.65 43.94 + L16 22.66 23.84 17.58 + M1 65.11 63.01 48.58 + M2 1.94 1.46 0.65 + M3 22.58 16.86 1.28 + M4 10.28 5.41 11.55 + M5 11.02 20.07 11.6 + M6 59.78 59.84 54.76 + M7 2.71 4.6 7.83 + M8 23.91 34.53 36.93 + M9 30.27 18.26 16.91 + M10 26.5 36.45 52.65 + M11 13.33 16.63 10.94 + M12 4.04 8.83 9.08 + M13 5.17 5.59 5.05 + M14 3.61 9.2 4.51 + M15 10.14 10.8 7.78 + M16 3.13 3.26 0.84 + N1 3.29 6.6 8.25 + N2 4.65 10.78 9.31 + N3 30.72 33.49 30.48 + N4 10.72 12.58 1.45 + N5 10.17 7.54 21.82 + N6 11.18 18 19.3 + N7 53.3 49.34 13.79 + N8 7.14 6.18 3.7 + N9 7.18 8.54 15.43 + N10 10.26 10.86 9.44 + N11 64.17 66.15 63.94 + N12 29.82 22.94 30.75 + N13 41.27 41.14 38.01 + N14 13.72 13.09 26.73 + N15 67.54 72.16 65.85 + N16 59.57 51.66 57.98 + O1 13.5 7.07 0.76 + O2 49.21 44.05 5.87 + O3 18.71 12.3 3.74 + O4 38.42 41.38 37.84 + O5 14.29 19.83 5.34 + O6 38.12 27.36 19.84 + O7 0.82 1.5 0.8 + O8 58.19 65.09 49.46 + O9 22.03 24.06 1.89 + O10 54.38 44.04 54.64 + O11 17.33 18.31 13.39 + O12 3.07 2.92 2.94 + O13 8.57 8.65 1.33 + O14 2.04 4.54 1.45 + O15 5.58 2.53 20.51 + O16 9.55 10.01 4.38 + P1 27.28 32.46 22.7 + P2 1.26 0.88 4.93 + P3 33.17 37.11 53.34 + P4 8.31 3.84 22.57 + P5 0.65 0.9 1.06 + P6 3.58 1.97 10.4 + P7 17.53 26.57 45.79 + P8 38.54 30.11 1.74 + P9 70.01 70.01 56.41 + P10 45.98 54.96 61.34 + P11 5.76 6.4 24.4 + P12 27.4 28.95 21.64 + P13 8.91 9.56 24.29 + P14 14.32 10.16 15.55 + P15 44.13 50.38 14.14 + P16 25.91 15.77 35.63 + Q1 7.89 5.75 27.26 + Q2 19.45 21.15 43.11 + Q3 2.18 1.59 2.48 + Q4 2.47 2.57 2.36 + Q5 71.98 71.6 65.38 + Q6 25.4 27.72 25.57 + Q7 46.78 38.92 22.52 + Q8 30.85 35.91 37 + Q9 9.11 15.52 1.94 + Q10 11.65 11.86 16.65 + Q11 20.6 21.96 11.36 + Q12 2.49 6.09 1.38 + Q13 43.66 45.37 39.11 + Q14 56.73 58.92 50.71 + Q15 13.37 14.14 10.18 + Q16 25.67 30.42 12.63 + R1 11.96 14.98 5.06 + R2 25.55 30.36 2.16 + R3 20.96 31.53 22.46 + R4 26.63 16.16 3.75 + R5 15.45 17.15 15.99 + R6 2.87 1.83 5.87 + R7 5.94 8.9 1.32 + R8 22.2 10.8 12.85 + R9 32.45 19.2 26.87 + R10 31.17 21.44 1.48 + R11 4.71 2.36 15.65 + R12 16.81 16.68 15.67 + R13 33.39 31.69 1.87 + R14 6.67 5.46 0.93 + R15 23.87 29.65 49.1 + R16 5.1 5.43 3.45 + + diff --git a/scanin/it8.cht b/scanin/it8.cht new file mode 100644 index 0000000..f1e256d --- /dev/null +++ b/scanin/it8.cht @@ -0,0 +1,338 @@ + + +BOXES 290 + F _ _ 1 1 616.0 1.5 615.5 358 1 358.5 + D ALL ALL _ _ 615 409 1 1 0 0 + D MARK MARK _ _ 14 14 1 1 0 0 + Y 01 22 A L 25.625 25.625 26.625 26.625 25.625 25.625 + X GS00 GS23 _ _ 25.625 51.25 0.0 358.75 25.625 0.0 + +BOX_SHRINK 3.2 + +REF_ROTATION -0.002006 + +XLIST 32 + 1.799625 1.000000 0.312500 + 27.064987 0.874039 0.750000 + 52.592403 0.133439 0.687500 + 78.196610 0.264191 0.687500 + 104.117756 0.165427 0.937500 + 129.377994 0.844432 0.937500 + 155.144274 0.501218 0.875000 + 180.839181 0.491428 0.937500 + 206.359758 0.212384 0.937500 + 232.038808 0.851851 0.937500 + 257.854725 0.162956 0.625000 + 283.552463 0.101243 0.812500 + 300.534000 0.024750 0.812500 + 309.507688 0.093829 1.000000 + 334.711314 0.856821 1.000000 + 360.428194 0.787677 1.000000 + 385.849730 0.748130 0.937500 + 386.650071 0.039487 0.687500 + 394.630372 0.024725 0.687500 + 411.835654 0.802501 0.750000 + 414.017731 0.041974 0.937500 + 437.133504 0.674062 0.937500 + 437.975355 0.103714 1.000000 + 462.938460 0.671643 1.000000 + 463.880560 0.093836 0.937500 + 488.517995 0.679022 1.000000 + 514.338544 0.760511 1.000000 + 540.037492 0.111108 0.625000 + 565.856396 0.133330 0.562500 + 591.114717 0.565475 0.562500 + 603.447516 0.032097 0.312500 + 615.984915 0.829608 0.250000 + +YLIST 22 + 2.477956 0.993407 0.142857 + 12.988903 0.016393 0.190476 + 14.739109 0.036082 0.190476 + 26.746171 0.911487 0.428571 + 52.537114 0.303282 0.904762 + 78.060317 0.585303 0.857143 + 103.498271 0.606862 0.761905 + 128.994535 0.567266 0.761905 + 154.483041 0.550814 0.714286 + 179.935985 0.623055 0.666667 + 205.552940 0.350826 0.714286 + 212.051372 0.016393 0.714286 + 231.153547 0.824618 0.857143 + 256.697418 0.744268 0.952381 + 282.145841 0.736126 0.904762 + 307.899015 0.536075 0.952381 + 333.262903 0.903282 0.809524 + 340.217754 0.019722 0.190476 + 344.988867 0.019671 0.095238 + 346.988885 0.018032 0.095238 + 358.840278 0.999967 1.000000 + 409.201393 1.000000 0.000000 + +EXPECTED XYZ 264 + A01 3.85 3.22 1.9 + A02 4.89 3.27 1.6 + A03 5.87 3.31 1.33 + A04 6.3 3.38 1.19 + A05 13.01 11.44 7.64 + A06 16.14 11.99 6.81 + A07 19.35 12.41 6.06 + A08 20.41 11.97 5.3 + A09 43.5 42.81 32.65 + A10 45.58 42.37 30.95 + A11 48.99 43.2 29.9 + A12 50.73 44.02 29.96 + A13 74.46 78.76 66.06 + A14 75.66 76.42 64.08 + A15 78.36 81.34 65.41 + A16 70.52 73.3 59.16 + A17 74.98 75.98 60.69 + A18 72.85 77.3 60.25 + A19 73.09 75.52 64.54 + B01 3.47 3.08 1.41 + B02 4.41 3.25 0.9 + B03 5.04 3.23 0.58 + B04 5.19 3.11 0.47 + B05 13.36 11.59 5.56 + B06 15.97 12.03 3.69 + B07 19.2 12.49 2.2 + B08 19.73 11.52 1.17 + B09 42.19 41.84 29.34 + B10 44.83 42.17 25.93 + B11 48.06 42.9 23.01 + B12 49.63 43.08 21.34 + B13 66.21 72.54 64.61 + B14 70.16 67.1 60.33 + B15 75.46 78.69 51.58 + B16 57.47 59.58 47.66 + B17 68.33 66.45 49.05 + B18 63.89 70.29 51.3 + B19 61.12 62.16 59.79 + C01 4.97 4.75 1.98 + C02 5.18 4.65 1.23 + C03 5.51 4.58 0.71 + C04 5.77 4.61 0.67 + C05 24.57 23.44 10.14 + C06 28.1 24.64 5.22 + C07 31.15 25.28 2.2 + C08 30.85 23.68 1.35 + C09 49.16 49.36 32.37 + C10 51.72 50.72 26.53 + C11 55.24 53.14 21.93 + C12 56.87 53.62 18.46 + C13 57.68 65.65 62.7 + C14 63.46 56.66 55.49 + C15 73 76.11 40.78 + C16 44.73 46.38 36.8 + C17 60.64 55.73 38.1 + C18 52.15 60.27 41.5 + C19 48.13 49.18 54.38 + D01 4.19 4.41 1.93 + D02 4.48 4.72 1.24 + D03 4.55 4.78 0.8 + D04 4.32 4.53 0.78 + D05 27.33 28.55 12.95 + D06 28.68 30.04 7.25 + D07 29.51 31.01 3.41 + D08 27.55 28.44 1.83 + D09 56.06 58.19 38.21 + D10 56.03 58.46 30.02 + D11 56.2 59.33 24.44 + D12 56.19 59.41 19.14 + D13 48.21 57.42 59.53 + D14 58.18 49.14 51.36 + D15 70.98 73.73 33.63 + D16 34.31 35.73 28.22 + D17 54.27 47.53 29.58 + D18 41.67 50.64 32.28 + D19 36.95 37.82 48.09 + E01 4.15 4.75 2.03 + E02 4 4.98 1.37 + E03 3.3 4.49 0.86 + E04 3.11 4.3 0.86 + E05 13.11 14.9 7.06 + E06 12.26 15.23 4.18 + E07 11.53 15.57 2.27 + E08 9.69 13.74 1.51 + E09 39.15 42.08 27.33 + E10 37.43 41.51 22.23 + E11 36.99 42.5 18.85 + E12 36.4 42.58 16.27 + E13 39.97 49.81 56.15 + E14 52.08 41.07 46.36 + E15 68.71 70.76 26.45 + E16 25.7 26.97 21.28 + E17 48.53 40.6 22 + E18 31.62 40.82 23.35 + E19 31.19 31.19 43.4 + F01 1.51 1.91 1.06 + F02 1.29 2.04 0.98 + F03 1.16 2.09 0.82 + F04 1.14 2.04 0.8 + F05 6.53 8.25 5.13 + F06 5.61 8.66 4.38 + F07 4.6 8.77 3.7 + F08 3.45 7.63 2.78 + F09 37.8 41.07 30.91 + F10 35.92 40.76 29.03 + F11 35.42 41.99 29.07 + F12 34 41.8 28 + F13 32.13 42.12 51.99 + F14 45.72 33.34 40.77 + F15 66.26 67.29 19.65 + F16 17.02 18.07 14.4 + F17 41.59 32.53 15.16 + F18 26.26 35.26 18.81 + F19 24.3 23.6 37.48 + G01 2.31 3 2.27 + G02 2 3.21 2.58 + G03 1.66 3.21 2.75 + G04 1.58 3.03 2.6 + G05 8.99 11.08 8.79 + G06 7.68 11.3 9.56 + G07 6.52 11.5 10.2 + G08 5.5 10.85 10.55 + G09 38.29 41.75 33.45 + G10 35.83 41.16 34.11 + G11 34.56 41.83 35.63 + G12 33.69 42.14 36.7 + G13 25.95 35.68 48 + G14 40.6 27.62 36.14 + G15 63.72 63.63 14.35 + G16 10.85 11.82 9.58 + G17 37.23 27.64 11.62 + G18 20.28 28.97 14.15 + G19 17.7 16.74 31.7 + H01 2.56 3.04 2.92 + H02 2.34 3.2 4.12 + H03 2.12 3.28 5.43 + H04 2.06 3.18 5.29 + H05 10.07 11.6 11.24 + H06 9.01 11.68 14.81 + H07 8.22 12 19.42 + H08 7.25 11.55 21.45 + H09 39.25 42.31 36.81 + H10 37.58 41.85 40.37 + H11 37.16 43.07 45.79 + H12 36.27 43.78 49.47 + H13 21.47 30.78 44.22 + H14 36.49 23.35 32.38 + H15 61.58 60.55 10.95 + H16 8.21 8.71 6.91 + H17 33.04 23.26 8.38 + H18 16.22 24.35 10.41 + H19 12.86 11.84 26.82 + I01 4.22 4.44 5.28 + I02 4.35 4.48 8.36 + I03 4.4 4.44 11.94 + I04 4.48 4.58 12.17 + I05 15.15 15.78 15.23 + I06 14.56 15.12 19.52 + I07 14.37 14.81 24.48 + I08 14.11 14.76 30.03 + I09 41.03 42.58 36.94 + I10 40.85 42.23 40.73 + I11 40.86 42.33 45.05 + I12 41.31 42.73 47.77 + I13 17.26 25.93 40.23 + I14 32.66 19.63 28.81 + I15 59.37 57.18 7.79 + I16 4.97 5.32 4.32 + I17 28.62 18.88 5.48 + I18 11.58 18.98 7.25 + I19 9.58 8.34 22.87 + I20 0.45 0.4 0.33 + I21 2.28 1.78 0.98 + I22 2.37 1.95 0.85 + J01 2.15 1.9 2.6 + J02 2.57 2 4.72 + J03 2.93 1.95 8.1 + J04 3.15 1.92 10.76 + J05 11.73 11.6 11.81 + J06 12.98 11.93 16.19 + J07 13.91 12.07 20.95 + J08 14.01 11.59 24.35 + J09 40.75 41.22 36.34 + J10 41.26 41.07 39.74 + J11 42.63 41.68 44.51 + J12 44.02 41.78 49.25 + J13 13.82 21.69 35.98 + J14 28.87 16.33 25.08 + J15 56.04 52.29 4.97 + J16 2.46 2.63 2.29 + J17 24.04 14.75 3.15 + J18 8.12 14.49 4.55 + J19 5.98 4.79 17.76 + J20 8.26 5.37 1.04 + J21 11.52 7.81 1.62 + J22 14.67 10.72 2.6 + K01 5.63 4.7 4.86 + K02 6.74 4.58 7.23 + K03 8.04 4.48 9.73 + K04 9.39 4.76 11.79 + K05 16.66 15.39 14.44 + K06 18.72 15.18 18.23 + K07 21.56 15.5 22.97 + K08 23 15.02 25.37 + K09 42.5 42.02 36.05 + K10 44.55 41.63 39.71 + K11 47.19 41.96 44.03 + K12 49.9 43.14 47.21 + K13 10.61 17.44 31.24 + K14 24.84 13.19 21 + K15 53.12 48.05 3.19 + K16 1.05 1.14 1.13 + K17 19.93 11.34 1.67 + K18 5.3 10.47 2.73 + K19 3.95 2.76 13.94 + K20 30.61 26.43 11.04 + K21 34.91 29.6 11.78 + K22 38.95 34.57 18.4 + L01 3.88 3.12 2.32 + L02 4.93 3.2 2.69 + L03 5.75 3.14 3.02 + L04 7.31 3.79 3.4 + L05 13.29 11.54 9.39 + L06 16.22 11.73 10.32 + L07 19.95 12.08 12.06 + L08 20.79 11.31 12.01 + L09 43.22 42.09 33.78 + L10 45.52 41.88 34.65 + L11 49.04 42.87 35.98 + L12 51.03 43.83 37.78 + L13 7.45 12.77 25.59 + L14 21.26 10.76 17.73 + L15 49.45 43.12 2.14 + L16 0.47 0.49 0.5 + L17 16.04 8.49 0.78 + L18 2.91 6.5 1.39 + L19 2.5 1.45 10.28 + L20 38.7 33.98 20.86 + L21 39.36 35.23 21.23 + L22 41.36 38.77 23.51 + GS00 79.47 82.51 69.04 + GS01 72.62 74.94 59.17 + GS02 63.15 65.11 51.57 + GS03 54.72 56.51 45.03 + GS04 48.1 49.81 39.24 + GS05 42.22 43.64 34.45 + GS06 37.33 38.7 30.5 + GS07 32.38 33.61 26.11 + GS08 27.56 28.7 22.11 + GS09 22.5 23.4 17.99 + GS10 18.77 19.55 14.83 + GS11 15.48 16.08 12.04 + GS12 12.69 13.29 9.98 + GS13 10.35 10.81 7.97 + GS14 8.39 8.77 6.37 + GS15 6.45 6.79 4.97 + GS16 4.95 5.18 3.7 + GS17 3.58 3.82 2.76 + GS18 2.76 2.89 2.06 + GS19 1.97 2.08 1.45 + GS20 1.22 1.31 0.98 + GS21 1 1.05 0.74 + GS22 0.87 0.89 0.65 + GS23 0.34 0.32 0.32 + + diff --git a/scanin/scanin.c b/scanin/scanin.c new file mode 100644 index 0000000..94771fe --- /dev/null +++ b/scanin/scanin.c @@ -0,0 +1,1436 @@ + +/* + * Argyll Color Correction System + * + * Scanin: Input the scan of a test chart, and output cgats data + * Uses scanrd to do the hard work. + * + * Author: Graeme W. Gill + * Date: 29/1/97 + * + * Copyright 1995 - 2002 Graeme W. Gill + * All rights reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +/* + TTBD + + Add "single pixel patch" mode, for pure digital processing for + abstract profile creation. + + + */ + +#include +#include /* In case DOS binary stuff is needed */ +#include +#include +#include + +#include +#include +#include +#include + +#include "copyright.h" +#include "aconfig.h" +#include "numlib.h" +#include "cgats.h" +#include "icc.h" +#include "xicc.h" +#include "scanrd.h" +#include "tiffio.h" + +/* Utilities */ + +void fix_it8(char *o, char *i); + +#ifdef NT /* You'd think there might be some standards.... */ +# ifndef __BORLANDC__ +# define stricmp _stricmp +# endif +#else +# define stricmp strcasecmp +#endif + +#define TXBUF (256*1024L) + +/* NOTE: We aren't handling the libtiff error/warning messages !! */ + +/* Read a line of data from the input Grey, RGB or CMYK tiff file */ +/* return non-zero on error */ +int read_line( +void *fdata, +int y, +char *dst +) { + if (TIFFReadScanline((TIFF *)fdata, (tdata_t)dst, y, 0) < 0) + return 1; + return 0; +} + +/* Write a line of data to the diagnostic RGB tiff file */ +/* return non-zero on error */ +static int +write_line( +void *ddata, +int y, +char *src +) { + if (TIFFWriteScanline((TIFF *)ddata, (tdata_t)src, y, 0) < 0) + return 1; + return 0; +} + +void +usage(void) { + fprintf(stderr,"Scanin, Version %s\n",ARGYLL_VERSION_STR); + fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"usage: scanin [options] input.tif recogin.cht valin.cie [diag.tif]\n"); + fprintf(stderr," :- inputs 'input.tif' and outputs scanner 'input.ti3', or\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"usage: scanin -g [options] input.tif recogout.cht [diag.tif]\n"); + fprintf(stderr," :- outputs file 'recogout.cht', or\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"usage: scanin -o [options] input.tif recogin.cht [diag.tif]\n"); + fprintf(stderr," :- outputs file 'input.val', or\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"usage: scanin -c [options] input.tif recogin.cht scanprofile.[%s|mpp] pbase [diag.tif]\n",ICC_FILE_EXT_ND); + fprintf(stderr," :- inputs pbase.ti2 and outputs printer pbase.ti3, or\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"usage: scanin -r [options] input.tif recogin.cht pbase [diag.tif]\n"); + fprintf(stderr," :- inputs pbase.ti2+.ti3 and outputs pbase.ti3\n"); + fprintf(stderr,"\n"); + fprintf(stderr," -g Generate a chart reference (.cht) file\n"); + fprintf(stderr," -o Output patch values in .val file\n"); + fprintf(stderr," -c Use image to measure color to convert printer pbase .ti2 to .ti3\n"); + fprintf(stderr," -ca Same as -c, but accumulates more values to pbase .ti3\n"); + fprintf(stderr," from subsequent pages\n"); + fprintf(stderr," -r Replace device values in pbase .ti2/.ti3\n"); + fprintf(stderr," Default is to create a scanner .ti3 file\n"); + fprintf(stderr," -F x1,y1,x2,y2,x3,y3,x4,y4\n"); + fprintf(stderr," Don't auto recognize, locate using four fiducual marks\n"); + fprintf(stderr," -p Compensate for perspective distortion\n"); + fprintf(stderr," -a Recognise chart in normal orientation only (-A fallback as is)\n"); + fprintf(stderr," Default is to recognise all possible chart angles\n"); + fprintf(stderr," -m Return true mean (default is robust mean)\n"); + fprintf(stderr," -G gamma Approximate gamma encoding of image\n"); + fprintf(stderr," -v [n] Verbosity level 0-9\n"); + fprintf(stderr," -d [ihvglLIcrsonap] Generate diagnostic output (try -dipn)\n"); + fprintf(stderr," i diag - B&W of input image\n"); + fprintf(stderr," h diag - Horizontal edge/tick detection\n"); + fprintf(stderr," v diag - Vertical edge/tick detection\n"); + fprintf(stderr," g diag - Groups detected\n"); + fprintf(stderr," l diag - Lines detected\n"); + fprintf(stderr," L diag - All lines detected\n"); + fprintf(stderr," I diag - lines used to improve fit\n"); + fprintf(stderr," c diag - lines perspective corrected\n"); + fprintf(stderr," r diag - lines rotated\n"); + fprintf(stderr," s diag - diagnostic sample boxes rotated\n"); + fprintf(stderr," o diag - sample box outlines\n"); + fprintf(stderr," n diag - sample box names\n"); + fprintf(stderr," a diag - sample box areas\n"); + fprintf(stderr," p diag - pixel areas sampled\n"); + fprintf(stderr," -O outputfile Override the default output filename & extension.\n"); + exit(1); + } + + +int main(int argc, char *argv[]) +{ + int fa,nfa; /* current argument we're looking at */ + static char tiffin_name[MAXNAMEL+1] = { 0 }; /* TIFF Input file name (.tif) */ + static char datin_name[MAXNAMEL+4+1] = { 0 }; /* Data input name (.cie/.q60) */ + static char datout_name[MAXNAMEL+4+1] = { 0 }; /* Data output name (.ti3/.val) */ + static char recog_name[MAXNAMEL+1] = { 0 }; /* Reference chart name (.cht) */ + static char prof_name[MAXNAMEL+1] = { 0 }; /* scanner profile name (.cht) */ + static char diag_name[MAXNAMEL+1] = { 0 }; /* Diagnostic Output (.tif) name, if used */ + int verb = 1; + int tmean = 0; /* Return true mean, rather than robust mean */ + int repl = 0; /* Replace .ti3 device values from raster file */ + int outo = 0; /* Output the values read, rather than creating scanner .ti3 */ + int colm = 0; /* Use inage values to measure color for print profile. > 1 == append */ + int flags = SI_GENERAL_ROT; /* Default allow all rotations */ + + TIFF *rh = NULL, *wh = NULL; + uint16 depth, bps; /* Useful depth, bits per sample */ + uint16 tdepth; /* Total depth including alpha */ + uint16 pconfig, photometric; + uint16 rextrasamples; /* Extra "alpha" samples */ + uint16 *rextrainfo; /* Info about extra samples */ + int gotres = 0; + uint16 resunits; + float resx, resy; + + icColorSpaceSignature tiffs = 0; /* Type of tiff color space */ + + int i, j; + double gamma = 0.0; /* default */ + double _sfid[8], *sfid = NULL; /* Specified fiducials */ + int width, height; /* x and y size */ + + scanrd *sr; /* Scanrd object */ + int err; + char *errm; + int pnotscan = 0; /* Number of patches that wern't scanned */ + + if (argc <= 1) + usage(); + + error_program = argv[0]; + + /* Process the arguments */ + for(fa = 1;fa < argc;fa++) { + nfa = fa; /* skip to nfa if next argument is used */ + if (argv[fa][0] == '-') /* Look for any flags */ + { + char *na = NULL; /* next argument after flag, null if none */ + + if (argv[fa][2] != '\000') + na = &argv[fa][2]; /* next is directly after flag */ + else + { + if ((fa+1) < argc) + { + if (argv[fa+1][0] != '-') + { + nfa = fa + 1; + na = argv[nfa]; /* next is seperate non-flag argument */ + } + } + } + + if (argv[fa][1] == '?') { + usage(); + } else if (argv[fa][1] == 'v') { + verb = 2; + if (na != NULL && isdigit(na[0])) { + verb = atoi(na); + } + } else if (argv[fa][1] == 'm') { + tmean = 1; + + } else if (argv[fa][1] == 'g') { + flags |= SI_BUILD_REF; + repl = 0; + outo = 0; + colm = 0; + + } else if (argv[fa][1] == 'r') { + repl = 1; + outo = 0; + colm = 0; + + } else if (argv[fa][1] == 'o') { + repl = 0; + outo = 1; + colm = 0; + + } else if (argv[fa][1] == 'c') { + repl = 0; + outo = 0; + colm = 1; + if (argv[fa][2] != '\000' && argv[fa][2] == 'a') + colm = 2; + + /* Approximate gamma encoding of image */ + } else if (argv[fa][1] == 'G') { + fa = nfa; + if (na == NULL) usage(); + gamma = atof(na); + if (gamma < 0.0 || gamma > 5.0) + usage(); + + /* Use specified fiducials instead of auto recognition */ + } else if (argv[fa][1] == 'F') { + fa = nfa; + if (na == NULL) usage(); + if (sscanf(na, " %lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf ", + &_sfid[0], &_sfid[1], &_sfid[2], &_sfid[3], + &_sfid[4], &_sfid[5], &_sfid[6], &_sfid[7]) != 8) { + usage(); + } + + sfid = _sfid; + + /* Compensate for perspective */ + } else if (argv[fa][1] == 'p') { + flags |= SI_PERSPECTIVE; + + /* Don't recognise rotations */ + } else if (argv[fa][1] == 'a') { + flags &= ~SI_GENERAL_ROT; + + /* Don't recognise rotations, and read patches */ + /* anyway "as is", if everything else failes */ + } else if (argv[fa][1] == 'A') { + flags &= ~SI_GENERAL_ROT; + flags |= SI_ASISIFFAIL; + + } else if (argv[fa][1] == 'd' || argv[fa][1] == 'D') { + while (na != NULL && *na != '\000') { + switch (*na) { + case 'i': + flags |= SI_SHOW_IMAGE; + break; + case 'h': + flags |= SI_SHOW_DIFFSH; + break; + case 'v': + flags |= SI_SHOW_DIFFSV; + break; + case 'g': + flags |= SI_SHOW_GROUPS; + break; + case 'l': + flags |= SI_SHOW_LINES; + break; + case 'L': + flags |= SI_SHOW_ALL_LINES; + break; + case 'I': + flags |= SI_SHOW_IMPL; + break; + case 'c': + flags |= SI_SHOW_PERS; + break; + case 'r': + flags |= SI_SHOW_ROT; + break; + case 's': + flags |= SI_SHOW_SBOX; + break; + case 'o': + flags |= SI_SHOW_SBOX_OUTLINES; + break; + case 'n': + flags |= SI_SHOW_SBOX_NAMES; + break; + case 'a': + flags |= SI_SHOW_SBOX_AREAS; + break; + case 'p': + flags |= SI_SHOW_SAMPLED_AREA; + break; + default: + usage(); + } + na++; + } + + /* Output file name */ + } else if (argv[fa][1] == 'O') { + fa = nfa; + if (na == NULL) usage(); + strncpy(datout_name,na,MAXNAMEL); datout_name[MAXNAMEL] = '\000'; + + } else + usage(); + } else + break; + } + + /* TIFF Raster input file name */ + if (fa >= argc || argv[fa][0] == '-') usage(); + strncpy(tiffin_name,argv[fa],MAXNAMEL); tiffin_name[MAXNAMEL] = '\000'; + + if (datout_name[0] == '\000' /* Not been overridden */ + && (flags & SI_BUILD_REF) == 0 + && repl == 0 && colm == 0) { /* Not generate ref or replacing .ti3 dev */ + char *xl; + strncpy(datout_name,argv[fa],MAXNAMEL); datout_name[MAXNAMEL] = '\000'; + if ((xl = strrchr(datout_name, '.')) == NULL) /* Figure where extention is */ + xl = datout_name + strlen(datout_name); + if (outo == 0) /* Creating scan calib data */ + strcpy(xl,".ti3"); + else /* Just outputing values for some other purpose */ + strcpy(xl,".val"); + } + + /* .cht Reference file in or out */ + if (++fa >= argc || argv[fa][0] == '-') usage(); + strncpy(recog_name,argv[fa],MAXNAMEL); recog_name[MAXNAMEL] = '\000'; + + if (colm > 0) { + if (++fa >= argc || argv[fa][0] == '-') usage(); + strncpy(prof_name,argv[fa],MAXNAMEL); prof_name[MAXNAMEL] = '\000'; + } + + /* CGATS Data file input/output */ + if ((flags & SI_BUILD_REF) == 0 && outo == 0) { /* Not generate ref or just outputing */ + if (++fa >= argc || argv[fa][0] == '-') usage(); + if (outo == 0) { /* Creating scan calib data */ + /* Data file */ + strncpy(datin_name,argv[fa],MAXNAMEL); datin_name[MAXNAMEL] = '\000'; + } + if (repl != 0 || colm > 0) { /* Color from image or replacing .ti3 device data */ + strcpy(datin_name,argv[fa]); + strcat(datin_name,".ti2"); + strcpy(datout_name,argv[fa]); + strcat(datout_name,".ti3"); + } + } + + /* optional diagnostic file */ + if (++fa < argc) { + if (argv[fa][0] == '-') + usage(); + strncpy(diag_name,argv[fa],MAXNAMEL); diag_name[MAXNAMEL] = '\000'; + } else { /* Provide a default name */ + strcpy(diag_name,"diag.tif"); + } + + if (stricmp(diag_name, tiffin_name) == 0) { + error("Diagnostic output '%s' might overwrite the input '%s'!",diag_name,tiffin_name); + } + + /* ----------------------------------------- */ + /* Open up input tiff file ready for reading */ + /* Got arguments, so setup to process the file */ + if ((rh = TIFFOpen(tiffin_name, "r")) == NULL) + error("error opening read file '%s'",tiffin_name); + + TIFFGetField(rh, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(rh, TIFFTAG_IMAGELENGTH, &height); + + TIFFGetField(rh, TIFFTAG_BITSPERSAMPLE, &bps); + if (bps != 8 && bps != 16) + error("TIFF Input file '%s' must be 8 or 16 bits/channel",tiffin_name); + + /* See if there are alpha planes */ + TIFFGetFieldDefaulted(rh, TIFFTAG_EXTRASAMPLES, &rextrasamples, &rextrainfo); + + TIFFGetField(rh, TIFFTAG_SAMPLESPERPIXEL, &depth); + + if (rextrasamples > 0 && verb) + printf("%d extra (alpha ?) samples will be ignored\n",rextrasamples); + + tdepth = depth; + depth = tdepth - rextrasamples; + + if (depth != 1 && depth != 3 && depth != 4) + error("Input '%s' must be a Grey, RGB or CMYK tiff file",tiffin_name); + + TIFFGetField(rh, TIFFTAG_PHOTOMETRIC, &photometric); + if (depth == 1 && photometric != PHOTOMETRIC_MINISBLACK + && photometric != PHOTOMETRIC_MINISWHITE) + error("1 chanel input '%s' must be a Grey tiff file",tiffin_name); + else if (depth == 3 && photometric != PHOTOMETRIC_RGB) + error("3 chanel input '%s' must be an RGB tiff file",tiffin_name); + else if (depth == 4 && photometric != PHOTOMETRIC_SEPARATED) + error("4 chanel input '%s' must be a CMYK tiff file",tiffin_name); + + if (depth == 1) + tiffs = icSigGrayData; + else if (depth == 3) + tiffs = icSigRgbData; + else if (depth == 4) + tiffs = icSigCmykData; + + TIFFGetField(rh, TIFFTAG_PLANARCONFIG, &pconfig); + if (pconfig != PLANARCONFIG_CONTIG) + error("TIFF Input file '%s' must be planar",tiffin_name); + + + if (TIFFGetField(rh, TIFFTAG_RESOLUTIONUNIT, &resunits) != 0) { + TIFFGetField(rh, TIFFTAG_XRESOLUTION, &resx); + TIFFGetField(rh, TIFFTAG_YRESOLUTION, &resy); + + if (resunits == RESUNIT_NONE /* If it looks valid */ + || resunits == RESUNIT_INCH + || resunits == RESUNIT_CENTIMETER) + gotres = 1; + } + + /* -------------------------- */ + /* setup the diag output file */ + if (flags & SI_SHOW_FLAGS) { + if ((wh = TIFFOpen(diag_name, "w")) == NULL) + error("Can\'t create TIFF file '%s'!",diag_name); + + TIFFSetField(wh, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField(wh, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(wh, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(wh, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField(wh, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(wh, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(wh, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(wh, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + if (gotres) { + TIFFSetField(wh, TIFFTAG_RESOLUTIONUNIT, resunits); + TIFFSetField(wh, TIFFTAG_XRESOLUTION, resx); + TIFFSetField(wh, TIFFTAG_YRESOLUTION, resy); + } + TIFFSetField(wh, TIFFTAG_IMAGEDESCRIPTION, "Scanin diagnosis output"); + } + + /* -------------------------- */ + if (verb >= 2) { + printf("Input file '%s': w=%d, h=%d, d = %d, bpp = %d\n", + tiffin_name, width, height, depth, bps); + if (flags & SI_BUILD_REF) + printf("Build Scan Chart reference file '%s'\n",recog_name); + else { + printf("Data input file '%s'\n",datin_name); + printf("Data output file '%s'\n",datout_name); + printf("Chart reference file '%s'\n",recog_name); + } + if (flags & SI_SHOW_FLAGS) + printf("Creating diagnostic tiff file '%s'\n",diag_name); + } + + /* -------------------------- */ + /* Do the operation */ + + if ((sr = do_scanrd( + flags, /* option flags */ + verb, /* verbosity level */ + + gamma, + sfid, /* Specified fiducuals, if any */ + width, height, depth, tdepth, bps, /* Width, Height and Depth of input in pixels */ + read_line, /* Read line function */ + (void *)rh, /* Opaque data for read_line */ + + recog_name, /* reference file name */ + + write_line, /* Write line function */ + (void *)wh /* Opaque data for write_line */ + )) == NULL) { + if (flags & SI_SHOW_FLAGS) + TIFFClose(wh); + error("Unable to allocate scanrd object"); + } + + if ((err = sr->error(sr, &errm)) != 0) { + if ((flags & SI_SHOW_FLAGS) && err != SI_DIAG_WRITE_ERR) + TIFFClose(wh); /* Close diagnostic file */ + error("Scanin failed with code 0x%x, %s",err,errm); + } + + /* Read an output the values */ + if ((flags & SI_BUILD_REF) == 0) { /* Not generate ref */ + + /* -------------------------------------------------- */ + if (outo != 0) { /* Just output the values */ + /* Note value range is raw 0..255, */ + /* while all others output formats are out of 100 */ + cgats *ocg; /* output cgats structure */ + time_t clk = time(0); + struct tm *tsp = localtime(&clk); + char *atm = asctime(tsp); /* Ascii time */ + + /* Setup output cgats file */ + ocg = new_cgats(); /* Create a CGATS structure */ + ocg->add_other(ocg, "VALS"); /* Dummy type */ + ocg->add_table(ocg, tt_other, 0); /* Start the first table */ + + ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Calibration raster values",NULL); + ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll scanin", NULL); + atm[strlen(atm)-1] = '\000'; /* Remove \n from end */ + ocg->add_kword(ocg, 0, "CREATED",atm, NULL); + + ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t); + if (depth == 1) { + ocg->add_field(ocg, 0, "GREY", r_t); + } else if (depth == 3) { + ocg->add_field(ocg, 0, "RGB_R", r_t); + ocg->add_field(ocg, 0, "RGB_G", r_t); + ocg->add_field(ocg, 0, "RGB_B", r_t); + } else if (depth == 4) { + ocg->add_field(ocg, 0, "CMYK_C", r_t); + ocg->add_field(ocg, 0, "CMYK_M", r_t); + ocg->add_field(ocg, 0, "CMYK_Y", r_t); + ocg->add_field(ocg, 0, "CMYK_K", r_t); + } + + /* Initialise, ready to read out all the values */ + for (j = 0; ; j++) { + char id[100]; /* Input patch id */ + double P[4]; /* Robust/true mean values */ + int pixcnt; /* PIxel count */ + + if (tmean) { + if (sr->read(sr, id, NULL, P, NULL, &pixcnt) != 0) + break; + } else { + if (sr->read(sr, id, P, NULL, NULL, &pixcnt) != 0) + break; + } + + if (pixcnt == 0) + pnotscan++; + + if (depth == 1) { + ocg->add_set( ocg, 0, id, P[0]); + } else if (depth == 3) { + ocg->add_set( ocg, 0, id, P[0], P[1], P[2]); + } else if (depth == 4) { + ocg->add_set( ocg, 0, id, P[0], P[1], P[2], P[3]); + } + } + + if (verb) + printf("Writing output values to file '%s'\n",datout_name); + + if (ocg->write_name(ocg, datout_name)) + error("Write error to '%s' : %s",datout_name,ocg->err); + + ocg->del(ocg); /* Clean up */ + + /* -------------------------------------------------- */ + } else if (repl != 0) { /* Replace .ti3 device values */ + cgats *icg; /* input .ti2 cgats structure */ + cgats *ocg; /* input/output .ti3 cgats structure */ + int npat; /* Number of test patches */ + int dim = 0; /* Dimenstionality of device space */ + int fi; /* Field index */ + int isi, ili; /* Input file sample and location indexes */ + char *dfnames[5][4] = { /* Device colorspace names */ + { "" }, + { "GRAY_W" }, + { "" }, + { "RGB_R", "RGB_G", "RGB_B" }, + { "CMYK_C", "CMYK_M", "CMYK_Y", "CMYK_K" } + }; + int odim = 0; /* Output file device dimensionality */ + int dfi[5][4]; /* Output file device colorspace indexes */ + int osi; /* Output file sample id index */ + + /* Setup input .ti2 file */ + icg = new_cgats(); /* Create a CGATS structure */ + icg->add_other(icg, "CTI2"); /* Calibration Target Information 2 */ + if (icg->read_name(icg, datin_name)) + error("CGATS file '%s' read error : %s",datin_name,icg->err); + + if (icg->t[0].tt != tt_other || icg->t[0].oi != 0) + error("Input file '%s' isn't a CTI2 format file",datin_name); + + if (icg->ntables < 1) + error("Input file '%s' doesn't contain at least one table",datin_name); + + if ((npat = icg->t[0].nsets) <= 0) + error("Input file '%s' doesn't contain any data sets",datin_name); + + /* Figure out the color space */ + if ((fi = icg->find_kword(icg, 0, "COLOR_REP")) < 0) + error("Input file '%s' doesn't contain keyword COLOR_REP",datin_name); + + if (strcmp(icg->t[0].kdata[fi],"CMYK") == 0) { + dim = 4; + } else if (strcmp(icg->t[0].kdata[fi],"RGB") == 0) { + dim = 3; + } else if (strcmp(icg->t[0].kdata[fi],"W") == 0) { + dim = 1; + } else + error("Input file '%s' keyword COLOR_REP has unknown value",datin_name); + + /* Find fields we want in the input file */ + if ((isi = icg->find_field(icg, 0, "SAMPLE_ID")) < 0) + error("Input file '%s' doesn't contain field SAMPLE_ID",datin_name); + if (icg->t[0].ftype[isi] != nqcs_t) + error("Input file '%s' Field SAMPLE_ID is wrong type",datin_name); + + if ((ili = icg->find_field(icg, 0, "SAMPLE_LOC")) < 0) + error("Input file '%s' doesn't contain field SAMPLE_LOC",datin_name); + if (icg->t[0].ftype[ili] != cs_t + && icg->t[0].ftype[ili] != nqcs_t) + error("Input file '%s' Field SAMPLE_LOC is wrong type",datin_name); + + /* Setup input/output .ti3 file */ + ocg = new_cgats(); /* Create a CGATS structure */ + ocg->add_other(ocg, "CTI3"); /* Calibration Target Information 3 */ + if (ocg->read_name(ocg, datout_name)) + error("CGATS file '%s' read error : %s",datout_name,ocg->err); + + if (ocg->t[0].tt != tt_other || ocg->t[0].oi != 0) + error("Input file '%s' isn't a CTI3 format file",datout_name); + + if (ocg->ntables < 1) + error("Input file '%s' doesn't contain at least one table",datout_name); + + if (npat != ocg->t[0].nsets) + error("Input file '%s' doesn't contain same number of data sets",datout_name); + + + /* Find the fields we want in the output file */ + + /* Figure out the color space */ + if ((fi = ocg->find_kword(ocg, 0, "COLOR_REP")) < 0) + error("Input file '%s' doesn't contain keyword COLOR_REP",datout_name); + + if (strncmp(ocg->t[0].kdata[fi],"CMYK",4) == 0) { + odim = 4; + } else if (strncmp(ocg->t[0].kdata[fi],"RGB",3) == 0) { + odim = 3; + } else if (strncmp(ocg->t[0].kdata[fi],"W",1) == 0) { + odim = 1; + } else + error("Input file '%s' keyword COLOR_REP has unknown value",datout_name); + + if (odim != dim) + error("File '%s' has different device space to '%s'",datin_name, datout_name); + + if ((osi = ocg->find_field(ocg, 0, "SAMPLE_ID")) < 0) + error("Input file '%s' doesn't contain field SAMPLE_ID",datout_name); + if (ocg->t[0].ftype[osi] != nqcs_t) + error("Input file '%s' Field SAMPLE_ID is wrong type",datout_name); + + for (i = 0; i < dim; i++) { + if ((dfi[dim][i] = ocg->find_field(ocg, 0, dfnames[dim][i])) < 0) + error("Input '%s' file doesn't contain field %s", datout_name, dfnames[dim][i]); + if (ocg->t[0].ftype[dfi[dim][i]] != r_t) + error("Input '%s' Field %s is wrong type",datout_name,dfnames[dim][i]); + } + + /* Initialise, ready to read out all the values */ + for (i = sr->reset(sr); i > 0; i--) { /* For all samples in .tiff file */ + char loc[100]; /* Target patch location */ + double P[4]; /* Robust/raw mean values */ + int pixcnt; /* Pixel count */ + int k, e; + + if (tmean) + sr->read(sr, loc, NULL, P, NULL, &pixcnt); + else + sr->read(sr, loc, P, NULL, NULL, &pixcnt); + + if (pixcnt == 0) + pnotscan++; + + /* Search for this location in the .ti2 file */ + for (j = 0; j < npat; j++) { + if (strcmp(loc, (char *)icg->t[0].fdata[j][ili]) == 0) { + char *sidp = (char *)icg->t[0].fdata[j][isi]; + + /* Search for this sample id in .ti3 file */ + for (k = 0; k < npat; k++) { + if (strcmp(sidp, (char *)ocg->t[0].fdata[k][osi]) == 0) { + /* Update the device values */ + for (e = 0; e < dim; e++) { + double vv = 100.0 * P[e]/255.0; + *((double *)ocg->t[0].fdata[k][dfi[dim][e]]) = vv; + } + break; + } + } + if (k >= npat && verb >= 1) + printf("Warning: Couldn't find sample '%s' in '%s'\n",sidp,datout_name); + break; + } + } + if (j >= npat && verb >= 1) + printf("Warning: Couldn't find location '%s' in '%s'\n",loc,datin_name); + } + + /* Flush our changes */ + if (verb) + printf("Writing output values to file '%s'\n",datout_name); + + if (ocg->write_name(ocg, datout_name)) + error("Write error to file '%s' : %s",datout_name,ocg->err); + + ocg->del(ocg); /* Clean up */ + icg->del(icg); /* Clean up */ + + /* ---------------------------------------------------------- */ + } else if (colm > 0) { /* Using the image to measure color */ + /* All this needs to track the code in spectro/printread.c */ + cgats *icg; /* input .ti2 cgats structure */ + cgats *ocg; /* input/output .ti3 cgats structure */ + icmFile *rd_fp = NULL; /* Image to CIE lookup */ + icc *rd_icco = NULL; + icmLuBase *luo; + mpp *mlu = NULL; + time_t clk = time(0); + struct tm *tsp = localtime(&clk); + char *atm = asctime(tsp); /* Ascii time */ + int nmask = 0; /* Device colorant mask */ + int nchan = 0; /* Number of device chanels */ + int npat; /* Number of input patches (inc. padding) */ + int nopat = 0; /* Number of output patches */ + int si; /* Sample id index */ + int li; /* Location id index */ + int ti; /* Temp index */ + int fi; /* Colorspace index */ + + icg = new_cgats(); /* Create a CGATS structure */ + icg->add_other(icg, "CTI2"); /* special type Calibration Target Information 2 */ + icg->add_other(icg, "CAL"); /* There may be a calibration too */ + + if (icg->read_name(icg, datin_name)) + error("CGATS file '%s' read error : %s",datin_name,icg->err); + + if (icg->t[0].tt != tt_other || icg->t[0].oi != 0) + error("Input file '%s' isn't a CTI2 format file",datin_name); + if (icg->ntables < 1) + error("Input file '%s' doesn't contain at least one table",datin_name); + + if ((npat = icg->t[0].nsets) <= 0) + error("Input file '%s' has no sets of data",datin_name); + + /* Setup output cgats file */ + ocg = new_cgats(); /* Create a CGATS structure */ + ocg->add_other(ocg, "CTI3"); /* special type Calibration Target Information 3 */ + + if (colm > 1) { /* Appending information to .ti3 */ + + if (ocg->read_name(ocg, datout_name)) + error("CGATS file read error on '%s': %s",datout_name, ocg->err); + + if (ocg->t[0].tt != tt_other || ocg->t[0].oi != 0) + error("Input file '%s' isn't a CTI3 format file",datout_name); + if (ocg->ntables < 1) + error("Input file '%s' doesn't at least exactly one table",datout_name); + if ((nopat = ocg->t[0].nsets) <= 0) + error("Input file '%s' has no existing sets of data",datout_name); + + } else { /* Creating .ti3 */ + + ocg->add_table(ocg, tt_other, 0); /* Start the first table */ + + ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Calibration Target chart information 3",NULL); + ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll printread", NULL); + atm[strlen(atm)-1] = '\000'; /* Remove \n from end */ + ocg->add_kword(ocg, 0, "CREATED",atm, NULL); + ocg->add_kword(ocg, 0, "DEVICE_CLASS","OUTPUT", NULL); /* What sort of device this is */ + if ((ti = icg->find_kword(icg, 0, "SINGLE_DIM_STEPS")) >= 0) + ocg->add_kword(ocg, 0, "SINGLE_DIM_STEPS",icg->t[0].kdata[ti], NULL); + + if ((ti = icg->find_kword(icg, 0, "COMP_GREY_STEPS")) >= 0) + ocg->add_kword(ocg, 0, "COMP_GREY_STEPS",icg->t[0].kdata[ti], NULL); + + if ((ti = icg->find_kword(icg, 0, "MULTI_DIM_STEPS")) >= 0) + ocg->add_kword(ocg, 0, "MULTI_DIM_STEPS",icg->t[0].kdata[ti], NULL); + + if ((ti = icg->find_kword(icg, 0, "FULL_SPREAD_PATCHES")) >= 0) + ocg->add_kword(ocg, 0, "FULL_SPREAD_PATCHES",icg->t[0].kdata[ti], NULL); + + if ((ti = icg->find_kword(icg, 0, "TOTAL_INK_LIMIT")) >= 0) + ocg->add_kword(ocg, 0, "TOTAL_INK_LIMIT",icg->t[0].kdata[ti], NULL); + + /* See if there is a calibration in the .ti2, and copy it if there is */ + { + int oi, tab; + + oi = icg->get_oi(icg, "CAL"); + + for (tab = 0; tab < icg->ntables; tab++) { + if (icg->t[tab].tt == tt_other && icg->t[tab].oi == oi) { + break; + } + } + if (tab < icg->ntables) { + xcal *cal = NULL; + + if (verb) + printf("Copying .cal from '%s' to '%s'\n",datin_name,datout_name); + + if ((cal = new_xcal()) == NULL) { + error("new_xcal failed"); + } + if (cal->read_cgats(cal, icg, tab, datin_name) != 0) { + error("%s",cal->err); + } + + if (cal->write_cgats(cal, ocg)) { + error("%s",cal->err); + } + + cal->del(cal); + } + } + } + + if ((si = icg->find_field(icg, 0, "SAMPLE_ID")) < 0) + error("Input file '%s' doesn't contain field SAMPLE_ID",datin_name); + if (icg->t[0].ftype[si] != nqcs_t) + error("Input file '%s' Field SAMPLE_ID is wrong type",datin_name); + + /* Fields we want */ + if (colm > 1) { /* Appending information to .ti3 */ + if ((ti = ocg->find_field(ocg, 0, "SAMPLE_ID")) != 0) + error("Input file '%s' field SAMPLE_ID (%d) not in expected location (%d)", + datout_name, ti, 0); + } else { + ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t); + } + + if ((li = icg->find_field(icg, 0, "SAMPLE_LOC")) < 0) + error("Input file '%s' doesn't contain field SAMPLE_LOC",datin_name); + if (icg->t[0].ftype[li] != cs_t) + error("Input file '%s' field SAMPLE_LOC is wrong type",datin_name); + + /* Figure out the color space */ + if ((fi = icg->find_kword(icg, 0, "COLOR_REP")) < 0) + error("Input file '%s' doesn't contain keyword COLOR_REPS",datin_name); + + if ((nmask = icx_char2inkmask(icg->t[0].kdata[fi])) != 0) { + int i, j, ii; + int chix[ICX_MXINKS]; /* Device chanel indexes */ + int xyzix[3]; /* XYZ chanel indexes */ + char *ident, *bident; + char *xyzfname[3] = { "XYZ_X", "XYZ_Y", "XYZ_Z" }; + + nchan = icx_noofinks(nmask); + ident = icx_inkmask2char(nmask, 1); + bident = icx_inkmask2char(nmask, 0); + + /* Device channels */ + for (j = 0; j < nchan; j++) { + int imask; + char fname[100]; + + imask = icx_index2ink(nmask, j); + sprintf(fname,"%s_%s",nmask == ICX_W || nmask == ICX_K ? "GRAY" : bident, + icx_ink2char(imask)); + + if ((ii = icg->find_field(icg, 0, fname)) < 0) + error("Input file '%s' doesn't contain field %s",datin_name,fname); + if (icg->t[0].ftype[ii] != r_t) + error("Field %s is wrong type",fname); + + if (colm > 1) { /* Appending information to .ti3 */ + if (ocg->find_field(ocg, 0, fname) != 1 + j) + error("Input file '%s' field %s not in expected location",datout_name,fname); + } else { + ocg->add_field(ocg, 0, fname, r_t); + } + chix[j] = ii; + } + + /* Approximate XYZ and real XYZ */ + for (j = 0; j < 3; j++) { + if ((ii = icg->find_field(icg, 0, xyzfname[j])) >= 0) { + + if (icg->t[0].ftype[ii] != r_t) + error("Input file '%s' field %s is wrong type",datin_name,xyzfname[j]); + } + + if (colm > 1) { /* Appending information to .ti3 */ + if (ocg->find_field(ocg, 0, xyzfname[j]) != 1 + nchan + j) + error("Input file '%s' field %s not in expected location", + datout_name,xyzfname[j]); + } else { + ocg->add_field(ocg, 0, xyzfname[j], r_t); + } + xyzix[j] = ii; + } + + if (colm <= 1) { /* Creating .ti3 */ + char fname[100]; + sprintf(fname, "%s_XYZ", ident); + ocg->add_kword(ocg, 0, "COLOR_REP", fname, NULL); + } + + if (colm > 1) { /* Appending .ti3 data */ + + /* Check that all the patches match */ + for (ii = i = 0; i < npat; i++) { + + if (strcmp(((char *)icg->t[0].fdata[i][si]), "0") == 0) + continue; /* Padding, so skip it */ + + /* Id's */ + if (strcmp (((char *)icg->t[0].fdata[i][si]), + ((char *)ocg->t[0].fdata[ii][si])) != 0) + error("'%s' and '%s' field id's don't match at patch %d\n",datin_name,datout_name,i+1); + + /* device values */ + for (j = 0; j < nchan; j++) { + double ival, oval; + ival = *((double *)icg->t[0].fdata[i][chix[j]]); + oval = *((double *)ocg->t[0].fdata[ii][1 + j]); + if (fabs(ival - oval) > 0.001) + error("'%s' and '%s' device values (%f %f) don't match at patch %d %d\n",datin_name,datout_name,ival, oval, i+1, ii+1); + } + ii++; + } + if (ii != nopat) + error("Different number of patches in '%s' (%d) to expected(%d)",datout_name,nopat,ii); + + } else { /* Read all the test patches in, and create output slots */ + cgats_set_elem *setel; /* Array of set value elements */ + + if ((setel = (cgats_set_elem *)malloc(sizeof(cgats_set_elem) * (1 + nchan + 3))) == NULL) + error("Malloc failed!"); + + + for (ii = i = 0; i < npat; i++) { + int k = 0; + + if (strcmp(((char *)icg->t[0].fdata[i][si]), "0") == 0) + continue; /* Padding, so skip it */ + + /* Id */ + setel[k++].c = ((char *)icg->t[0].fdata[i][si]); + + /* device values */ + for (j = 0; j < nchan; j++) { + setel[k++].d = *((double *)icg->t[0].fdata[i][chix[j]]); + } + + /* Unset XYZ values */ + setel[k++].d = -1.0; + setel[k++].d = -1.0; + setel[k++].d = -1.0; + + ocg->add_setarr(ocg, 0, setel); + + ii++; + } + nopat = ii; + free(setel); + } + free(ident); + free(bident); + + } else + error("Input file '%s' keyword COLOR_REPS has unknown value",datin_name); + + /* Setup RGB to XYZ conversion */ + { + int inn, outn; /* Chanels for input and output spaces */ + icColorSpaceSignature ins, outs; /* Type of input and output spaces */ + int rv; + + /* Open up the file for reading */ + if ((rd_fp = new_icmFileStd_name(prof_name,"r")) == NULL) + error("Write: Can't open file '%s'",prof_name); + + if ((rd_icco = new_icc()) == NULL) + error("Read: Creation of ICC object failed"); + + /* Read the header and tag list */ + if ((rv = rd_icco->read(rd_icco,rd_fp,0)) == 0) { + + /* Get the Fwd table, absolute with XYZ override */ + if ((luo = rd_icco->get_luobj(rd_icco, icmFwd, icAbsoluteColorimetric, + icSigXYZData, icmLuOrdNorm)) == NULL) { + error("%d, %s",rd_icco->errc, rd_icco->err); + } + + /* Get details of conversion */ + luo->spaces(luo, &ins, &inn, &outs, &outn, NULL, NULL, NULL, NULL, NULL); + + /* Check that it matches what we expect */ + + } else { /* Not a valid ICC */ + inkmask cnv_nmask = 0; /* Conversion input nmask */ + + /* Close out the ICC profile */ + rd_icco->del(rd_icco); + rd_icco = NULL; + rd_fp->del(rd_fp); + rd_fp = NULL; + + /* If we don't have an ICC lookup object, look for an MPP */ + + if ((mlu = new_mpp()) == NULL) + error ("Creation of MPP object failed"); + + if ((rv = mlu->read_mpp(mlu, prof_name)) == 0) { + + /* mlu defaults to absolute XYZ lookup */ + mlu->get_info(mlu, &cnv_nmask, &inn, NULL, NULL, NULL, NULL, NULL, NULL); + + outn = 3; + outs = icSigXYZData; + + if ((ins = icx_colorant_comb_to_icc(cnv_nmask)) == 0) + error ("Couldn't match MPP mask to valid ICC colorspace"); + + } else { + mlu->del(mlu); + mlu = NULL; + error("File '%s' failed to read as ICC or MPP profile",prof_name); + } + } + if (inn != depth || tiffs != ins) + error("%s profile '%s' doesn't match TIFF file type",luo != NULL ? "ICC" : "MPP", prof_name); + } + + /* Initialise, ready to read out all the values */ + for (i = sr->reset(sr); i > 0; i--) { /* For all samples in .tiff file */ + char loc[100]; /* Target patch location */ + double P[ICX_MXINKS]; /* Robust/true mean values */ + double xyz[3]; /* profile XYZ value */ + int pixcnt; /* Pixel count */ + int k, e; + + if (tmean) + sr->read(sr, loc, NULL, P, NULL, &pixcnt); + else + sr->read(sr, loc, P, NULL, NULL, &pixcnt); + + if (pixcnt == 0) + pnotscan++; + + /* Search for this location in the .ti2 file */ + for (j = 0; j < npat; j++) { + if (strcmp(loc, (char *)icg->t[0].fdata[j][li]) == 0) { /* Got location */ + char *sidp = (char *)icg->t[0].fdata[j][si]; /* Get id */ + + if (strcmp(sidp, "0") == 0) + break; /* Padding, so ignore it */ + + /* Search for this sample id in .ti3 file */ + for (k = 0; k < nopat; k++) { + if (strcmp(sidp, (char *)ocg->t[0].fdata[k][si]) == 0) { + +//printf("Loc %s, ID %s got RGB value %f %f %f\n",sidp, loc, P[0], P[1], P[2]); + + /* Convert RGB to XYZ */ + for (e = 0; e < depth; e++) + P[e] /= 255.0; /* Convert to 0.0 .. 1.0 range */ + + /* Convert to XYZ */ + if (luo != NULL) + luo->lookup(luo, xyz, P); + else + mlu->lookup(mlu, xyz, P); + + /* Sanity check XYZ ? */ + // ~~~99 + + /* Update the XYZ values */ + for (e = 0; e < 3; e++) { + double ev = *((double *)ocg->t[0].fdata[k][1 + nchan + e]); + + if (ev != -1.0) + error("Found an existing value in '%s' file (%f)",datout_name,ev); + + *((double *)ocg->t[0].fdata[k][1 + nchan + e]) = 100.0 * xyz[e]; + } + break; + } + } + if (k >= nopat) + error("Couldn't find sample '%s' in '%s'\n",sidp,datout_name); + break; + } + } + if (j >= npat && verb >= 1) + error("Couldn't find location '%s' in '%s'\n",loc, datin_name); + } + + /* Warn if not all patch values have been filled */ + if (verb) { + int e, k; + for (k = 0; k < nopat; k++) { + for (e = 0; e < 3; e++) { + double ev = *((double *)ocg->t[0].fdata[k][1 + nchan + e]); + + if (ev == -1.0) + break; + } + if (e < 3) + break; + } + if (k < nopat) + printf("Not all sample values have been filled\n"); + else + printf("All sample values have been filled\n"); + } + + if (verb) + printf("Writing output values to file '%s'\n",datout_name); + + if (ocg->write_name(ocg, datout_name)) + error("File '%s' write error : %s",datout_name,ocg->err); + + if (luo != NULL) + luo->del(luo); + if (rd_icco != NULL) + rd_icco->del(rd_icco); + if (rd_fp != NULL) + rd_fp->del(rd_fp); + if (mlu != NULL) + mlu->del(mlu); + + ocg->del(ocg); /* Clean up */ + icg->del(icg); /* Clean up */ + + /* ----------------------------------- */ + } else { /* Normal scan calibration */ + cgats *icg; /* input cgats structure */ + cgats *ocg; /* output cgats structure */ + time_t clk = time(0); + struct tm *tsp = localtime(&clk); + char *atm = asctime(tsp); /* Ascii time */ + int ti; /* Temp index */ + int sx; /* Sample id index */ + int isLab = 0; /* D50 Lab reference */ + int Xx, Yx, Zx; /* XYZ_X, XYZ_Y, XYZ_Z index */ + int spec_n = 0; /* Number of spectral bands */ + double spec_wl_short;/* First reading wavelength in nm (shortest) */ + double spec_wl_long; /* Last reading wavelength in nm (longest) */ + int spi[XSPECT_MAX_BANDS]; /* CGATS indexes for each wavelength */ + int npat; /* Number of test patches in it8 chart */ + int nsetel = 0; /* Number of output set elements */ + cgats_set_elem *setel; /* Array of set value elements */ + + icg = new_cgats(); /* Create a CGATS structure */ + icg->add_other(icg, ""); /* Accept any type */ + if (icg->read_name(icg, datin_name)) + error("CGATS file '%s' read error : %s",datin_name,icg->err); + + /* ~~ should accept ti2 file and convert RGB to XYZ using */ + /* device cal., to make W/RGB/CMYK ->XYZ reading chart ~~ */ + if (icg->ntables < 1) + error("Input file '%s' doesn't contain at least one table",datin_name); + + if ((npat = icg->t[0].nsets) <= 0) + error("File '%s' no sets of data in first table",datin_name); + + /* Setup output cgats file */ + ocg = new_cgats(); /* Create a CGATS structure */ + ocg->add_other(ocg, "CTI3"); /* our special type is Calibration Target Information 3 */ + ocg->add_table(ocg, tt_other, 0); /* Start the first table */ + + ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Calibration Target chart information 3",NULL); + ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll target", NULL); + atm[strlen(atm)-1] = '\000'; /* Remove \n from end */ + ocg->add_kword(ocg, 0, "CREATED",atm, NULL); + + ocg->add_kword(ocg, 0, "DEVICE_CLASS","INPUT", NULL); /* What sort of device this is */ + ocg->add_kword(ocg, 0, "COLOR_REP","XYZ_RGB", NULL); + + /* Fields we want from input chart reference file */ + if ((sx = icg->find_field(icg, 0, "Sample_Name")) < 0) { + if ((sx = icg->find_field(icg, 0, "SAMPLE_NAME")) < 0) { + if ((sx = icg->find_field(icg, 0, "SAMPLE_LOC")) < 0) { + if ((sx = icg->find_field(icg, 0, "SAMPLE_ID")) < 0) { + error("Input file '%s' doesn't contain field SAMPLE_ID, Sample_Name or SAMPLE_NAME",datin_name); + } + } + } + } + if (icg->t[0].ftype[sx] != nqcs_t && icg->t[0].ftype[sx] != cs_t) + error("Input file '%s' field %s is wrong type", datin_name, icg->t[0].fsym[sx]); + + if ((Xx = icg->find_field(icg, 0, "XYZ_X")) < 0) { + if ((Xx = icg->find_field(icg, 0, "LAB_L")) < 0) + error("Input file '%s' doesn't contain field XYZ_X or LAB_L",datin_name); + + isLab = 1; + if (icg->t[0].ftype[Xx] != r_t) + error("Input file '%s' field LAB_L is wrong type",datin_name); + if ((Yx = icg->find_field(icg, 0, "LAB_A")) < 0) + error("Input file doesn't contain field LAB_A",datin_name); + if (icg->t[0].ftype[Yx] != r_t) + error("Input file '%s' field LAB_A is wrong type",datin_name); + if ((Zx = icg->find_field(icg, 0, "LAB_B")) < 0) + error("Input file '%s' doesn't contain field LAB_B",datin_name); + if (icg->t[0].ftype[Zx] != r_t) + error("Input file '%s' field LAB_B is wrong type",datin_name); + } else { + if (icg->t[0].ftype[Xx] != r_t) + error("Input file '%s' field XYZ_X is wrong type",datin_name); + if ((Yx = icg->find_field(icg, 0, "XYZ_Y")) < 0) + error("Input file '%s' doesn't contain field XYZ_Y",datin_name); + if (icg->t[0].ftype[Yx] != r_t) + error("Input file '%s' field XYZ_Y is wrong type",datin_name); + if ((Zx = icg->find_field(icg, 0, "XYZ_Z")) < 0) + error("Input file '%s' doesn't contain field XYZ_Z",datin_name); + if (icg->t[0].ftype[Zx] != r_t) + error("Input file '%s' field XYZ_Z is wrong type",datin_name); + } + + /* Find possible spectral fields in reference */ + if ((ti = icg->find_kword(icg, 0, "SPECTRAL_BANDS")) >= 0) { + spec_n = atoi(icg->t[0].kdata[ti]); + if ((ti = icg->find_kword(icg, 0, "SPECTRAL_START_NM")) < 0) + error ("Input file '%s' doesn't contain keyword SPECTRAL_START_NM",datin_name); + spec_wl_short = atof(icg->t[0].kdata[ti]); + if ((ti = icg->find_kword(icg, 0, "SPECTRAL_END_NM")) < 0) + error ("Input file '%s' doesn't contain keyword SPECTRAL_END_NM",datin_name); + spec_wl_long = atof(icg->t[0].kdata[ti]); + + /* Find the fields for spectral values */ + for (i = 0; i < spec_n; i++) { + char buf[100]; + int nm; + + /* Compute nearest integer wavelength */ + nm = (int)(spec_wl_short + ((double)i/(spec_n-1.0)) + * (spec_wl_long - spec_wl_short) + 0.5); + + sprintf(buf,"SPEC_%03d",nm); + + if ((spi[i] = icg->find_field(icg, 0, buf)) < 0) + error("Input file doesn't contain field %s",datin_name); + } + } + + ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t); + nsetel += 1; + ocg->add_field(ocg, 0, "XYZ_X", r_t); + ocg->add_field(ocg, 0, "XYZ_Y", r_t); + ocg->add_field(ocg, 0, "XYZ_Z", r_t); + nsetel += 3; + + /* If we have spectral information, output it too */ + if (spec_n > 0) { + char buf[100]; + + nsetel += spec_n; /* Spectral values */ + sprintf(buf,"%d", spec_n); + ocg->add_kword(ocg, 0, "SPECTRAL_BANDS",buf, NULL); + sprintf(buf,"%f", spec_wl_short); + ocg->add_kword(ocg, 0, "SPECTRAL_START_NM",buf, NULL); + sprintf(buf,"%f", spec_wl_long); + ocg->add_kword(ocg, 0, "SPECTRAL_END_NM",buf, NULL); + + /* Generate fields for spectral values */ + for (i = 0; i < spec_n; i++) { + int nm; + + /* Compute nearest integer wavelength */ + nm = (int)(spec_wl_short + ((double)i/(spec_n-1.0)) + * (spec_wl_long - spec_wl_short) + 0.5); + + sprintf(buf,"SPEC_%03d",nm); + ocg->add_field(ocg, 0, buf, r_t); + } + } + + if (depth == 1) { + ocg->add_field(ocg, 0, "GREY", r_t); + ocg->add_field(ocg, 0, "STDEV_GREY", r_t); + } else if (depth == 3) { + ocg->add_field(ocg, 0, "RGB_R", r_t); + ocg->add_field(ocg, 0, "RGB_G", r_t); + ocg->add_field(ocg, 0, "RGB_B", r_t); + ocg->add_field(ocg, 0, "STDEV_R", r_t); + ocg->add_field(ocg, 0, "STDEV_G", r_t); + ocg->add_field(ocg, 0, "STDEV_B", r_t); + } else if (depth == 4) { + ocg->add_field(ocg, 0, "CMYK_C", r_t); + ocg->add_field(ocg, 0, "CMYK_M", r_t); + ocg->add_field(ocg, 0, "CMYK_Y", r_t); + ocg->add_field(ocg, 0, "CMYK_K", r_t); + ocg->add_field(ocg, 0, "STDEV_C", r_t); + ocg->add_field(ocg, 0, "STDEV_M", r_t); + ocg->add_field(ocg, 0, "STDEV_Y", r_t); + ocg->add_field(ocg, 0, "STDEV_K", r_t); + } + nsetel += 2 * depth; + + if ((setel = (cgats_set_elem *)malloc(sizeof(cgats_set_elem) * nsetel)) == NULL) + error("Malloc failed!"); + + /* Initialise, ready to read out all the values */ + for (j = 0; j < npat; j++) { + char id[100]; /* Input patch id */ + + /* Normalise labels */ + fix_it8(id,((char *)icg->t[0].fdata[j][sx])); /* Copy and fix */ + + /* Search for matching id */ + for (i = sr->reset(sr); i > 0; i--) { + char tod[100]; /* Output patch id */ + char od[100]; /* Output patch id */ + double P[4]; /* Robust/true mean values */ + double sdP[4]; /* Standard deviation */ + int pixcnt; /* Pixel count */ + + if (tmean) + sr->read(sr, tod, NULL, P, sdP, &pixcnt); + else + sr->read(sr, tod, P, NULL, sdP, &pixcnt); + + if (pixcnt == 0) + pnotscan++; + + fix_it8(od,tod); + + if (strcmp(id,od) == 0) { + int k = 0, m; + double XYZ[3]; + + setel[k++].c = id; + + XYZ[0] = *((double *)icg->t[0].fdata[j][Xx]); + XYZ[1] = *((double *)icg->t[0].fdata[j][Yx]); + XYZ[2] = *((double *)icg->t[0].fdata[j][Zx]); + if (isLab) { + icmLab2XYZ(&icmD50, XYZ, XYZ); + XYZ[0] *= 100.0; + XYZ[1] *= 100.0; + XYZ[2] *= 100.0; + } + + setel[k++].d = XYZ[0]; + setel[k++].d = XYZ[1]; + setel[k++].d = XYZ[2]; + + if (spec_n > 0) { + for (m = 0; m < spec_n; m++) { + setel[k++].d = *((double *)icg->t[0].fdata[j][spi[m]]); + } + } + + for (m = 0; m < depth; m++) + setel[k++].d = P[m] * 100.0/255.0; + for (m = 0; m < depth; m++) + setel[k++].d = sdP[m] * 100.0/255.0; + + ocg->add_setarr(ocg, 0, setel); + + break; + } + } + if (i <= 0 && verb >= 1) + printf("Warning: Couldn't match field '%s'\n",id); + } + + if (verb) + printf("Writing output values to file '%s'\n",datout_name); + + if (ocg->write_name(ocg, datout_name)) + error("Output file '%s' write error : %s",datout_name, ocg->err); + + free(setel); + + ocg->del(ocg); /* Clean up */ + icg->del(icg); /* Clean up */ + + } + } + + if (pnotscan > 0) + warning("A total of %d patches had no value set!",pnotscan); + + /* Clean up */ + sr->free(sr); + + TIFFClose(rh); + + if (flags & SI_SHOW_FLAGS) + TIFFClose(wh); + + return 0; +} + +/* Fix IT8 chart labels */ +void fix_it8(char *o, char *i) { + if (strcmp(i,"Dmin")==0) { + strcpy(o,"GS00"); + return; + } + if (strcmp(i,"Dmax")==0) { + strcpy(o,"GS23"); + return; + } + while (!isdigit(*i) && *i != '\000') /* Skip non-numbers */ + *o++ = *i++; + if (i[0] != '\000' && i[1] == '\000') /* Single last digit */ + *o++ = '0'; /* Add leading zero */ + strcpy(o, i); /* Copy remainder */ +} + +/********************************************************************************/ diff --git a/scanin/scanrd.c b/scanin/scanrd.c new file mode 100644 index 0000000..a915e44 --- /dev/null +++ b/scanin/scanrd.c @@ -0,0 +1,4659 @@ + +/* + * Raster Color Target Scan Input module + * This is the core chart recognition code. + * + * Author: Graeme Gill + * + * Copyright 1995 - 2008 Graeme W. Gill, All right reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +/* + * To Do: + * Add option to output a raster file made from the .cht and example values. + * + * Fix sboxes parameters/digitization to fix "droop" in box areas. + * Scale parameters with image size. + * To handle high res, introduce automatic sub-sampler. + * Change reference parser to make it more forgiving - use cgats parser ? + */ + +#undef DEBUG + +#define VERSION "1.0" + +/* Behaviour defines */ +#undef DIAGN /* Allow diagonal connectivity of groups */ +#define AA_LINES /* Plot diagnostics using anti-aliased lines */ + +#define MATCHCC 0.3 /* Match correlation threshold - reject any match under this */ + /* (Might want to be able to override this in command line) */ + +#define ALT_ROT_TH 0.7 /* Correlation threshold of alternate rotations to be greater than this */ + +#define TH (20.0 * 20.0) /* Initial color change threshhold */ + +#undef DBG +#define dbgo stdout +#define DBG(aaa) fprintf aaa, fflush(dbgo) + +#include +/* #include */ /* In case DOS binary stuff is needed */ +#include +#include + +#include +#include +/* #include */ + +#include "numlib.h" +#include "scanrd_.h" + +/* ------------------------------------------------- */ +/* Implementations of public functions */ +static void free_scanrd(scanrd *s); +static int scanrd_reset(scanrd *s); +static int scanrd_read(scanrd *ps, char *id, double *P, double *mP, + double *sdP, int *cnt); +static unsigned int scanrd_error(scanrd *s, char **errm); + +/* Forward internal function declaration */ +static scanrd_ *new_scanrd(int flags, int verb, double gammav, + int (*write_line)(void *ddata, int y, char *src), void *ddata, + int w, int h, int d, int td, int p, + int (*read_line)(void *fdata, int y, char *dst), void *fdata, + char *refname); +static int read_input(scanrd_ *s); +static int calc_lines(scanrd_ *s); +static int show_lines(scanrd_ *s); +static int calc_perspective(scanrd_ *s); +static int calc_rotation(scanrd_ *s); +static int calc_elists(scanrd_ *s, int ref); +static int write_elists(scanrd_ *s); +static int read_relists(scanrd_ *s); +static int do_match(scanrd_ *s); +static int compute_ptrans(scanrd_ *s); +static int compute_man_ptrans(scanrd_ *s, double *sfids); +static int improve_match(scanrd_ *s); +static int setup_sboxes(scanrd_ *s); +static int do_value_scan(scanrd_ *s); +static int compute_xcc(scanrd_ *s); +//static int restore_best(scanrd_ *s); +static int show_sbox(scanrd_ *s); +static int show_groups(scanrd_ *s); +static int scanrd_write_diag(scanrd_ *s); +static void toRGB(unsigned char *dst, unsigned char *src, int depth, int bpp); +static void XYZ2Lab(double *out, double *in); +static void pval2Lab(double *out, double *in, int depth); +/* ------------------------------------------------- */ + +/* Read in a chart, and either create a reference or make values available, */ +/* by using reset() and read() to get values read */ +scanrd *do_scanrd( +int flags, /* option flags */ +int verb, /* verbosity level */ + +double gammav, /* Apprimate gamma encoding of image (0.0 = default 2.2) */ +double *sfid, /* Specified four fiducials x1, y1 .. x4, y4, NULL if auto recognition */ + /* Typical clockwise from top left */ + +int w, int h, /* Width and Height of input raster in pixels */ +int d, int td, int p, /* Useful plane depth, Total depth, Bit presision of input pixels */ +int (*read_line)(void *fdata, int y, char *dst), /* Read RGB line of source file */ +void *fdata, /* Opaque data for read_line */ + +char *refname, /* reference file name */ + +int (*write_line)(void *ddata, int y, char *src), /* Write RGB line of diag file */ +void *ddata /* Opaque data for write_line */ +) { + scanrd_ *s; + + /* allocate the basic object */ + if (verb >= 2) + DBG((dbgo,"About to allocate scanrd_ object\n")); + if ((s = new_scanrd(flags, verb, gammav, write_line, ddata, w, h, d, td, p, read_line, fdata, refname)) == NULL) + return NULL; + + if (s->errv != 0) /* Some other error from new_scanrd() */ + return (scanrd *)s; + + if (s->verb >= 2) + DBG((dbgo,"About to read input tiff file and discover groups\n")); + if (read_input(s)) + goto sierr; /* Error */ + + if (s->flags & SI_SHOW_GROUPS) + if (show_groups(s)) + goto sierr; /* Error */ + + if (s->verb >= 2) + DBG((dbgo,"About to calculate edge lines\n")); + if (calc_lines(s)) + goto sierr; /* Error */ + if (s->verb >= 2) + DBG((dbgo,"%d useful edges out of %d\n",s->novlines, s->noslines)); + + if (s->flags & SI_PERSPECTIVE) { + if (s->verb >= 2) + DBG((dbgo,"About to calculate perspective correction\n")); + if (calc_perspective(s)) { + if (s->flags & SI_SHOW_LINES) { + s->flags &= ~SI_SHOW_PERS; /* Calc perspective failed! */ + s->flags &= ~SI_SHOW_ROT; /* Calc rotation not done! */ + show_lines(s); + } + goto sierr; /* Error */ + } + } + + if (s->verb >= 2) + DBG((dbgo,"About to calculate rotation\n")); + if (calc_rotation(s)) { + if (s->flags & SI_SHOW_LINES) { + s->flags &= ~SI_SHOW_ROT; /* Calc rotation failed! */ + show_lines(s); + } + goto sierr; /* Error */ + } + + if (s->flags & SI_BUILD_REF) { /* If generating a chart reference file */ + /* Calculate the edge lists and write it to the file */ + if (s->verb >= 2) + DBG((dbgo,"About to build feature information\n")); + if (calc_elists(s, 1)) /* reference */ + goto sierr; /* Error */ + + if (s->verb >= 2) + DBG((dbgo,"About to write feature reference information\n")); + if (write_elists(s)) + goto sierr; /* Error */ + } else { + /* If we are matching to the reference and generating an output data file */ + int rv; + + /* Calculate the edge lists read for a match */ + if (s->verb >= 2) + DBG((dbgo,"About to calculate feature information\n")); + if (calc_elists(s, 0)) /* match */ + goto sierr; /* Error */ + + if (s->verb >= 2) + DBG((dbgo,"About to read reference feature information\n")); + if (read_relists(s)) + goto sierr; /* Error */ + if (s->verb >= 2) + DBG((dbgo,"Read of chart reference file succeeded\n")); + + if (sfid != NULL) { /* Manual matching */ + if (s->verb >= 2) + DBG((dbgo,"Using manual matching\n")); + + if (s->havefids == 0) { + s->errv = SI_NO_FIDUCIALS_ERR; + sprintf(s->errm,"Chart recognition definition file doesn't contain fiducials"); + goto sierr; /* Error */ + } + if (compute_man_ptrans(s, sfid)) + goto sierr; + + /* Do the actual scan given out manual transformation matrix */ + if (s->verb >= 2) + DBG((dbgo,"About to setup value scanrdg boxes\n")); + if (setup_sboxes(s)) + goto sierr; + if (s->verb >= 2) + DBG((dbgo,"About to read raster values\n")); + if (do_value_scan(s)) + goto sierr; + + } else { /* Automatic matching */ + + /* Attempt to match input file with reference */ + if (s->verb >= 2) + DBG((dbgo,"About to match features\n")); + if ((rv = do_match(s)) != 0) { + if (rv == 1) { /* No reasonable rotation found */ + s->errv = SI_POOR_MATCH; + sprintf(s->errm,"Pattern match wasn't good enough"); + } + goto sierr; + } + + /* If there is patch matching data and more than one */ + /* feasible matching rotation, try and discriminate between them. */ + if (s->xpt && s->norots > 1) { + int i, j; + int flags = s->flags; + + s->flags &= ~SI_SHOW_SAMPLED_AREA; /* Don't show areas for trials */ + + /* For each candidate rotation, scan in the pixel values */ + for (s->crot = 0; s->crot < s->norots; s->crot++) { + + /* Compute transformation from reference to input file */ + if (s->verb >= 2) + DBG((dbgo,"About to compute match transform for rotation %f deg.\n", + DEG(s->rots[s->crot].irot))); + if (compute_ptrans(s)) + goto sierr; + + /* Setup the input boxes ready for scanning in the input values */ + if (s->verb >= 2) + DBG((dbgo,"About to setup value scanrdg boxes\n")); + if (setup_sboxes(s)) + goto sierr; + + /* Scan in the pixel values */ + if (s->verb >= 2) + DBG((dbgo,"About to read raster values\n")); + if (do_value_scan(s)) + goto sierr; + + /* Copy to this rotation values so that the best can be restored */ + if (s->xpt != 0) { /* Got expected patch values to compare with */ + if (s->verb >= 2) + DBG((dbgo,"About to compute expected value correlation\n")); + if (compute_xcc(s)) + goto sierr; + } + } + + /* Pick the best from the candidate rotation */ + if (s->verb >= 2) { + DBG((dbgo,"Expected value distance values are:\n")); + for (i = 0; i < s->norots; i++) { + DBG((dbgo,"%d, rot %f: %f\n", i, DEG(s->rots[i].irot), s->rots[i].xcc)); + } + } + + for (j = 0, i = 1; i < s->norots; i++) { + if (s->rots[i].xcc < s->rots[j].xcc) + j = i; + } + + if (s->verb >= 2) + DBG((dbgo,"Chosen rotation %f deg. as best\n",DEG(s->rots[j].irot))); + + s->crot = j; + s->flags = flags; /* Restore flags */ + } + + /* Setup transformation to be that for chosen rotation for diagnostics */ + if (s->verb >= 2) + DBG((dbgo,"About to compute final match transform\n")); + if (compute_ptrans(s)) + goto sierr; + + if (s->verb >= 2) + DBG((dbgo,"Improve match\n")); + if (improve_match(s)) + goto sierr; + + /* After choosing rotation of improving the fit, rescan the values */ + if (s->verb >= 2) + DBG((dbgo,"About to setup value scanrdg boxes\n")); + if (setup_sboxes(s)) + goto sierr; + if (s->verb >= 2) + DBG((dbgo,"About to read raster values\n")); + if (do_value_scan(s)) + goto sierr; + } + + if (s->flags & SI_SHOW_SBOX) { + show_sbox(s); /* Draw sample box outlines on diagnostic raster */ + } + } + if (s->flags & SI_SHOW_LINES) + if(show_lines(s)) + goto sierr; /* Error */ + +sierr:; + if (s->verb >= 2) + DBG((dbgo,"About to write diag file\n")); + if (scanrd_write_diag(s)) + return (scanrd *)s; /* Error */ + + return (scanrd *)s; +} + + +/********************************************************************************/ + +/* Allocate the basic scanrd object */ +/* Return NULL on failure to allocate */ +/* Need to check errv for other problems */ +static scanrd_ +*new_scanrd( + int flags, /* option flags */ + int verb, /* verbosity level */ + double gammav, /* Approximate gamma encoding of image (0.0 = default 2.2) */ + int (*write_line)(void *ddata, int y, char *src), /* Write RGB line of diag file */ + void *ddata, /* Opaque data for write_line() */ + int w, int h, /* Width and Height of input raster in pixels */ + int d, int td, int p, /* Useful plane Depth, Total depth, Bit presision of input pixels */ + int (*read_line)(void *fdata, int y, char *dst), /* Read RGB line of source file */ + void *fdata, /* Opaque data for read_line() */ + + char *refname /* reference file name */ +) { + scanrd_ *s; + + if ((s = (scanrd_ *)calloc(1, sizeof(scanrd_))) == NULL) + return NULL; + + /* Public functions */ + s->public.reset = scanrd_reset; + s->public.read = scanrd_read; + s->public.error = scanrd_error; + s->public.free = free_scanrd; + + if (flags & (SI_SHOW_ROT | SI_SHOW_PERS | SI_SHOW_IMPL | SI_SHOW_ALL_LINES)) + flags |= SI_SHOW_LINES; /* Key all line stuff off SI_SHOW_LINES */ + + if (flags & (SI_SHOW_SBOX_OUTLINES | SI_SHOW_SBOX_NAMES | SI_SHOW_SBOX_AREAS)) + flags |= SI_SHOW_SBOX;; /* Key all sample box stuff off SI_SHOW_SBOX */ + + if (write_line == NULL) + flags &= ~SI_SHOW_FLAGS; /* If no diag file, turn off show flags */ + + s->flags = flags; + s->verb = verb; + + s->errv = 0; + s->errm[0] = '\0'; + + if (gammav <= 0.0) + gammav = 2.2; /* default */ + s->gammav = gammav; + s->width = w; + s->height = h; + s->depth = d; + s->tdepth = td; + s->bpp = p; + + if (d > MXDE) { + s->errv = SI_PIX_DEPTH_ERR; + sprintf(s->errm,"scanrd: Pixel depth is too large"); + return s; + } + + if (p != 8 && p != 16) { + s->errv = SI_BIT_DEPTH_ERR; + sprintf(s->errm,"scanrd: Pixel bits/pixel is not 8 or 16"); + return s; + } + if (p == 8) + s->bypp = 1; + else + s->bypp = 2; + + if (verb >= 2) + DBG((dbgo,"Verbosity = %d, flags = 0x%x\n",verb, flags)); + + /* RGB Diagnostic output raster array requested */ + if ((flags & SI_SHOW_FLAGS) && write_line != NULL) { + if ((s->out = malloc(3 * w * h)) == NULL) { + s->errv = SI_MALLOC_DIAG_RAST; + sprintf(s->errm,"scanrd: Diagnostic output raster array malloc failed"); + return s; + } + } + + s->noslines = 0; + s->novlines = 0; + s->gdone = NULL; + s->irot = 0.0; + s->norots = 0; + + s->ppc[0] = 0.0; + s->ppc[1] = 0.0; + s->ppc[2] = 0.0; + s->ppc[3] = 0.0; + + /* Set overall perspective transform to null */ + s->ptrans[0] = 1.0; + s->ptrans[1] = 0.0; + s->ptrans[2] = 0.0; + s->ptrans[3] = 0.0; + s->ptrans[4] = 1.0; + s->ptrans[5] = 0.0; + s->ptrans[6] = 0.0; + s->ptrans[7] = 0.0; + + INIT_ELIST(s->xelist); + INIT_ELIST(s->yelist); + INIT_ELIST(s->ixelist); + INIT_ELIST(s->iyelist); + INIT_ELIST(s->rxelist); + INIT_ELIST(s->ryelist); + s->rbox_shrink = 0.9; + s->xpt = 0; + + s->nsbox = 0; + s->sboxes = NULL; + s->sbstart = NULL; + s->sbend = NULL; + s->csi = 0; + s->cei = 0; + s->alist = NULL; + + s->next_read = 0; + + s->refname = refname; + + s->inited = 0; + s->vrego = s->vregn = NULL; + s->no_vo = s->no_vn = 0; + s->hrego = s->hregn = NULL; + s->no_ho = s->no_hn = 0; + s->th = TH; + s->divval = 0.25; + s->adivval = 0.0; + s->divc = 0; + + /* aa line init */ + s->aa_inited = 0; /* Let line init do the rest */ + s->coverage = NULL; + + /* Callbacks */ + s->read_line = read_line; + s->fdata = fdata; + + s->write_line = write_line; + s->ddata = ddata; + + return s; +} + +static void free_elist_array(elist *el); + +/* Free the object up */ +static void +free_scanrd( +scanrd *ps +) { + scanrd_ *s = (scanrd_ *)ps; /* Cast public to private */ + points *tp; + + free_elist_array(&s->xelist); + free_elist_array(&s->yelist); + free_elist_array(&s->ixelist); + free_elist_array(&s->iyelist); + free_elist_array(&s->rxelist); + free_elist_array(&s->ryelist); + + if (s->sboxes != NULL) + free(s->sboxes); + if (s->sbstart != NULL) + free(s->sbstart); + if (s->sbend != NULL) + free(s->sbend); + s->alist = NULL; + + /* Free up done line list */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->r != NULL) + free(tp->r); + free(tp); + END_FOR_ALL_ITEMS(tp); + s->gdone = NULL; + + /* Points were deleted with gdone ??? */ + if(s->vrego != NULL) + free(s->vrego); + if(s->vregn) + free(s->vregn); + if(s->hrego != NULL) + free(s->hrego); + if(s->hregn != NULL) + free(s->hregn); + s->inited = 1; + + /* Free up output diag array */ + if (s->out != NULL) + free(s->out); + + /* Free up aa line array */ + if (s->coverage != NULL) + free(s->coverage); + free(s); +} + + +/* Return the error flag, and set the message pointer */ +static unsigned int +scanrd_error(scanrd *ps, char **errm) { + scanrd_ *s = (scanrd_ *)ps; /* Cast public to private */ + *errm = s->errm; + return s->errv; +} + +/********************************************************************************/ +static int analize(scanrd_ *s, unsigned char *inp[6], int y); + +/* Read in and process the input file */ +/* Return non-zero on error */ +static int +read_input(scanrd_ *s) { + unsigned char *in[6]; /* Pointer to six input buffers */ + int w = s->width; /* Raster width */ + int h = s->height; /* Raster height */ + int i, y; + + /* Allocate input line buffers */ + for (i = 0; i < 6; i++) { + if ((in[i] = malloc(s->tdepth * w * s->bypp)) == NULL) { + s->errv = SI_MALLOC_INPUT_BUF; + sprintf(s->errm,"scanrd: Failed to malloc input line buffers"); + return 1; + } + } + + /* Prime the input buffers with 5 lines */ + for (y = 0; y < 5; y++) { + if (s->read_line(s->fdata, y, (char *)in[y])) { + s->errv = SI_RAST_READ_ERR; + sprintf(s->errm,"scanrd: read_line() returned error"); + return 1; + } + } + /* Process the tiff file line by line (Assume at least 6 lines in total raster) */ + for (; y < h; ++y) { + unsigned char *tt; + if (s->read_line(s->fdata, y, (char *)in[5])) { + s->errv = SI_RAST_READ_ERR; + sprintf(s->errm,"scanrd: read_line() returned error"); + return 1; + } + + if (analize(s, in, y)) { + return 1; + } + + tt = in[0]; /* Shuffle buffers about */ + in[0] = in[1]; + in[1] = in[2]; + in[2] = in[3]; + in[3] = in[4]; + in[4] = in[5]; + in[5] = tt; + + } + s->adivval /= (double)s->divc; /* Average divider value, 1.0 = 0 degrees, 0.0 = 45 degrees */ + if (s->adivval < 0.0) + s->adivval = 0.0; + else if (s->adivval > 1.0) + s->adivval = 1.0; + + if (s->verb >= 2) + DBG((dbgo,"adivval = %f\n",s->adivval)); + + /* Free the input line buffers */ + for (i = 0; i < 6; i++) + free(in[i]); + + return 0; +} + +/********************************************************************************/ + +#ifdef NEVER /* Before 22/5/2004 */ +#define THRN 1.0 /* Threshold above average ratio - numerator */ +#define THRD 2.0 /* Threshold above average ratio - denominator */ + +#define THAWF 1.0 /* Threshold average adaptation filter weight, fixed value (TH) */ +#define THAWP 4.0 /* Threshold average adaptation filter weight, previous value */ +#define THAWN 1.0 /* Threshold average adaptation filter weight, new value */ + +#else /* Current values */ + +#define THRN 1.0 /* Threshold above average ratio - numerator */ +#define THRD 1.5 /* Threshold above average ratio - denominator */ + +#define THAWF 1.0 /* Threshold average adaptation filter weight, fixed value (TH) */ +#define THAWP 5.0 /* Threshold average adaptation filter weight, previous value */ +#define THAWN 1.0 /* Threshold average adaptation filter weight, new value */ + +#endif + +/* ~~~ minimum raster size needs to be specified/checked ~~~~ */ +#define MIN_NO_LINES 16 /* Minimum number of valid fitted lines to estimate rotation */ + +/* Criteria for accepting lines for angle calculation (valid lines) */ +#define MAX_MWID_TO_LEN 0.1 +#define MIN_POINT_TO_AREA 0.9 /* Minimum point desity over the lines area */ +#define SD_WINDOW 1.5 /* Allow += 1.5 of a standard deviation for robust angle calc. */ +#define ELISTCDIST 800 /* 1/ELISTCDIST = portion of refence edge list legth to coalesce over */ + +/* Criteria for accepting lines for improring final fit */ +#define IMP_MATCH 0.10 /* Proportion of average tick spacing */ + +/* The following should be scaled to the resolution of the image ? */ +#define MIN_POINTS 10 /* Minimum points to calculate line */ +#define MIN_LINE_LENGTH 10.0 +#define CUT_CHUNKS 128 /* cut groups along diagonals - must be power of 2 */ + +static int add_region(scanrd_ *s, region *rego, int no_o, region *regn, int no_n, int y); + +/* Process a line of the TIFF file */ +/* return non-zero on error */ +static int +analize( +scanrd_ *s, +unsigned char *inp[6], /* current and previous 5 lines */ +int y /* Current line y */ +) { + int w = s->width; + int stride = s->tdepth * s->width; /* In pixels */ + unsigned short *gamma = s->gamma; + int x,i; + unsigned short *inp2[6]; /* current and previous 5 lines (16bpp) equivalent of inp[] */ + unsigned char *in[6]; /* six input lines (8bpp) */ + unsigned short *in2[6]; /* six input lines (16bpp) */ + region *tr; + double tdh,tdv; /* Horizontal/virtical detect levels */ + double tdmag; + double atdmag = 0.0; /* Average magnitude over a line */ + int atdmagc = 0; /* Average magnitude over a line count */ + double linedv = 0.0; /* Lines average divider value */ + int linedc = 0; /* Lines average count */ + int xo3 = s->tdepth * 3; /* Xoffset by 3 pixels */ + int xo2 = s->tdepth * 2; /* Xoffset by 2 pixels */ + int xo1 = s->tdepth * 1; /* Xoffset by 1 pixels */ + + for (x = 0; x < 6; x++) /* Create 16 bpp version of line pointers */ + inp2[x] = (unsigned short *)inp[x]; + + if (s->inited == 0) { + /* Init gamma conversion lookup and region tracking. */ + /* The assumption is that a typical chart has an approx. visually */ + /* uniform distribution of samples, so that a typically gamma */ + /* encoded scan image will have an average pixel value of 50%. */ + /* If a the chart has a different gamma encoding (ie. linear), */ + /* then we convert it to gamma 2.2 encoded to (hopefuly) enhance */ + /* the patch contrast. */ + if (s->bpp == 8) + for (i = 0; i < 256; i++) { + int byteb1; + + byteb1 = (int)(0.5 + 255 * pow( i / 255.0, s->gammav/2.2 )); + gamma[i] = byteb1; + } + else + for (i = 0; i < 65536; i++) { + int byteb1; + + byteb1 = (int)(0.5 + 65535 * pow( i / 65535.0, s->gammav/2.2 )); + gamma[i] = byteb1; + } + + if ((s->vrego = (region *) malloc(sizeof(region) * (w+1)/2)) == NULL) { + s->errv = SI_MALLOC_VREGION; + sprintf(s->errm,"vreg malloc failed"); + return 1; + } + s->no_vo = 0; + if ((s->vregn = (region *) malloc(sizeof(region) * (w+1)/2)) == NULL) { + s->errv = SI_MALLOC_VREGION; + sprintf(s->errm,"vreg malloc failed"); + return 1; + } + s->no_vn = 0; + if ((s->hrego = (region *) malloc(sizeof(region) * (w+1)/2)) == NULL) { + s->errv = SI_MALLOC_VREGION; + sprintf(s->errm,"vreg malloc failed"); + return 1; + } + s->no_ho = 0; + if ((s->hregn = (region *) malloc(sizeof(region) * (w+1)/2)) == NULL) { + s->errv = SI_MALLOC_VREGION; + sprintf(s->errm,"vreg malloc failed"); + return 1; + } + s->no_hn = 0; + INIT_LIST(s->gdone); + s->inited = 1; + } + + /* Un-gamma correct the latest input line */ + if (s->bpp == 8) + for (x = 0; x < stride; x++) + inp[5][x] = (unsigned char)gamma[inp[5][x]]; + else + for (x = 0; x < stride; x++) + inp2[5][x] = gamma[inp2[5][x]]; + + /* Compute difference output for line y-3 */ + atdmagc = w - 5; /* Magnitude count (to compute average) */ + for (x = 3; x < (w-2); x++) { /* Allow for -3 to +2 from x */ + unsigned char *out = s->out; + int e; + int ss; + int idx = ((y-2) * w + x) * 3; /* Output raster index in bytes */ + + if (s->bpp == 8) + for (i = 0; i < 6; i++) + in[i] = inp[i] + x * s->tdepth; /* Strength reduce */ + else + for (i = 0; i < 6; i++) { + in2[i] = inp2[i] + x * s->tdepth; /* Strength reduce */ + in[i] = (unsigned char *)in2[i]; /* track 8bpp pointers */ + } + + if (s->flags & SI_SHOW_IMAGE) { /* Create B&W image */ + toRGB(out + idx, in[2], s->depth, s->bpp); /* Convert to RGB */ + out[idx] = out[idx+1] = out[idx+2] = (2 * out[idx] + 7 * out[idx+1] + out[idx+2])/10; + } + + ss = 0; /* Sign of cross components the same vote */ + tdh = tdv = 0.0; + + if (s->bpp == 8) + for (e = 0; e < s->depth; e++) { + int d1,d2; + /* Compute Gxp */ + d1 = -in[0][-xo3+e] + -in[0][-xo2+e] + -in[0][-xo1+e] + + -in[0][ 0+e] + -in[0][ xo1+e] + -in[0][ xo2+e] + + -in[1][-xo3+e] + -in[1][-xo2+e] + -in[1][-xo1+e] + + -in[1][ 0+e] + -in[1][ xo1+e] + -in[1][ xo2+e] + + -in[2][-xo3+e] + -in[2][-xo2+e] + -in[2][-xo1+e] + + -in[2][ 0+e] + -in[2][ xo1+e] + -in[2][ xo2+e] + + in[3][-xo3+e] + in[3][-xo2+e] + in[3][-xo1+e] + + in[3][ 0+e] + in[3][ xo1+e] + in[3][ xo2+e] + + in[4][-xo3+e] + in[4][-xo2+e] + in[4][-xo1+e] + + in[4][ 0+e] + in[4][ xo1+e] + in[4][ xo2+e] + + in[5][-xo3+e] + in[5][-xo2+e] + in[5][-xo1+e] + + in[5][ 0+e] + in[5][ xo1+e] + in[5][ xo2+e]; + /* Compute Gyp */ + d2 = -in[0][-xo3+e] + -in[1][-xo3+e] + -in[2][-xo3+e] + + -in[3][-xo3+e] + -in[4][-xo3+e] + -in[5][-xo3+e] + + -in[0][-xo2+e] + -in[1][-xo2+e] + -in[2][-xo2+e] + + -in[3][-xo2+e] + -in[4][-xo2+e] + -in[5][-xo2+e] + + -in[0][-xo1+e] + -in[1][-xo1+e] + -in[2][-xo1+e] + + -in[3][-xo1+e] + -in[4][-xo1+e] + -in[5][-xo1+e] + + in[0][ 0+e] + in[1][ 0+e] + in[2][ 0+e] + + in[3][ 0+e] + in[4][ 0+e] + in[5][ 0+e] + + in[0][+xo1+e] + in[1][+xo1+e] + in[2][+xo1+e] + + in[3][+xo1+e] + in[4][+xo1+e] + in[5][+xo1+e] + + in[0][+xo2+e] + in[1][+xo2+e] + in[2][+xo2+e] + + in[3][+xo2+e] + in[4][+xo2+e] + in[5][+xo2+e]; + + if ((d1 >= 0 && d2 >=0) + || (d1 < 0 && d2 < 0)) + ss++; /* Sign was the same */ + tdh += d1/4.5 * d1/4.5; /* (4.5 = 6x6/4x2, to scale original tuned values) */ + tdv += d2/4.5 * d2/4.5; + } + else + for (e = 0; e < s->depth; e++) { + int d1,d2; + /* Compute Gxp */ + d1 = -in2[0][-xo3+e] + -in2[0][-xo2+e] + -in2[0][-xo1+e] + + -in2[0][ 0+e] + -in2[0][ xo1+e] + -in2[0][ xo2+e] + + -in2[1][-xo3+e] + -in2[1][-xo2+e] + -in2[1][-xo1+e] + + -in2[1][ 0+e] + -in2[1][ xo1+e] + -in2[1][ xo2+e] + + -in2[2][-xo3+e] + -in2[2][-xo2+e] + -in2[2][-xo1+e] + + -in2[2][ 0+e] + -in2[2][ xo1+e] + -in2[2][ xo2+e] + + in2[3][-xo3+e] + in2[3][-xo2+e] + in2[3][-xo1+e] + + in2[3][ 0+e] + in2[3][ xo1+e] + in2[3][ xo2+e] + + in2[4][-xo3+e] + in2[4][-xo2+e] + in2[4][-xo1+e] + + in2[4][ 0+e] + in2[4][ xo1+e] + in2[4][ xo2+e] + + in2[5][-xo3+e] + in2[5][-xo2+e] + in2[5][-xo1+e] + + in2[5][ 0+e] + in2[5][ xo1+e] + in2[5][ xo2+e]; + /* Compute Gyp */ + d2 = -in2[0][-xo3+e] + -in2[1][-xo3+e] + -in2[2][-xo3+e] + + -in2[3][-xo3+e] + -in2[4][-xo3+e] + -in2[5][-xo3+e] + + -in2[0][-xo2+e] + -in2[1][-xo2+e] + -in2[2][-xo2+e] + + -in2[3][-xo2+e] + -in2[4][-xo2+e] + -in2[5][-xo2+e] + + -in2[0][-xo1+e] + -in2[1][-xo1+e] + -in2[2][-xo1+e] + + -in2[3][-xo1+e] + -in2[4][-xo1+e] + -in2[5][-xo1+e] + + in2[0][ 0+e] + in2[1][ 0+e] + in2[2][ 0+e] + + in2[3][ 0+e] + in2[4][ 0+e] + in2[5][ 0+e] + + in2[0][+xo1+e] + in2[1][+xo1+e] + in2[2][+xo1+e] + + in2[3][+xo1+e] + in2[4][+xo1+e] + in2[5][+xo1+e] + + in2[0][+xo2+e] + in2[1][+xo2+e] + in2[2][+xo2+e] + + in2[3][+xo2+e] + in2[4][+xo2+e] + in2[5][+xo2+e]; + + if ((d1 >= 0 && d2 >=0) + || (d1 < 0 && d2 < 0)) + ss++; /* Sign was the same */ + + tdh += d1/(4.5 * 257) * d1/(4.5 * 257); /* Scale to 0..255 range */ + tdv += d2/(4.5 * 257) * d2/(4.5 * 257); + } + + tdmag = tdh + tdv; + + if (tdmag < (32.0 * s->th)) + atdmag += tdmag; /* Average magnitude over a line */ + else + atdmag += 32.0 * s->th; + + /* if over threshold */ + /* (Cut long lines up to prevent long lines being */ + /* (thrown away due to attached blobs) */ + if (tdmag >= s->th + && (x & (CUT_CHUNKS-1)) != (y & (CUT_CHUNKS-1))) { + double tt; + double av; /* Angle value of current pixel */ + tt = (tdv - tdh)/(tdh + tdv); /* Partial angle */ + linedv += fabs(tt); + linedc++; + + if (ss >= (s->depth/2+1)) /* Assume signs are the same if clear majority */ + av = 3.0 + tt; + else + av = 1.0 - tt; + + /* Separate the orthogonal elements */ + if (av >= s->divval && av < (s->divval + 2.0)) { + if (s->flags & SI_SHOW_DIFFSH) + out[idx] = (char)255; /* Red */ + /* Add point to new region */ + /* See if we can add to last region */ + if (s->no_hn > 0 && x == s->hregn[s->no_hn-1].hx) + s->hregn[s->no_hn-1].hx++; + else { /* Add another */ + if (s->no_hn >= (w+1)/2) { + s->errv = SI_INTERNAL; + sprintf(s->errm,"Internal, no_hn is too large"); + return 1; + } + s->hregn[s->no_hn].lx = x; + s->hregn[s->no_hn].hx = x+1; + s->hregn[s->no_hn].p = NULL; + s->no_hn++; + } + } else { + if (s->flags & SI_SHOW_DIFFSV) + out[idx+1] = (char)255; /* Green */ + /* Add point to new region */ + /* See if we can add to last region */ + if (s->no_vn > 0 && x == s->vregn[s->no_vn-1].hx) + s->vregn[s->no_vn-1].hx++; + else { /* Add another */ + if (s->no_vn >= (w+1)/2) { + s->errv = SI_INTERNAL; + sprintf(s->errm,"Internal, no_vn is too large"); + return 1; + } + s->vregn[s->no_vn].lx = x; + s->vregn[s->no_vn].hx = x+1; + s->vregn[s->no_vn].p = NULL; + s->no_vn++; + } + } + } + } + + if (linedc != 0) { /* Adapt divider value to line */ + linedv /= (double)linedc; /* Compute average over the line */ + linedv = (linedv * linedv); /* Square to even out linedv vs angle */ + linedv = (1.65 * (linedv - 0.12)); /* Compensate for random offsets */ + s->adivval += linedv; + s->divc++; + s->divval = (7.0 * s->divval + linedv)/8.0; /* Average over 8 lines */ + if (s->divval < 0.0) + s->divval = 0.0; + else if (s->divval > 1.0) + s->divval = 1.0; + if (s->verb >= 5) + DBG((dbgo,"linedv = %f, divval = %f\n",linedv,s->divval)); + } + + /* Adjust the threshold */ + atdmag /= (double)atdmagc; /* compute average magnitude over the line */ + s->th = (s->th * THRD)/(THRN + s->divval);/* Convert threshold to average */ + s->th = ((THAWF * TH) + (THAWP * s->th) + (THAWN * atdmag))/(THAWF + THAWP + THAWN); + s->th = (s->th * (THRN + s->divval))/THRD; /* Convert average back to threshold */ + + /* Add vertical regions */ + if (add_region(s,s->vrego,s->no_vo,s->vregn,s->no_vn,y-2)) + return 1; + + /* Add horizontal regions */ + if (add_region(s,s->hrego,s->no_ho,s->hregn,s->no_hn,y-2)) + return 1; + + /* shuffle them along */ + tr = s->vrego; + s->vrego = s->vregn; /* move new to old */ + s->vregn = tr; /* old to new */ + s->no_vo = s->no_vn; + s->no_vn = 0; + + tr = s->hrego; + s->hrego = s->hregn; /* move new to old */ + s->hregn = tr; /* old to new */ + s->no_ho = s->no_hn; + s->no_hn = 0; + + return 0; +} + +/********************************************************************************/ +/* Point list code */ + +/* allocate a new (empty) points structure */ +/* return NULL on error */ +static points * +new_points( +scanrd_ *s +) { + points *ps; + static int pn = 0; + if ((ps = (points *) malloc(sizeof(points))) == NULL) { + s->errv = SI_MALLOC_POINTS; + sprintf(s->errm,"new_points: malloc failed"); + return NULL; + } + ps->mxno = 0; + ps->no = 0; + ps->nop = 0; + ps->r = NULL; + ps->pn = pn; + pn++; + return ps; +} + +/* destroy a points structure */ +static void +destroy_points( +scanrd_ *s, +points *ps) { + if (ps->r != NULL) /* Free any array pointed to */ + free(ps->r); + free (ps); +} + +/* Add another run to a points object */ +/* return non-zero on error */ +static int +add_run( +scanrd_ *s, +points *ps, +int lx, +int hx, +int y) + { + if (ps->no == ps->mxno) { /* Need some more space */ + ps->mxno = (2 * ps->mxno) + 5; /* New size */ + if ((ps->r = (run *) realloc(ps->r, sizeof(run) * ps->mxno)) == NULL) { + s->errv = SI_REALLOC_POINTS; + sprintf(s->errm,"add_run: realloc failed"); + return 1; + } + } + ps->r[ps->no].lx = lx; + ps->r[ps->no].hx = hx; + ps->r[ps->no].y = y; + ps->no++; /* One more run */ + ps->nop += hx - lx; /* Total of pixels */ + return 0; +} + +/* copy src points to dest */ +/* Return non-zero on error */ +static int +copy_points( +scanrd_ *s, +points *dst, +points *src +) { + int i; + for (i = 0; i < src->no; i++) { + if (add_run(s,dst,src->r[i].lx,src->r[i].hx,src->r[i].y)) + return 1; + } + return 0; +} + +/********************************************************************************/ + +/* Add a new region of points to the line points lists */ +/* Note that regions are assumed to be non-overlapping x sorted */ +/* Return non-zero on error */ +static int +add_region( +scanrd_ *s, +region *rego, /* Old regions */ +int no_o, /* No of old region */ +region *regn, /* New regions */ +int no_n, /* No of new region */ +int y /* Y value */ +) { + int osp,op,np; /* Old/new pointers */ + + osp = 0; + for (np = 0; np < no_n; np++) { /* Process all new runs */ + /* Advance start pointer until we get to runs that may touch */ +#ifdef DIAGN + while (osp < no_o && rego[osp].hx < regn[np].lx) +#else + while (osp < no_o && rego[osp].hx <= regn[np].lx) +#endif + osp++; + /* For all old runs that may touch new */ +#ifdef DIAGN + for(op = osp; op < no_o && rego[op].lx <= regn[np].hx; op++) { +#else + for(op = osp; op < no_o && rego[op].lx < regn[np].hx; op++) { +#endif + +#ifdef DIAGN + if (rego[op].hx >= regn[np].lx && rego[op].lx <= regn[np].hx) { +#else + if (rego[op].hx > regn[np].lx && rego[op].lx < regn[np].hx) { +#endif + /* Old region touches new */ + if (regn[np].p == NULL) { /* No group for new yet */ + regn[np].p = rego[op].p; /* Make part of the same group */ + if (add_run(s, regn[np].p,regn[np].lx,regn[np].hx,y)) /* add new run to group */ + return 1; + } else if (regn[np].p != rego[op].p) { /* Touches different group */ + int j; + points *tp = rego[op].p; /* Old region to be renamed/merged */ + if (copy_points(s,regn[np].p,tp)) /* Merge old with current new */ + return 1; /* Error */ + DEL_LINK(s->gdone,tp); /* Don't need other any more */ + for (j = 0; j < no_o; j++) /* Fix all references to this group */ + if (rego[j].p == tp) + rego[j].p = regn[np].p; + for (j = 0; j < no_n; j++) + if (regn[j].p == tp) + regn[j].p = regn[np].p; + destroy_points(s,tp); + } + } + } + /* Finished all relevant old runs */ + if (regn[np].p == NULL) { /* No old touched, so start new group */ + if ((regn[np].p = new_points(s)) == NULL) + return 1; /* Error */ + ADD_ITEM_TO_TOP(s->gdone,regn[np].p); /* Stash it in points list */ + if (add_run(s, regn[np].p,regn[np].lx,regn[np].hx,y)) /* add new run to group */ + return 1; /* Error */ + } + } + return 0; +} + +/********************************************************************************/ + +/* Apply partial perspective to an xy point */ +/* (We omit the two offset parameters, since we don't need them) */ +void ppersp(scanrd_ *s, double *xx, double *yy, double x, double y, double *ppc) { + double den; + + /* Offset the partial perspective transform */ + x -= ppc[2]; + y -= ppc[3]; + + den = ppc[0] * x + ppc[1] * y + 1.0; + + if (fabs(den) < 1e-6) { + if (den < 0.0) + den = -1e-6; + else + den = 1e-6; + } + *xx = x/den + ppc[2]; + *yy = y/den + ppc[3]; +} + + +/* Apply inverse partial perspective to an xy point */ +void invppersp(scanrd_ *s, double *x, double *y, double xx, double yy, double *ppc) { + double den; + + /* Offset the partial perspective transform */ + xx -= ppc[2]; + yy -= ppc[3]; + + den = - ppc[0] * xx - ppc[1] * yy + 1.0; + + if (fabs(den) < 1e-6) { + if (den < 0.0) + den = -1e-6; + else + den = 1e-6; + } + *x = xx/den + ppc[2]; + *y = yy/den + ppc[3]; +} + +/********************************************************************************/ + +/* Compute the least squares best line fit for a group */ +/* Return non-zero if failed */ +static int +points_to_line( +scanrd_ *s, +points *ps) { + int i,j; + point *vv; /* Point vectors */ + int nop = ps->nop; /* Number of points */ + double sx,sy; /* Sum */ + double mx,my; /* Mean */ + double a; /* Angle, Clockwise from 12o'clock */ + double mw,len; /* mean width, length */ + double x1,y1,x2,y2; /* Start/end point of fitted line */ + + ps->flag = 0; + + if (nop < MIN_POINTS) /* Don't bother if too few pixels */ + return 0; + + /* Convert runs to individual points, and compute mean */ + if ((vv = (point *) malloc(sizeof(point) * nop)) == NULL) { + s->errv = SI_MALLOC_POINT2LINE; + sprintf(s->errm,"scanrd: points_to_line: malloc failed"); + return 1; + } + + sx = sy = 0.0; + for (j = i = 0; i < ps->no; i++) { /* For all runs */ + int x,y; + int hx = ps->r[i].hx, lx = ps->r[i].lx; + + y = ps->r[i].y; + sy += (hx - lx) * y; + for (x = lx; x < hx; x++, j++) { /* Convert to points */ + sx += x; + vv[j].x = x; + vv[j].y = y; + } + } + mx = sx/(double)nop; /* Centroid (mean) of points */ + my = sy/(double)nop; + + /* Offset points to centroid */ + for (i=0; i < nop; i++) { + vv[i].x -= mx; + vv[i].y -= my; + } + + /* Compute ad and bd, then A, B, C */ + /* From Graphics Gems V, pp 91-97, */ + /* "The Best Least-Squares Line Fit" */ + /* by David Alciatore and Rick Miranda. */ + { + double ad, bd; /* a' and b' values */ + double xd, yd; /* temp x' and y' */ + double A, B; /* line equation */ + double abn; /* A & B normalizer */ + + xd = yd = bd = 0.0; + for (i = 0; i < nop; i++) { + double x, y; + + x = vv[i].x; + y = vv[i].y; + xd += x * x; + yd += y * y; + bd += x * y; + } + ad = xd - yd; + + /* Equation of best fit line is Ax + By = C */ + A = 2 * bd; + B = -(ad + sqrt(ad * ad + 4.0 * bd * bd)); + /* C = A * mx + B * my; */ + + /* Compute angle */ + /* A = abn * cos(a), B = -abn * sin(a) */ + + abn = sqrt(A * A + B * B); /* Normalize A & B */ + if (fabs(abn) < 1e-6) { /* No dominant direction */ + a = 0.0; + } else { + a = acos(A/abn); + } + /* Make angle +ve */ + while (a < 0.0) a += M_PI; + } + + /* Now figure out the bounding box for the line + other stats */ + { + double s,c; + double pl,nl; /* Positive length, negative length */ + s = sin(a); + c = cos(a); + for (mw = 0.0, pl = 0.0, nl = 0.0, i = 0; i < nop; i++) + { + double npj; /* Projection onto normal */ + double lpj; /* Projection onto line */ + npj = -c * vv[i].x + s * vv[i].y; + if (npj < 0) + mw -= npj; + else + mw += npj; + lpj = s * vv[i].x + c * vv[i].y; + if (lpj > pl) + pl = lpj; + if (lpj < nl) + nl = lpj; + } + mw = 2.0 * mw/(double)nop; /* Mean width */ + + x1 = mx + s * nl; + y1 = my + c * nl; + x2 = mx + s * pl; + y2 = my + c * pl; + len = pl - nl; + } + + ps->mx = mx; /* Mean point */ + ps->my = my; + ps->a = a; /* Angle */ + ps->mw = mw; /* Mean width */ + ps->len = len; /* Mean length */ + ps->x1 = x1; /* Start/end point of fitted line */ + ps->y1 = y1; + ps->x2 = x2; + ps->y2 = y2; + ps->flag = F_LINESTATS; /* Line stats valid */ + + /* Compute the Constrained to 90 degrees angle */ + /* We use the adivval to figure out where to split angles */ + /* Split at 0 if adivval == 0.0, split at 45 if adivval == 1.0 */ + if (a >= (M_PI * (1.0 - s->adivval/4.0))) + ps->ca = a - M_PI; + else if (a >= (M_PI * (0.5 - s->adivval/4.0))) + ps->ca = a - M_PI_2; + else + ps->ca = a; + + if (s->verb >= 5) + DBG((dbgo,"Angle %f, CA = %f, length = %f, mean width = %f, Line %f,%f to %f,%f\n", + DEG(a),DEG(ps->ca),len,mw,x1,y1,x2,y2)); + free(vv); + +/* printf("~~stats: mw = %f, len = %f, mw/len = %f, area = %f\n", + mw, len, mw/len, ((double)nop/(len * (mw + 0.01)))); */ + /* Look at stats to see what lines are acceptable for further processing */ + if ( len >= MIN_LINE_LENGTH + && mw/len <= MAX_MWID_TO_LEN + && ((double)nop/(len * (mw + 0.01))) >= MIN_POINT_TO_AREA) { + ps->flag |= F_VALID; /* Line stats valid to use */ +/* printf("~~set valid\n"); */ + } + return 0; +} + +static int +calc_lines( +scanrd_ *s +) { + points *tp; + s->noslines = 0; + s->novlines = 0; + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (points_to_line(s,tp)) + return 1; /* Error */ + if (tp->flag & F_LINESTATS) /* Line stats valid */ + s->noslines++; + if (tp->flag & F_VALID) /* Valid for angle calcs */ + s->novlines++; + + /* Save orininal raster (non partial perspective corrected) values */ + if (tp->flag & F_VALID) { + tp->pmx = tp->mx; + tp->pmy = tp->my; + tp->px1 = tp->x1; + tp->py1 = tp->y1; + tp->px2 = tp->x2; + tp->py2 = tp->y2; + } + END_FOR_ALL_ITEMS(tp); + return 0; +} + +static int show_line(scanrd_ *s, int x1, int y1, int x2, int y2, unsigned long c); + +/* Show the edge detected lines */ +static int +show_lines( +scanrd_ *s +) { + points *tp; + int outw = s->width; + int outh = s->height; + /* For SI_SHOW_ROT */ + double cirot,sirot; /* cos and sin of -irot */ + cirot = cos(-s->irot); + sirot = sin(-s->irot); + + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if ((s->flags & SI_SHOW_ALL_LINES) || (tp->flag & F_VALID)) + { + unsigned long col = 0xffffff; /* default color is white */ + double x1 = tp->px1, y1 = tp->py1, x2 = tp->px2, y2 = tp->py2; + /* For SI_SHOW_ROT */ + + /* Show partial perspective corrected lines */ + if (s->flags & (SI_SHOW_ROT | SI_SHOW_PERS)) { + invppersp(s, &x1, &y1, x1, y1, s->ppc); + invppersp(s, &x2, &y2, x2, y2, s->ppc); + col = 0xffff00; /* cyan */ + } + + /* Show rotation correction of lines + color coding yellow and red */ + if (s->flags & SI_SHOW_ROT) { + double tx1, ty1, tx2, ty2; + double a = tp->a - s->irot; + + tx1 = x1; + ty1 = y1; + tx2 = x2; + ty2 = y2; + + /* Rotate about center of raster */ + x1 = (tx1-outw/2.0) * cirot + (ty1-outh/2.0) * sirot; + y1 = -(tx1-outw/2.0) * sirot + (ty1-outh/2.0) * cirot; + x2 = (tx2-outw/2.0) * cirot + (ty2-outh/2.0) * sirot; + y2 = -(tx2-outw/2.0) * sirot + (ty2-outh/2.0) * cirot; + + x1 += outw/2.0; /* Rotate about center of raster */ + y1 += outh/2.0; + x2 += outw/2.0; + y2 += outh/2.0; + if ((a >= -0.08 && a <= 0.08) || (a >= (M_PI-0.08) && a <= (M_PI+0.08)) + || (a >= (M_PI_2-0.08) && a <= (M_PI_2+0.08))) + col = 0x00ffff; /* yellow */ + else + col = 0x0000ff; /* Red */ + } + /* Show just lines used for fit improvement in blue */ + if (s->flags & SI_SHOW_IMPL) { + if (tp->flag & F_IMPROVE) + col = 0xff4040; /* blue */ + } + show_line(s,(int)(x1+0.5),(int)(y1+0.5),(int)(x2+0.5),(int)(y2+0.5),col); + } + END_FOR_ALL_ITEMS(tp); + return 0; +} + + +/********************************************************************************/ + +/* Definition of the optimization function handed to powell() */ +static double +pfunc(void *ss, double p[]) { + scanrd_ *s = (scanrd_ *)ss; + points *tp; + double aa; /* Average angle */ + double va, rva; /* Variance */ + double wt; /* Total weighting = sum of line lengths */ + double pw; + double dw; /* Discrimination width */ + +//printf("~1 %f %f %f %f %f %f\n", p[0],p[1],p[2],p[3],p[4],p[5]); + + /* Correct the perspective of all the edge lines using the parameters */ + /* and compute the mean angle */ + aa = 0.0; /* Average constrained angle */ + wt = 0.0; /* Total weighting = sum of line lengths */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_LONGENOUGH) { + double a, ca; + invppersp(s, &tp->x1, &tp->y1, tp->px1, tp->py1, p); + invppersp(s, &tp->x2, &tp->y2, tp->px2, tp->py2, p); + + /* Compute the angle */ + a = atan2(tp->x2 - tp->x1,tp->y2 - tp->y1); + + /* Make angle +ve */ + while (a < 0.0) + a += M_PI; + + /* Compute the Constrained to 90 degrees angle */ + /* We use the adivval to figure out where to split angles */ + /* Split at 0 if adivval == 0.0, split at 45 if adivval == 1.0 */ + if (a >= (M_PI * (1.0 - s->adivval/4.0))) + ca = a - M_PI; + else if (a >= (M_PI * (0.5 - s->adivval/4.0))) + ca = a - M_PI_2; + else + ca = a; + + tp->a = a; + tp->ca = ca; + + aa += tp->len * ca; + wt += tp->len; + } + END_FOR_ALL_ITEMS(tp); + aa /= wt; + + /* Calculate the angle variance */ + va = 0.0; + tp = s->gdone; + wt = 0.0; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_LONGENOUGH) { + double tt; + tt = tp->ca - aa; + va += tp->len * tt * tt; + wt += tp->len; + } + END_FOR_ALL_ITEMS(tp); + va = va/wt; + + /* Calculate the a robust angle variance */ + rva = 0.0; + wt = 0.0; + dw = sqrt(va) * 3.1; /* Allow += 0.5 of a standard deviation */ + if (dw < 0.0001) /* A perfect chart may have dw of zero */ + dw = 0.0001; + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_LONGENOUGH && fabs(tp->ca - aa) <= dw) { + double tt; + tt = tp->ca - aa; + rva += tp->len * tt * tt; + wt += tp->len; + } + END_FOR_ALL_ITEMS(tp); + if (wt > 0.0) { + rva = rva/wt; + va = rva; + } + + /* Add some regularization to stop it going crazy */ + pw = 0.0; + pw += 0.01 * (fabs(p[0]) + fabs(p[1])); + pw += 0.0001 * (fabs(p[2]/s->width - 0.5) + fabs(p[3]/s->height - 0.5)); + va += pw; + + return va; +} + +/* Calculate the partial perspective correction factors */ +/* Return non-zero if failed */ +static int +calc_perspective( +scanrd_ *s +) { + points *tp; + int nl; /* Number of lines used */ + double ml; /* Minimum length */ + double pc[4]; /* Perspective factors */ + double ss[4]; /* Initial search distance */ + double rv; /* Return value */ + int rc = 0; /* Return code */ + + if (s->novlines < MIN_NO_LINES) { + s->errv = SI_FIND_PERSPECTIVE_FAILED; + sprintf(s->errm,"Not enough valid lines to compute perspective"); + return 1; + } + + /* Find the longest line */ + ml = 0.0; + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID) { + if (tp->len > ml) + ml = tp->len; + } + END_FOR_ALL_ITEMS(tp); + + /* Make minimum line length to be included in angle */ + /* calculation 1% of longest line */ + ml *= 0.01; + + /* Mark lines long enough to participate in angle calculation */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID && tp->len >= ml) + tp->flag |= F_LONGENOUGH; + END_FOR_ALL_ITEMS(tp); + + /* Locate the perspective correction factors that minimze the */ + /* variance of the mean angle. */ + + pc[0] = 0.0; + pc[1] = 0.0; + pc[2] = 0.5 * s->width; + pc[3] = 0.5 * s->height; + + ss[0] = 0.0001; + ss[1] = 0.0001; + ss[2] = 1.0001; + ss[3] = 1.0001; + rc = powell(&rv, 4, pc,ss,1e-8,2000,pfunc,s, NULL, NULL); + + if (rc == 0) { + points *tp; + + DBG((dbgo,"Perspective correction factors = %f %f %f %f\n", + pc[0],pc[1],pc[2],pc[3])); + + s->ppc[0] = pc[0]; + s->ppc[1] = pc[1]; + s->ppc[2] = pc[2]; + s->ppc[3] = pc[3]; + + /* Implement the perspective correction */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_LONGENOUGH) { + double a, ca; + invppersp(s, &tp->x1, &tp->y1, tp->px1, tp->py1, s->ppc); + invppersp(s, &tp->x2, &tp->y2, tp->px2, tp->py2, s->ppc); + tp->mx = 0.5 * (tp->x2 + tp->x1); + tp->my = 0.5 * (tp->y2 + tp->y1); + tp->len = sqrt((tp->x2 - tp->x1) * (tp->x2 - tp->x1) + + (tp->y2 - tp->y1) * (tp->y2 - tp->y1)); + + /* Compute the angle */ + a = atan2(tp->x2 - tp->x1,tp->y2 - tp->y1); + + /* Make angle +ve */ + while (a < 0.0) + a += M_PI; + + /* Compute the Constrained to 90 degrees angle */ + /* We use the adivval to figure out where to split angles */ + /* Split at 0 if adivval == 0.0, split at 45 if adivval == 1.0 */ + if (a >= (M_PI * (1.0 - s->adivval/4.0))) + ca = a - M_PI; + else if (a >= (M_PI * (0.5 - s->adivval/4.0))) + ca = a - M_PI_2; + else + ca = a; + + tp->a = a; + tp->ca = ca; + } + END_FOR_ALL_ITEMS(tp); + } + + return 0; +} + +/********************************************************************************/ +/* Calculate the image rotation */ +/* Return non-zero if failed */ +static int +calc_rotation( +scanrd_ *s +) { + points *tp; + int nl; /* Number of lines used */ + double ml; /* Minimum length */ + double aa; /* Average angle */ + double sd,dw; /* Standard deviation, deviation window */ + double wt; /* Total weighting = sum of line lengths */ + + if (s->novlines < MIN_NO_LINES) { + s->errv = SI_FIND_ROTATION_FAILED; + sprintf(s->errm,"Not enough valid lines to compute rotation angle"); + return 1; + } + + /* Find the longest line */ + tp = s->gdone; + ml = 0.0; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID) { + if (tp->len > ml) + ml = tp->len; + } + END_FOR_ALL_ITEMS(tp); + + /* Make minimum line length to be included in angle */ + /* calculation 1% of longest line */ + ml *= 0.01; + + /* Calculate the mean angle */ + aa = 0.0; + wt = 0.0; /* Total weighting = sum of line lengths */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID && tp->len >= ml) { + aa += tp->len * tp->ca; + wt += tp->len; + } + END_FOR_ALL_ITEMS(tp); + aa /= wt; + + if (s->verb >= 2) + DBG((dbgo,"Mean angle = %f\n",DEG(aa))); + + /* Calculate the angle standard deviation */ + tp = s->gdone; + sd = 0.0; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID && tp->len >= ml) { + double tt; + tt = tp->ca - aa; + sd += tp->len * tt * tt; + } + END_FOR_ALL_ITEMS(tp); + + sd = sqrt(sd/wt); + + if (s->verb >= 2) + DBG((dbgo,"Standard deviation = %f\n",DEG(sd))); + + /* Now re-compute the angle while rejecting any that fall outside one standard deviation */ + s->irot = 0.0; + wt = 0.0; /* Total weighting = sum of line lengths */ + nl = 0; + dw = sd * SD_WINDOW; /* Allow += 0.5 of a standard deviation */ + if (dw < 0.01) /* A perfect chart may have dw of zero */ + dw = 0.01; + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID && tp->len >= ml && fabs(tp->ca - aa) <= dw) { + s->irot += tp->len * tp->ca; + wt += tp->len; + nl++; + } + END_FOR_ALL_ITEMS(tp); + if (nl < (MIN_NO_LINES/2)) { + s->errv = SI_FIND_ROTATION_FAILED; + sprintf(s->errm,"%d consistent lines is not enough to compute rotation angle",nl); + return 1; + } + s->irot /= wt; + + if (s->verb >= 2) + DBG((dbgo,"Robust mean angle = %f from %d lines\n",DEG(s->irot),nl)); + + return 0; +} + +/********************************************************************************/ +/* Coalesce close entries of an edge list */ +/* return non-zero on error */ +static int +coalesce_elist( +scanrd_ *s, +elist *el, +int close /* Closeness factor, smaller = coarser */ +) { + double r; /* Margin for coalescence */ + int i,k; + + if (el->c < 2) /* Need at least 2 entries */ + return 0; + + r = (el->a[el->c-1].pos - el->a[0].pos)/(double)close; + for (k = 0, i = 1; i < el->c; i++) { + if ((el->a[i].pos - el->a[k].pos) <= r) { + /* Merge the two */ + double lk = el->a[k].len; + double li = el->a[i].len; + el->a[k].pos = (el->a[k].pos * lk + el->a[i].pos * li)/(lk + li); + el->a[k].len = lk + li; + if (el->a[k].p1 > el->a[i].p1) /* Track overall start/end points */ + el->a[k].p1 = el->a[i].p1; + if (el->a[k].p2 < el->a[i].p2) + el->a[k].p2 = el->a[i].p2; + continue; + } + k++; /* Inc destination pointer */ + if (k != i) + el->a[k] = el->a[i]; /* shuffle data down */ + } + k++; /* one past last out entry */ + el->c = k; + return 0; +} + +static int invert_elist(scanrd_ *s, elist *dl, elist *sl); +static void debug_elist(scanrd_ *s, elist *el); + +/* Make up the x and y edge lists */ +/* Return non-zero if failed */ +static int +calc_elists( +scanrd_ *s, +int ref /* 1 if generating reference lists */ +) { + int outw = s->width; + int outh = s->height; + points *tp; + int i,j; + double cirot,sirot; /* cos and sin of -irot */ + elist xl, yl; /* Temporary X and Y edge lists array */ + elist tl; /* temporary crossing list */ + + /* Allocate structures for edge lists */ + if ((xl.a = (epoint *) malloc(sizeof(epoint) * s->novlines)) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"scanrd: calc_elist: malloc failed - novlines = %d",s->novlines); + return 1; + } + xl.c = 0; + if ((yl.a = (epoint *) malloc(sizeof(epoint) * s->novlines)) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"scanrd: calc_elist: malloc failed - novlines = %d",s->novlines); + return 1; + } + yl.c = 0; + + /* Put valid lines into one of the two edge list arrays */ + cirot = cos(-s->irot); + sirot = sin(-s->irot); + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID) { + /* Rotate the point about 0,0 by angle -irot */ + double x,y,a; + double mx = tp->mx, my = tp->my; + + if (ref) { /* Rotate about center of raster for reference generation */ + mx -= outw/2.0; /* Rotate about center of raster */ + my -= outh/2.0; + x = mx * cirot + my * sirot + outw/2.0; + y = -mx * sirot + my * cirot + outh/2.0; + } else { /* Rotate about 0,0 for matching */ + x = mx * cirot + my * sirot; + y = -mx * sirot + my * cirot; + } + a = tp->a - s->irot; + if ((a >= -0.08 && a <= 0.08) || (a >= (M_PI-0.08) && a <= (M_PI+0.08))) { + xl.a[xl.c].pos = x; + xl.a[xl.c].len = tp->len; + xl.a[xl.c].p1 = y - tp->len/2.0; + xl.a[xl.c].p2 = y + tp->len/2.0; + xl.c++; + } else if (a >= (M_PI_2-0.08) && a <= (M_PI_2+0.08)) { + yl.a[yl.c].pos = y; + yl.a[yl.c].len = tp->len; + yl.a[yl.c].p1 = x - tp->len/2.0; + yl.a[yl.c].p2 = x + tp->len/2.0; + yl.c++; + } + } + END_FOR_ALL_ITEMS(tp); + + /* ~~~~ need to check that lists have a reasonable number of entries ~~~~~ */ + + /* now sort the lists */ +#define HEAP_COMPARE(A,B) (A.pos < B.pos) + HEAPSORT(epoint,xl.a,xl.c); + HEAPSORT(epoint,yl.a,yl.c); +#undef HEAP_COMPARE + + /* Copy the temporary lists to the real lists */ + if ((s->xelist.a = (epoint *) malloc(sizeof(epoint) * xl.c)) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"scanrd: calc_elist: malloc failed, xl.c = %d",xl.c); + return 1; + } + s->xelist.c = xl.c; + for (i=0; i < xl.c; i++) + s->xelist.a[i] = xl.a[i]; + if ((s->yelist.a = (epoint *) malloc(sizeof(epoint) * yl.c)) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"scanrd: calc_elist: malloc failed, yl.c = %d",yl.c); + return 1; + } + s->yelist.c = yl.c; + for (i=0; i < yl.c; i++) + s->yelist.a[i] = yl.a[i]; + + /* Coalese close entries of the final lists */ + if (coalesce_elist(s, &s->xelist,ELISTCDIST)) + return 1; + if (coalesce_elist(s, &s->yelist,ELISTCDIST)) + return 1; + + /* Calculate crossing count for lines in the X and y lists */ + if ((tl.a = (epoint *) malloc(sizeof(epoint) * (xl.c > yl.c ? xl.c : yl.c))) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"scanrd: calc_elist: malloc failed, xl.c = %d, yl.c = %d",xl.c,yl.c); + return 1; + } + /* X list */ + for (i = 0; i < s->xelist.c; i++) { + double ppos = s->xelist.a[i].pos; + double pp,np; /* Previous and next pos */ + if ((i-1) >= 0) + pp = (ppos + s->xelist.a[i-1].pos)/2.0; /* Half distance to next line */ + else + pp = -1e6; + if ((i+1) < s->xelist.c) + np = (ppos + s->xelist.a[i+1].pos)/2.0; /* Half distance to next line */ + else + np = 1e6; + + /* For all the lines in the Y list */ + for (tl.c = j = 0; j < yl.c; j++) { + double pos = yl.a[j].pos; + double p1 = yl.a[j].p1; + double p2 = yl.a[j].p2; + if (p1 <= pp) + p1 = pp; + if (p2 >= np) + p2 = np; + /* If crosses on this lines X within +-0.5 of line each side */ + if (p1 <= np && p2 >= pp) { + tl.a[tl.c].pos = pos; + tl.a[tl.c].len = p2 - p1; + tl.a[tl.c].p1 = p1; + tl.a[tl.c].p2 = p2; + tl.c++; + } + } + /* now coalesce the crossings */ + if (coalesce_elist(s,&tl,200)) + return 1; + /* Put count in line we're working on */ + s->xelist.a[i].ccount = (double)tl.c; + pp = ppos; + } + + /* Y list */ + for (i = 0; i < s->yelist.c; i++) { + double ppos = s->yelist.a[i].pos; + double pp,np; /* Previous and next pos */ + if ((i-1) >= 0) + pp = (ppos + s->yelist.a[i-1].pos)/2.0; /* Half distance to next line */ + else + pp = -1e6; + if ((i+1) < s->xelist.c) + np = (ppos + s->yelist.a[i+1].pos)/2.0; /* Half distance to next line */ + else + np = 1e6; + + for (tl.c = j = 0; j < xl.c; j++) { + double pos = xl.a[j].pos; + double p1 = xl.a[j].p1; + double p2 = xl.a[j].p2; + if (p1 <= pp) + p1 = pp; + if (p2 >= np) + p2 = np; + /* If crosses on this lines Y within +-0.5 of line each side */ + if (p1 <= np && p2 >= pp) { + tl.a[tl.c].pos = pos; + tl.a[tl.c].len = p2 - p1; + tl.a[tl.c].p1 = p1; + tl.a[tl.c].p2 = p2; + tl.c++; + } + } + /* now coalesce the crossings */ + if (coalesce_elist(s,&tl,200)) + return 1; + /* Put count in line we're working on */ + s->yelist.a[i].ccount = (double)tl.c; + pp = ppos; + } + + /* Normalize the length and ccount */ + { + double tlen; /* Total length maximum */ + double tcmax; /* Total count maximum */ + for (tlen = tcmax = 0.0, i=0; i < s->xelist.c; i++) { + if (tlen < s->xelist.a[i].len) + tlen = s->xelist.a[i].len; + if (tcmax < s->xelist.a[i].ccount) + tcmax = s->xelist.a[i].ccount; + } + for (i=0; i < s->xelist.c; i++) { + s->xelist.a[i].len /= tlen; + s->xelist.a[i].ccount /= tcmax; + } + for (tlen = tcmax = 0.0, i=0; i < s->yelist.c; i++) { + if (tlen < s->yelist.a[i].len) + tlen = s->yelist.a[i].len; + if (tcmax < s->yelist.a[i].ccount) + tcmax = s->yelist.a[i].ccount; + } + for (i=0; i < s->yelist.c; i++) { + s->yelist.a[i].len /= tlen; + s->yelist.a[i].ccount /= tcmax; + } + } + + /* Create the inverted lists for any rotation matching */ + if (invert_elist(s, &s->ixelist, &s->xelist)) + return 1; + if (invert_elist(s, &s->iyelist, &s->yelist)) + return 1; + + if (s->verb >= 3) { + DBG((dbgo,"\nxelist:\n")); + debug_elist(s,&s->xelist); + DBG((dbgo,"\nixelist:\n")); + debug_elist(s,&s->ixelist); + DBG((dbgo,"\nyelist:\n")); + debug_elist(s,&s->yelist); + DBG((dbgo,"\niyelist:\n")); + debug_elist(s,&s->iyelist); + } + + /* Clean up */ + free(xl.a); + free(yl.a); + free(tl.a); + return 0; +} + +/********************************************************************************/ +/* Write the elists out to a file */ + +/* Increment a string counter */ +static void +strinc( +char *s +) { + int i,n,c; /* Length of string and carry flag */ + n = strlen(s); + for (c = 1, i = n-1; i >= 0 && c != 0; i--) { + char sval = ' '; + if (s[i] == '9') { + s[i] = '0'; + sval = '1'; + c = 1; + } else if (s[i] == 'z') { + s[i] = 'a'; + sval = 'a'; + c = 1; + } else if (s[i] == 'Z') { + s[i] = 'A'; + sval = 'A'; + c = 1; + } else { + s[i]++; + c = 0; + } + if (i == 0 && c != 0) { + /* Assume there is some more space */ + for (i = n; i >= 0; i--) + s[i+1] = s[i]; + s[0] = sval; + break; + } + } +} + +/* Write out the match reference information */ +/* Return non-zero on error */ +static int +write_elists( +scanrd_ *s +) { + char *fname = s->refname; /* Path of file to write to */ + FILE *elf; + int i; + + if ((elf=fopen(fname,"w"))==NULL) { + s->errv = SI_REF_WRITE_ERR; + sprintf(s->errm,"write_elists: error opening match reference file '%s'",fname); + return 1; + } + + fprintf(elf,"REF_ROTATION %f\n\n",DEG(s->irot)); + + fprintf(elf,"XLIST %d\n",s->xelist.c); + for (i = 0; i < s->xelist.c; i++) + fprintf(elf," %f %f %f\n",s->xelist.a[i].pos, s->xelist.a[i].len, s->xelist.a[i].ccount); + fprintf(elf,"\n"); + + fprintf(elf,"YLIST %d\n",s->yelist.c); + for (i = 0; i < s->yelist.c; i++) + fprintf(elf," %f %f %f\n",s->yelist.a[i].pos, s->yelist.a[i].len, s->yelist.a[i].ccount); + fprintf(elf,"\n"); + + if ((fclose(elf)) == EOF) { + s->errv = SI_REF_WRITE_ERR; + error("write_elists: Unable to close match reference file '%s'\n",fname); + return 1; + } + return 0; +} + +/* Read in an elist reference file */ +/* return non-zero on error */ +/* (~~~ the line counting is rather broken ~~~) */ +static int +read_relists( +scanrd_ *s +) { + char *fname = s->refname; /* Path of file to read from */ + FILE *elf; + int i,l = 1; + int rv; + char *em; /* Read error message */ + + if ((elf=fopen(fname,"r"))==NULL) { + s->errv = SI_REF_READ_ERR; + sprintf(s->errm,"read_elists: error opening match reference file '%s'",fname); + return 1; + } + + s->fid[0] = s->fid[1] = 0.0; + s->fid[2] = s->fid[3] = 0.0; + s->fid[4] = s->fid[5] = 0.0; + s->fid[6] = s->fid[7] = 0.0; + + /* BOXES */ + for(;;) { + if((rv = fscanf(elf,"BOXES %d",&s->nsbox)) == 1) { + l++; + break; + } + if (rv == EOF) { + em = "Didn't find BOXES before end of file"; + goto read_error; + } + if (rv == 0) { + while ((rv = getc(elf)) != '\n' && rv != EOF); + l++; + } + } + + /* Allocate structures for boxes */ + if ((s->sboxes = (sbox *) calloc(s->nsbox, sizeof(sbox))) == NULL) { + s->errv = SI_MALLOC_REFREAD; + sprintf(s->errm,"read_elist, malloc failed"); + return 1; + } + for (i = 0; i < s->nsbox;) { + char xfix1[20], xfix2[20], yfix1[20],yfix2[20]; + char xfirst[20]; + double ox,oy,w,h,xi,yi; + char xf[20]; + double x; + + if(fscanf(elf," %19s %19s %19s %19s %19s %lf %lf %lf %lf %lf %lf",xfirst ,xfix1, xfix2, yfix1, yfix2, &w, &h, &ox, &oy, &xi, &yi) != 11) { + em = "Read of BOX failed"; + goto read_error; + } + l++; + + /* If Fiducial. Typically top left, top right, botton right, bottom left. */ + if (xfirst[0] == 'F') { + s->fid[0] = atof(yfix1); + s->fid[1] = atof(yfix2); + s->fid[2] = w; + s->fid[3] = h; + s->fid[4] = ox; + s->fid[5] = oy; + s->fid[6] = xi; + s->fid[7] = yi; + s->fidsize = fabs(s->fid[2] - s->fid[0]) + fabs(s->fid[5] - s->fid[3]); + s->fidsize /= 80.0; + s->havefids = 1; + +//printf("~1 fiducials %f %f, %f %f %f, %f\n",w, h, ox,oy, xi, yi); + continue; + } + for(;;) { /* Do Y increment */ + x = ox; + strcpy(xf,xfix1); + for(;;) { /* Do X increment */ + if (i >= s->nsbox) { + em = "More BOXes that declared"; + goto read_error; + } + /* '_' is used as a null string marker for single character single cells */ + if (xf[0] == '_') + sprintf(s->sboxes[i].name,"%s",yfix1); + else if (yfix1[0] == '_') + sprintf(s->sboxes[i].name,"%s",xf); + else { /* Y indicates Y name comes first */ + if (xfirst[0] == 'Y') + sprintf(s->sboxes[i].name,"%s%s",yfix1,xf); + else /* X or D */ + sprintf(s->sboxes[i].name,"%s%s",xf,yfix1); + } + if (xfirst[0] == 'D') + s->sboxes[i].diag = 1; /* Diagnostic box - don't print name or read pixels */ + else + s->sboxes[i].diag = 0; + s->sboxes[i].x1 = x; + s->sboxes[i].y1 = oy; + s->sboxes[i].x2 = x + w; + s->sboxes[i].y2 = oy + h; + + /* Misc. init. of new sbox */ + s->sboxes[i].xpt[0] = -1.0; /* No default expected value */ + + i++; + x += xi; + if (strcmp(xf,xfix2) == 0) + break; + strinc(xf); + } + if (strcmp(yfix1,yfix2) == 0) + break; + oy += yi; + strinc(yfix1); + } + } + + /* BOX_SHRINK */ + for(;;) { + if((rv = fscanf(elf,"BOX_SHRINK %lf ",&s->rbox_shrink)) == 1) { + l++; + break; + } + if (rv == EOF) { + em = "Didn't find BOX_SHRINK before end of file"; + goto read_error; + } + if (rv == 0) { + while ((rv = getc(elf)) != '\n' && rv != EOF); + l++; + } + } + + /* XLIST */ + for(;;) { + if((rv = fscanf(elf,"XLIST %d ",&s->rxelist.c)) == 1) { + l++; + break; + } + if (rv == EOF) { + em = "Didn't find XLIST before end of file"; + goto read_error; + } + if (rv == 0) { + while ((rv = getc(elf)) != '\n' && rv != EOF); + l++; + } + } + /* Allocate structures for ref edge lists */ + if ((s->rxelist.a = (epoint *) malloc(sizeof(epoint) * s->rxelist.c)) == NULL) { + s->errv = SI_MALLOC_REFREAD; + sprintf(s->errm,"read_elist, malloc failed"); + return 1; + } + for (i = 0; i < s->rxelist.c; i++) { + if (fscanf(elf," %lf %lf %lf ", + &s->rxelist.a[i].pos, &s->rxelist.a[i].len, &s->rxelist.a[i].ccount) != 3) { + em = "Failed to read an XLIST line"; + goto read_error; + } + l++; + } + + /* YLIST */ + for(;;) { + if ((rv = fscanf(elf,"YLIST %d ",&s->ryelist.c)) == 1) { + l++; + break; + } + if (rv == EOF) { + em = "Didn't find YLIST before end of file"; + goto read_error; + } + if (rv == 0) { + while ((rv = getc(elf)) != '\n' && rv != EOF); + l++; + } + } + if ((s->ryelist.a = (epoint *) malloc(sizeof(epoint) * s->ryelist.c)) == NULL) { + s->errv = SI_MALLOC_REFREAD; + sprintf(s->errm,"read_elist, malloc failed"); + return 1; + } + for (i = 0; i < s->ryelist.c; i++) { + if (fscanf(elf," %lf %lf %lf ", + &s->ryelist.a[i].pos, &s->ryelist.a[i].len, &s->ryelist.a[i].ccount) != 3) + { + em = "Failed to read an YLIST line"; + goto read_error; + } + l++; + } + + /* EXPECTED */ + { + int j; + int isxyz = 0; + int nxpt = 0; + char csps[20]; + + for(;;) { + if ((rv = fscanf(elf,"EXPECTED %19s %d ",csps, &nxpt)) == 2) { + l++; + if (strcmp(csps, "XYZ") == 0) { + isxyz = 1; + break; + } else if (strcmp(csps, "LAB") == 0) { + isxyz = 0; + break; + } else { + em = "Unknown EXPECTED colorespace"; + goto read_error; + } + } + if (rv == EOF) { + break; + } + if (rv == 0) { + while ((rv = getc(elf)) != '\n' && rv != EOF); + l++; + } + } + for (j = 0; j < nxpt; j++) { + char name[20]; + double val[3]; + if (fscanf(elf," %19s %lf %lf %lf ", + name, &val[0], &val[1], &val[2]) != 4) + { + em = "Failed to read an EXPECTED line"; + goto read_error; + } + l++; + /* Now locate the matching box */ + for (i = 0; i < s->nsbox; i++) { + if (strcmp(s->sboxes[i].name, name) == 0) { /* Found it */ + if (isxyz) { + XYZ2Lab(s->sboxes[i].xpt, val); + } else { + s->sboxes[i].xpt[0] = val[0]; + s->sboxes[i].xpt[1] = val[1]; + s->sboxes[i].xpt[2] = val[2]; + } + s->xpt = 1; + break; + } + } + if (i >= s->nsbox) { + em = "Failed to locate matching sample box in EXPECTED list"; + goto read_error; + } + } + } + + if ((fclose(elf)) == EOF) { + s->errv = SI_REF_WRITE_ERR; + error("read_elists: Unable to close match reference file '%s'\n",fname); + return 1; + } + + /* Generate length normalization factor */ + { + double tlen; /* Total of normalized length */ + for (tlen = 0.0, i=0; i < s->rxelist.c; i++) + tlen += s->rxelist.a[i].len; + s->rxelist.lennorm = tlen; + for (tlen = 0.0, i=0; i < s->ryelist.c; i++) + tlen += s->ryelist.a[i].len; + s->ryelist.lennorm = tlen; + } + + if (s->verb >= 3) { + DBG((dbgo,"\nrxelist:\n")); + debug_elist(s, &s->rxelist); + DBG((dbgo,"\nryelist:\n")); + debug_elist(s, &s->ryelist); + } + + return 0; + +read_error:; + s->errv = SI_REF_FORMAT_ERR; + sprintf(s->errm,"read_relist failed at line %d in file %s: %s\n",l,fname,em); + return 1; +} + +/********************************************************************************/ +/* Create an inverted direction elist */ +/* return non-zero on error */ +static int +invert_elist( +scanrd_ *s, +elist *dl, /* Destination list */ +elist *sl /* Source list */ +) { + int i,j, rc = sl->c; + + *dl = *sl; /* Copy all the structure elements */ + + /* Allocate space in the destination list */ + if ((dl->a = (epoint *) malloc(sizeof(epoint) * rc)) == NULL) { + s->errv = SI_MALLOC_ELIST; + sprintf(s->errm,"invert_elist: malloc failed"); + return 1; + } + + /* Copy the array data and reverse its order */ + for (i = 0, j = rc-1; i < rc; i++,j--) { + dl->a[j] = sl->a[i]; /* Copy array element */ + dl->a[j].pos = -dl->a[j].pos; /* Invert position */ + } + return 0; +} + +/* Print out elist */ +static void +debug_elist( +scanrd_ *s, +elist *el +) { + int i, rc = el->c; + + DBG((dbgo,"Elist has %d entries allocated at 0x%p\n",el->c,el->a)); + DBG((dbgo,"lennorm = %f\n",el->lennorm)); + for (i = 0; i < rc; i++) + DBG((dbgo," [%d] = %f %f %f\n",i,el->a[i].pos,el->a[i].len,el->a[i].ccount)); +} + +/* Free the array data in an elist */ +static void +free_elist_array(elist *el) { + free(el->a); + el->c = 0; +} + +/********************************************************************************/ +/* !!!!!!! */ +/* NEED TO RESOLVE WHY current code is better in some cases, but */ +/* not in others. */ + +#ifndef NEVER /* Current code */ + +/* Compute a correlation between two elists */ +static double +elist_correl( +scanrd_ *s, +elist *r, /* Reference list */ +elist *t, /* Target list */ +double off, double scale, /* Offset and scale of target to ref */ +int verb /* Verbose mode */ +) { + int i, j, rc = r->c; + double cc = 0.0; /* Correlation */ + double marg = (r->a[rc-1].pos - r->a[0].pos)/150.0; /* determines sharpness of pos. match */ + double marg2 = marg * 3.0; /* Don't contribute anything outside this distance */ + + for (i = j = 0; i < t->c; i++) { + int ri; /* Reference index */ + double dd,d1,d2; /* Distance to nearest reference */ + double pos = (t->a[i].pos + off) * scale; + double len = t->a[i].len; + double cnt = t->a[i].ccount; + while (pos > r->a[j+1].pos && j < (r->c-2)) j++; + d1 = fabs(pos - r->a[j].pos); + d2 = fabs(r->a[j+1].pos - pos); + if (d1 < d2) { + dd = d1; + ri = j; + } else { + dd = d2; + ri = j+1; + } + if (dd <= marg2) { /* If close enough to reference */ + double ccf, rcnt = r->a[ri].ccount; + double llf, rlen = r->a[ri].len; + double df = marg/(marg + dd); + df *= df; + ccf = 1.0 - (rcnt > cnt ? rcnt-cnt : cnt-rcnt); + llf = 1.0 - (rlen > len ? rlen-len : len-rlen); + /* The weighting gives slightly more emphasis on matching long lines */ + cc += (1.0 + rlen) * (df * llf * ccf); + if (verb) { + DBG((dbgo,"---- t[%d] %f %f %f this cc = %f, running total cc = %f\n r[%d] %f %f %f, df = %f, llf = %f, ccf = %f\n", + i,pos,len,cnt,df * llf * ccf,cc,j,r->a[ri].pos,r->a[ri].len,rcnt,df, llf, ccf)); + } + } + } + return cc/(r->lennorm + (double)r->c); /* Normalize */ +} + +#else /* New test code */ + +/* Compute a correlation between two elists */ +static double +elist_correl( +scanrd_ *s, +elist *r, /* Reference list */ +elist *t, /* Target list */ +double off, double scale, /* Offset and scale of target to ref */ +int verb /* Verbose mode */ +) { + int i, rc = r->c; + double cc = 0.0; /* Correlation */ + double marg = (r->a[rc-1].pos - r->a[0].pos)/100.0; /* determines sharpness of pos. match */ + double marg2 = marg * marg; /* marg squared */ + +//printf("~1 doing elist_correl\n"); + /* For each reference edge */ + for (i = 0; i < rc; i++) { + int j[3], jj, bj, tc = t->c; + double dd, pos, bdd; + + /* Find the closest target edge using binary search. */ + for(bdd = 1e6, j[2] = tc-1, j[0] = 0; j[2] > (j[0]+1);) { + double dist; + j[1] = (j[2] + j[0])/2; /* Trial point */ + dist = r->a[i].pos - (t->a[j[1]].pos + off) * scale; + +//printf("~1 j1 = %d, j1 = %d, j0 = %d, dist = %f\n",j[2], j[1], j[0], dist); + if (dist > 0) { + j[0] = j[1]; + } else { + j[2] = j[1]; + } + } + + /* Locate best out of 3 remaining points */ + for (jj = 0; jj < 3; jj++) { + double dist; + pos = (t->a[j[jj]].pos + off) * scale; + dist = r->a[i].pos - pos; + dd = dist * dist; /* Distance squared */ + if (dd < bdd) { /* New closest */ + bdd = dd; + bj = j[jj]; + } + } + +//printf("~1 best j = %d, bdd = %f, marg2 = %f\n",bj,bdd,marg2); + /* Compute correlation */ + if (bdd < marg2) { /* Within our margine */ + double df = (marg2 - bdd)/marg2; /* Distance factor */ + double llf, rlen = r->a[i].len, len = t->a[i].len; + double ccf, rcnt = r->a[i].ccount, cnt = t->a[i].ccount; + double tcc; + llf = 1.0 - (rlen > len ? rlen-len : len-rlen); + ccf = 1.0 - (rcnt > cnt ? rcnt-cnt : cnt-rcnt); + + /* The weighting gives slightly more emphasis on matching long lines */ + /* Not using crossing count */ + tcc = (1.0 + rlen) * (df * llf); + cc += tcc; + if (verb) { + DBG((dbgo,"---- targ[%d] %f %f %f this cc = %f, running total cc = %f\n", + bj,pos,t->a[bj].len,t->a[bj].ccount, tcc,cc)); + DBG((dbgo," ref[%d] %f %f %f, df = %f, llf = %f, ccf = %f\n", + i,r->a[i].pos,r->a[i].len,r->a[i].ccount, df, llf, ccf)); + } + } + + } + return cc/(r->lennorm + (double)r->c); /* Normalize */ +} + +#endif /* NEVER */ + +/* Structure to hold data for optimization function */ +struct _edatas { + scanrd_ *s; /* scanrd object */ + elist *r; /* Reference list */ + elist *t; /* Target list */ + int verb; /* Verbose mode */ + }; typedef struct _edatas edatas; + +/* Definition of the optimization function handed to powell() */ +static double +efunc(void *edata, double p[]) { + edatas *e = (edatas *)edata; + double rv = 2.0 - elist_correl(e->s,e->r,e->t,p[0],p[1],e->verb); + return rv; +} + +/* return non-zero on error */ +static int +best_match( +scanrd_ *s, +elist *r, /* Reference list */ +elist *t, /* Target list */ +ematch *rv /* Return values */ +) { + int r0,r1,rw,t0,t1; + double rwidth; + double cc; + double bcc = 0.0, boff = 0.0, bscale = 0.0; /* best values */ + + /* The target has been rotated, and we go through all reasonable */ + /* translations and scales to see if we can match it to the */ + /* reference. */ + r0 = 0; + r1 = r->c-1; + rw = r->c/2; /* Minimum number of target line to match all of reference */ + if (t->c/2 < rw) + rw = t->c/2; + rwidth = r->a[r1].pos - r->a[r0].pos; + + for (t0 = 0; t0 < t->c-1; t0++) { + double off; + for (t1 = t->c-1; t1 > (t0+rw); t1--) { + double scale; + + scale = rwidth/(t->a[t1].pos - t->a[t0].pos); + if (scale < 0.001 || scale > 100.0) { + break; /* Don't bother with silly scale factors */ + } + + /* Have to compenate the offset for the scale since it is scaled from 0 */ + off = r->a[r0].pos/scale - t->a[t0].pos; + cc = elist_correl(s,r,t,off,scale,0); + + if (s->verb >= 7) { + DBG((dbgo,"Matching target [%d]-[%d] to ref [%d]-[%d] = %f-%f to %f-%f\n", + t0,t1,r0,r1,t->a[t0].pos,t->a[t1].pos,r->a[r0].pos,r->a[r1].pos)); + DBG((dbgo,"Initial off %f, scale %f, cc = %f\n",off,scale,cc)); + } + if (cc > 0.20) { /* Looks promising, try optimizing solution */ + double cp[2]; /* Start point/improved point */ + double rv; /* Return value */ + int rc; /* Return code */ + edatas dd; /* Data structure */ + double ss[2] = { 0.1, 0.1}; /* Initial search distance */ + + dd.s = s; /* scanrd object */ + dd.r = r; /* Reference list */ + dd.t = t; /* Target list */ + dd.verb = 0; /* Verbose mode */ + + /* Set search start point */ + cp[0] = off; + cp[1] = scale; + /* Set search distance */ + ss[0] = (0.01 * rwidth/ELISTCDIST)/scale; /* Search distance */ + ss[1] = scale * 0.01 * rwidth/ELISTCDIST; + + /* Find minimum */ + rc = powell(&rv, 2,cp,ss,0.0001,400,efunc,&dd, NULL, NULL); + + if (rc == 0 /* Powell converged */ + && cp[1] > 0.001 && cp[1] < 100.0) { /* and not ridiculous */ + cc = 2.0 - rv; + off = cp[0]; + scale = cp[1]; + } + /* Else use unoptimsed values */ + + if (s->verb >= 7) { + DBG((dbgo,"After optimizing, off %f, scale %f, cc = %f\n",off,scale,cc)); + } + } + + if (s->verb >= 7) { + if (cc > 0.25) { + DBG((dbgo,"Good correlation::\n")); + elist_correl(s,r,t,off,scale,1); + } + } + if (s->verb >= 7) + DBG((dbgo,"offset %f, scale %f cc %f\n", off,scale,cc)); + if (cc > 0.0 && cc > bcc) { /* Keep best */ + boff = off; + bscale = scale; + bcc = cc; + if (s->verb >= 7) + DBG((dbgo,"(New best)\n")); + } + } + } + if (s->verb >= 7) + DBG((dbgo,"Returning best offset %f, scale %f returns %f\n\n", boff,bscale,bcc)); + + /* return best values */ + rv->cc = bcc; + rv->off = boff; + rv->scale = bscale; + return 0; +} + +/* Find best offset and scale match between reference and target, */ +/* and then from this, compute condidate 90 degree rotations. */ +/* Return 0 if got at least one candidate rotation */ +/* Return 1 if no reasonable candidate rotation found */ +/* Return 2 if some other error */ +static int +do_match( +scanrd_ *s +) { + ematch xx, yy, xy, yx, xix, yiy, xiy, yix; /* All 8 matches needed to detect rotations */ + double r0, r90, r180, r270; /* Correlation for each extra rotation of target */ + + /* Check out all the matches */ + if (s->verb >= 2) DBG((dbgo,"Checking xx\n")); + if (best_match(s, &s->rxelist,&s->xelist,&xx)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking yy\n")); + if (best_match(s, &s->ryelist,&s->yelist,&yy)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking xy\n")); + if (best_match(s, &s->rxelist,&s->yelist,&xy)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking yx\n")); + if (best_match(s, &s->ryelist,&s->xelist,&yx)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking xix\n")); + if (best_match(s, &s->rxelist,&s->ixelist,&xix)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking yiy\n")); + if (best_match(s, &s->ryelist,&s->iyelist,&yiy)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking xiy\n")); + if (best_match(s, &s->rxelist,&s->iyelist,&xiy)) + return 2; + if (s->verb >= 2) DBG((dbgo,"Checking yix\n")); + if (best_match(s, &s->ryelist,&s->ixelist,&yix)) + return 2; + + if (s->verb >= 2) { + DBG((dbgo,"Axis matches for each possible orientation:\n")); + DBG((dbgo," 0: xx = %f, yy = %f, xx.sc = %f, yy.sc = %f\n", + xx.cc,yy.cc,xx.scale,yy.scale)); + DBG((dbgo," 90: xiy = %f, yx = %f, xiy.sc = %f, yx.sc = %f\n", + xiy.cc,yx.cc,xiy.scale,yx.scale)); + DBG((dbgo,"180: xix = %f, yiy = %f, xix.sc = %f, yiy.sc = %f\n", + xix.cc,yiy.cc,xix.scale,yiy.scale)); + DBG((dbgo,"270: xy = %f, yix = %f, xy.sc = %f, yix.sc = %f\n", + xy.cc,yix.cc,xy.scale,yix.scale)); + } + + /* Compute the combined values for the four orientations. */ + /* add penalty for different scale factors */ + r0 = sqrt(xx.cc * xx.cc + yy.cc * yy.cc) + * (xx.scale > yy.scale ? yy.scale/xx.scale : xx.scale/yy.scale); + r90 = sqrt(xiy.cc * xiy.cc + yx.cc * yx.cc) + * (xiy.scale > yx.scale ? yx.scale/xiy.scale : xiy.scale/yx.scale); + r180 = sqrt(xix.cc * xix.cc + yiy.cc * yiy.cc) + * (xix.scale > yiy.scale ? yiy.scale/xix.scale : xix.scale/yiy.scale); + r270 = sqrt(xy.cc * xy.cc + yix.cc * yix.cc) + * (xy.scale > yix.scale ? yix.scale/xy.scale : xy.scale/yix.scale); + + if (s->verb >= 2) + DBG((dbgo,"r0 = %f, r90 = %f, r180 = %f, r270 = %f\n",r0,r90,r180,r270)); + + s->norots = 0; + if (s->flags & SI_GENERAL_ROT) { /* If general rotation allowed */ + if (s->xpt == 0) { /* No expected color information to check rotations agaist */ + /* so choose the single best rotation by the edge matching */ + DBG((dbgo,"There is no expected color information, so best fit rotations will be used\n")); + if (r0 >= MATCHCC && r0 >= r90 && r0 >= r180 && r0 >= r270) { + s->rots[0].ixoff = -xx.off; + s->rots[0].ixscale = 1.0/xx.scale; + s->rots[0].iyoff = -yy.off; + s->rots[0].iyscale = 1.0/yy.scale; + s->rots[0].irot = s->irot; + s->rots[0].cc = r0; + s->norots = 1; + } else if (r90 >= MATCHCC && r90 >= r180 && r90 >= r270) { + s->rots[0].ixoff = -xiy.off; + s->rots[0].ixscale = 1.0/xiy.scale; + s->rots[0].iyoff = -yx.off; + s->rots[0].iyscale = 1.0/yx.scale; + s->rots[0].irot = s->irot + M_PI_2; + s->rots[0].cc = r90; + s->norots = 1; + } else if (r180 >= MATCHCC && r180 >= r270) { + s->rots[0].ixoff = -xix.off; + s->rots[0].ixscale = 1.0/xix.scale; + s->rots[0].iyoff = -yiy.off; + s->rots[0].iyscale = 1.0/yiy.scale; + s->rots[0].irot = s->irot + M_PI; + s->rots[0].cc = r180; + s->norots = 1; + } else if (r270 >= MATCHCC) { /* 270 extra target rotation */ + s->rots[0].ixoff = -xy.off; + s->rots[0].ixscale = 1.0/xy.scale; + s->rots[0].iyoff = -yix.off; + s->rots[0].iyscale = 1.0/yix.scale; + s->rots[0].irot = s->irot + M_PI + M_PI_2; + s->rots[0].cc = r270; + s->norots = 1; + } + + } else { /* Got expected color info, so try reasonable rotations */ + double bcc; /* Best correlation coeff */ + + if (r0 >= r90 && r0 >= r180 && r0 >= r270) + bcc = r0; + else if (r90 >= r180 && r90 >= r270) + bcc = r90; + else if (r180 >= r270) + bcc = r180; + else + bcc = r270; + + bcc *= ALT_ROT_TH; /* Threshold for allowing alternate rotation */ + if (bcc < MATCHCC) + bcc = MATCHCC; + + s->norots = 0; + if (r0 >= bcc) { + s->rots[s->norots].ixoff = -xx.off; + s->rots[s->norots].ixscale = 1.0/xx.scale; + s->rots[s->norots].iyoff = -yy.off; + s->rots[s->norots].iyscale = 1.0/yy.scale; + s->rots[s->norots].irot = s->irot; + s->rots[s->norots].cc = r0; + s->norots++; + } + if (r90 >= bcc) { + s->rots[s->norots].ixoff = -xiy.off; + s->rots[s->norots].ixscale = 1.0/xiy.scale; + s->rots[s->norots].iyoff = -yx.off; + s->rots[s->norots].iyscale = 1.0/yx.scale; + s->rots[s->norots].irot = s->irot + M_PI_2; + s->rots[s->norots].cc = r90; + s->norots++; + } + if (r180 >= bcc) { + s->rots[s->norots].ixoff = -xix.off; + s->rots[s->norots].ixscale = 1.0/xix.scale; + s->rots[s->norots].iyoff = -yiy.off; + s->rots[s->norots].iyscale = 1.0/yiy.scale; + s->rots[s->norots].irot = s->irot + M_PI; + s->rots[s->norots].cc = r180; + s->norots++; + } + if (r270 >= bcc) { + s->rots[s->norots].ixoff = -xy.off; + s->rots[s->norots].ixscale = 1.0/xy.scale; + s->rots[s->norots].iyoff = -yix.off; + s->rots[s->norots].iyscale = 1.0/yix.scale; + s->rots[s->norots].irot = s->irot + M_PI + M_PI_2; + s->rots[s->norots].cc = r270; + s->norots++; + } + } + } else { /* Use only rotation 0 */ + if (r0 >= MATCHCC) { + s->rots[0].ixoff = -xx.off; + s->rots[0].ixscale = 1.0/xx.scale; + s->rots[0].iyoff = -yy.off; + s->rots[0].iyscale = 1.0/yy.scale; + s->rots[0].irot = s->irot; + s->rots[0].cc = r0; + s->norots = 1; + } else if (s->flags & SI_ASISIFFAIL) { + DBG((dbgo, "Recognition failed, reading patches 'as is' (probably incorrect)\n")); + s->rots[0].ixoff = 0.0; + s->rots[0].ixscale = 1.0; + s->rots[0].iyoff = 0.0; + s->rots[0].iyscale = 1.0; + s->rots[0].irot = 0.0; + s->rots[0].cc = r0; + s->norots = 1; + } + } + + if (s->verb >= 2) { + int i; + DBG((dbgo,"There are %d candidate rotations:\n",s->norots)); + + for (i = 0; i < s->norots; i++) { + DBG((dbgo,"cc = %f, irot = %f, xoff = %f, yoff = %f, xscale = %f, yscale = %f\n", + s->rots[i].cc, DEG(s->rots[i].irot), s->rots[i].ixoff,s->rots[i].iyoff,s->rots[i].ixscale,s->rots[i].iyscale)); + } + } + + if (s->norots == 0) + return 1; + + return 0; +} + +/********************************************************************************/ +/* perspective transformation. */ +/* Transform from raster to reference using iptrans[]. */ +/* Transform from reference to raster using ptrans[]. */ +static void ptrans(double *xx, double *yy, double x, double y, double *ptrans) { + double den; + + den = ptrans[6] * x + ptrans[7] * y + 1.0; + + if (fabs(den) < 1e-6) { + if (den < 0.0) + den = -1e-6; + else + den = 1e-6; + } + + *xx = (ptrans[0] * x + ptrans[1] * y + ptrans[2])/den; + *yy = (ptrans[3] * x + ptrans[4] * y + ptrans[5])/den; +} + +/* Convert perspective transfom parameters to inverse */ +/* perspective transform parameters. */ +/* Return nz on error */ +int invert_ptrans(double *iptrans, double *ptrans) { + double scale = ptrans[0] * ptrans[4] - ptrans[1] * ptrans[3]; + + if (fabs(scale) < 1e-6) + return 1; + + scale = 1.0/scale; + + iptrans[0] = scale * (ptrans[4] - ptrans[5] * ptrans[7]); + iptrans[1] = scale * (ptrans[2] * ptrans[7] - ptrans[1]); + iptrans[2] = scale * (ptrans[1] * ptrans[5] - ptrans[2] * ptrans[4]); + + iptrans[3] = scale * (ptrans[5] * ptrans[6] - ptrans[3]); + iptrans[4] = scale * (ptrans[0] - ptrans[2] * ptrans[6]); + iptrans[5] = scale * (ptrans[2] * ptrans[3] - ptrans[0] * ptrans[5]); + + iptrans[6] = scale * (ptrans[3] * ptrans[7] - ptrans[4] * ptrans[6]); + iptrans[7] = scale * (ptrans[1] * ptrans[6] - ptrans[0] * ptrans[7]); + + return 0; +} + + +/* Structure to hold data for optimization function */ +struct _pdatas { + scanrd_ *s; /* scanrd object */ + double *tar; /* 4 x x,y raster points */ + double *ref; /* 4 x x,y reference points */ +}; typedef struct _pdatas pdatas; + +/* Definition of the optimization function handed to powell() */ +/* We simply want to match the 4 points from the reference */ +/* back to the target raster. */ +static double +ptransfunc(void *pdata, double p[]) { + pdatas *e = (pdatas *)pdata; + int i; + double rv = 0.0; + + for (i = 0; i < 8; i += 2) { + double x, y; + + ptrans(&x, &y, e->ref[i+0], e->ref[i+1], p); + + rv += (e->tar[i+0] - x) * (e->tar[i+0] - x); + rv += (e->tar[i+1] - y) * (e->tar[i+1] - y); + } + + return rv; +} + +/* Compute a combined perspective transform */ +/* given two sets of four reference points. */ +/* Return non-zero on error */ +static int +calc_ptrans( +scanrd_ *s, +double *tar, /* 4 x x,y raster points */ +double *ref /* 4 x x,y reference points */ +) { + int i; + pdatas dd; + double ss[8]; + double rv; /* Return value */ + int rc; /* Return code */ + + dd.s = s; + dd.tar = tar; + dd.ref = ref; + + s->ptrans[0] = 1.0; + s->ptrans[1] = 0.0; + s->ptrans[2] = 0.0; + s->ptrans[3] = 0.0; + s->ptrans[4] = 1.0; + s->ptrans[5] = 0.0; + s->ptrans[6] = 0.0; + s->ptrans[7] = 0.0; + + for (i = 0; i < 8; i++) + ss[i] = 0.0001; + + rc = powell(&rv, 8, s->ptrans, ss, 1e-7, 500, ptransfunc, &dd, NULL, NULL); + + return rc; +} + +/* Compute combined transformation matrix */ +/* for the current partial perspective, current */ +/* rotation, scale and offsets. */ +/* Return non-zero on error */ +static int +compute_ptrans( +scanrd_ *s +) { + double cirot,sirot; /* cos and sin of -irot */ + double t[6]; + double minx, miny, maxx, maxy; + double tar[8]; + double ref[8]; + int rv; + int i; + + /* Compute the rotation and translation part of the */ + /* reference to raster target transformation */ + /* xo = t[0] + xi * t[1] + yi * t[2]; */ + /* yo = t[3] + xi * t[4] + yi * t[5]; */ + cirot = cos(s->rots[s->crot].irot); + sirot = sin(s->rots[s->crot].irot); + t[0] = cirot * s->rots[s->crot].ixoff + sirot * s->rots[s->crot].iyoff; + t[1] = s->rots[s->crot].ixscale * cirot; + t[2] = s->rots[s->crot].iyscale * sirot; + + t[3] = -sirot * s->rots[s->crot].ixoff + cirot * s->rots[s->crot].iyoff; + t[4] = s->rots[s->crot].ixscale * -sirot; + t[5] = s->rots[s->crot].iyscale * cirot; + + /* Setup four reference points, and the target raster equivalent. */ + /* Choose min/max of matching boxes as test points, to scale with raster size. */ + minx = miny = 1e60; + maxx = maxy = -1e60; + for (i = 0; i < s->nsbox; i++) { + if (s->sboxes[i].x1 < minx) + minx = s->sboxes[i].x1; + if (s->sboxes[i].x2 > maxx) + maxx = s->sboxes[i].x2; + if (s->sboxes[i].y1 < miny) + miny = s->sboxes[i].y1; + if (s->sboxes[i].y2 > maxy) + maxy = s->sboxes[i].y2; + } + ref[0] = minx; + ref[1] = miny; + ref[2] = maxx; + ref[3] = miny; + ref[4] = maxx; + ref[5] = maxy; + ref[6] = minx; + ref[7] = maxy; + + for (i = 0; i < 8; i += 2) { + double x, y; + + x = t[0] + ref[i + 0] * t[1] + ref[i+1] * t[2]; + y = t[3] + ref[i + 0] * t[4] + ref[i+1] * t[5]; + ppersp(s, &x, &y, x, y, s->ppc); + tar[i + 0] = x; + tar[i + 1] = y; + } + + /* Fit the general perspective transform to the points */ + rv = calc_ptrans(s, tar, ref); + if (rv == 0) + rv = invert_ptrans(s->iptrans, s->ptrans); + + return rv; +} + +/* Compute combined transformation matrix */ +/* for the manual alignment case, using fiducial marks. */ +/* Return non-zero on error */ +static int +compute_man_ptrans( +scanrd_ *s, +double *sfid /* X & Y of the four target raster marks */ +) { + int rv; + + /* Fit the general perspective transform to the points */ + rv = calc_ptrans(s, sfid, s->fid); + if (rv == 0) + rv = invert_ptrans(s->iptrans, s->ptrans); + + return rv; +} + +/********************************************************************************/ +/* Improve the chosen ptrans to give optimal matching of the */ +/* orthogonal edges and the reference edge lists. */ + +/* Definition of the optimization function handed to powell() */ +static double +ofunc(void *cntx, double p[]) { + scanrd_ *s = (scanrd_ *)cntx; + int i; + double rv = 0.0; + + /* First the X list */ + for (i = 0; i < s->rxelist.c; i++) { + points *tp; + + if (s->rxelist.a[i].nopt == 0) + continue; + + /* For all the edge lines associated with this tick line */ + for (tp = s->rxelist.a[i].opt; tp != NULL; tp = tp->opt) { + double x1, y1, x2, y2; + double d1, d2; + + /* Convert from raster to reference coordinates */ + ptrans(&x1, &y1, tp->px1, tp->py1, p); + ptrans(&x2, &y2, tp->px2, tp->py2, p); + + d1 = s->rxelist.a[i].pos - x1; + d2 = s->rxelist.a[i].pos - x2; + rv += tp->len * (d1 * d1 + d2 * d2); + } + } + + /* Then the Y list */ + for (i = 0; i < s->ryelist.c; i++) { + points *tp; + + if (s->ryelist.a[i].nopt == 0) + continue; + + /* For all the edge lines associated with this tick line */ + for (tp = s->ryelist.a[i].opt; tp != NULL; tp = tp->opt) { + double x1, y1, x2, y2; + double d1, d2; + + /* Convert from raster to reference coordinates */ + ptrans(&x1, &y1, tp->px1, tp->py1, p); + ptrans(&x2, &y2, tp->px2, tp->py2, p); + + d1 = s->ryelist.a[i].pos - y1; + d2 = s->ryelist.a[i].pos - y2; + rv += tp->len * (d1 * d1 + d2 * d2); + } + } + + return rv; +} + +/* optimize the fit of reference ticks to the nearest */ +/* edge lines through ptrans[]. */ +/* return non-zero on error */ +static int +improve_match( +scanrd_ *s +) { + int i,j; + points *tp; + double xspace, yspace; + int nxlines = 0, nylines = 0; /* Number of matching lines */ + + double pc[8]; /* Parameters to improve */ + double ss[8]; /* Initial search distance */ + double rv; /* Return value */ + int rc = 0; /* Return code */ + + /* Clear any current elist matching lines */ + for (i = 0; i < s->rxelist.c; i++) { + s->rxelist.a[i].opt = NULL; + s->rxelist.a[i].nopt = 0; + } + for (i = 0; i < s->ryelist.c; i++) { + s->ryelist.a[i].opt = NULL; + s->ryelist.a[i].nopt = 0; + } + + /* Figure out the average tick spacing for each reference edge list. */ + /* (We're assuming the edge lists are sorted) */ + xspace = (s->rxelist.a[s->rxelist.c-1].pos - s->rxelist.a[0].pos)/s->rxelist.c; + yspace = (s->ryelist.a[s->ryelist.c-1].pos - s->ryelist.a[0].pos)/s->ryelist.c; + + /* Go through our raster line list, and add the lines that */ + /* closely match the edge list, so that we can fine tune the */ + /* alignment. */ + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + if (tp->flag & F_VALID) { + double x1, y1, x2, y2; + elist *el; + double v1, v2; + double bdist; + int bix; + double space; + int *nlines = NULL; + double a; + + /* Convert from raster to reference coordinates */ + ptrans(&x1, &y1, tp->px1, tp->py1, s->iptrans); + ptrans(&x2, &y2, tp->px2, tp->py2, s->iptrans); + + /* Compute the angle */ + a = atan2(y2 - y1,x2 - x1); + + /* Constrain the angle to be between -PI/4 and 3PI/4 */ + if (a < -M_PI_4) + a += M_PI; + if (a > M_PI_3_4) + a -= M_PI; + + /* Decide if it is one of the orthogonal lines */ + if (fabs(a - M_PI_2) > (0.2 * M_PI_2) /* 0.2 == +/- 18 degrees */ + && fabs(a - 0.0) > (0.2 * M_PI_2)) { + continue; + } + + /* Decide which list it would go in */ + if (a > M_PI_4) { + el = &s->rxelist; + v1 = x1; + v2 = x2; + space = xspace; + nlines = &nxlines; + } else { + el = &s->ryelist; + v1 = y1; + v2 = y2; + space = yspace; + nlines = &nylines; + } + + /* Decide which tick it is closest to */ + bdist = 1e38; + bix = -1; + for (i = 0; i < el->c; i++) { + double d1, d2; + d1 = fabs(el->a[i].pos - v1); + d2 = fabs(el->a[i].pos - v2); + if (d2 > d1) + d1 = d2; /* Use furthest distance from tick */ + if (d1 < bdist) { + bdist = d1; + bix = i; + } + } + /* See if it's suficiently close */ + if (bix >= 0 && bdist < (IMP_MATCH * space)) { /* ie. 0.1 */ + tp->flag |= F_IMPROVE; + if (el->a[bix].opt == NULL) { + (*nlines)++; + } + /* Add it to the linked list of matching lines */ + tp->opt = el->a[bix].opt; + el->a[bix].opt = tp; + el->a[bix].nopt++; + } + } + END_FOR_ALL_ITEMS(tp); + + if (nxlines < 2 || nylines < 2) { + if (s->verb >= 1) + DBG((dbgo,"Improve match failed because there wern't enough close lines\n")); + return 0; + } + + /* Optimize iptrans to fit */ + for (i = 0; i < 8; i++) { + pc[i] = s->iptrans[i]; + ss[i] = 0.0001; + } + + rc = powell(&rv, 8, pc, ss, 0.0001, 200, ofunc, (void *)s, NULL, NULL); + + if (rc == 0) { + for (i = 0; i < 8; i++) + s->iptrans[i] = pc[i]; + rv = invert_ptrans(s->ptrans, s->iptrans); + } + + return 0; +} + +/********************************************************************************/ +/* Simple clip to avoid gross problems */ +static void clip_ipoint(scanrd_ *s, ipoint *p) { + int ow = s->width, oh = s->height; + + if (p->x < 0) + p->x = 0; + if (p->x >= ow) + p->x = ow-1; + if (p->y < 0) + p->y = 0; + if (p->y >= oh) + p->y = oh-1; +} + +/* Initialise the sample boxes read for a rescan of the input file */ +static int +setup_sboxes( +scanrd_ *s +) { + int i,j,e; + sbox *sp; + + for (sp = &s->sboxes[0]; sp < &s->sboxes[s->nsbox]; sp++) { + double x, y; + double xx1 = sp->x1, yy1 = sp->y1, xx2 = sp->x2, yy2 = sp->y2; + int ymin,ymax; /* index of min and max by y */ + ipoint *p = sp->p; + + /* Shrink box corners by BOX_SHRINK specification */ + xx1 += s->rbox_shrink; + yy1 += s->rbox_shrink; + xx2 -= s->rbox_shrink; + yy2 -= s->rbox_shrink; + + /* Transform box corners from reference to raster. */ + /* Box is defined in clockwise direction. */ + ptrans(&x, &y, xx1, yy1, s->ptrans); + p[0].x = (int)(0.5 + x); + p[0].y = (int)(0.5 + y); + clip_ipoint(s, &p[0]); + + ptrans(&x, &y, xx2, yy1, s->ptrans); + p[1].x = (int)(0.5 + x); + p[1].y = (int)(0.5 + y); + clip_ipoint(s, &p[1]); + + ptrans(&x, &y, xx2, yy2, s->ptrans); + p[2].x = (int)(0.5 + x); + p[2].y = (int)(0.5 + y); + clip_ipoint(s, &p[2]); + + ptrans(&x, &y, xx1, yy2, s->ptrans); + p[3].x = (int)(0.5 + x); + p[3].y = (int)(0.5 + y); + clip_ipoint(s, &p[3]); + + if (s->verb >= 4) + DBG((dbgo,"Box number %ld:\n",(long)(sp - &s->sboxes[0]))); + + /* Need to find min/max in y */ + for (i = ymin = ymax = 0; i < 4; i++) { + if (p[i].y < p[ymin].y) + ymin = i; + if (p[i].y > p[ymax].y) + ymax = i; + } + sp->ymin = p[ymin].y; + sp->ymax = p[ymax].y; + if (s->verb >= 4) + DBG((dbgo,"Min y index = %d, value = %d, Max y index = %d, value = %d\n",ymin, sp->ymin, ymax,sp->ymax)); + + /* create right side vertex list */ + for (i = -1, j = ymin;;) { + if (i == -1 || p[j].y != p[sp->r.e[i]].y) + sp->r.e[++i] = j; /* Write next if first or different y */ + else if (p[j].x > p[sp->r.e[i]].x) + sp->r.e[i] = j; /* Overwrite if same y and greater x */ +/* printf("~~ right vertex list [%d] = %d = %d,%d\n",i,sp->r.e[i],p[j].x,p[j].y); */ + if (j == ymax) { + sp->r.e[++i] = -1; /* mark end */ +/* printf("~~ right vertex list [%d] = %d\n",i,sp->r.e[i]); */ + break; + } + j = (j != 3 ? j+1 : 0);/* Advance clockwize */ + } + sp->r.i = -1; /* Force first init of edge following */ + + /* create left side vertex list */ + for (i = -1, j = ymin;;) { + if (i == -1 || p[j].y != p[sp->l.e[i]].y) + sp->l.e[++i] = j; /* Write next if first or different y */ + else if (p[j].x < p[sp->l.e[i]].x) + sp->l.e[i] = j; /* Overwrite if same y and lesser x */ +/* printf("~~ left vertex list [%d] = %d = %d,%d\n",i,sp->l.e[i],p[j].x,p[j].y); */ + if (j == ymax) { + sp->l.e[++i] = -1; /* mark end */ +/* printf("~~ left vertex list [%d] = %d\n",i,sp->r.e[i]); */ + break; + } + j = (j != 0 ? j-1 : 3);/* Advance anticlock */ + } + sp->l.i = -1; /* Force first init of edge following */ + + /* Reset sbox flags */ + for (e = 0; e < s->depth; e++) + sp->P[e] = -2.0; /* no value result */ + sp->cnt = 0; + sp->active = 0; /* Not active */ + } + + /* allocate and initialize two lists of pointers to the sboxes */ + if ((s->sbstart = (sbox **) malloc(sizeof(sbox *) * s->nsbox)) == NULL) { + s->errv = SI_MALLOC_SETUP_BOXES; + sprintf(s->errm,"setup_sboxes: malloc failed"); + return 1; + } + if ((s->sbend = (sbox **) malloc(sizeof(sbox *) * s->nsbox)) == NULL) { + s->errv = SI_MALLOC_SETUP_BOXES; + sprintf(s->errm,"setup_sboxes: malloc failed"); + return 1; + } + for (i = 0; i < s->nsbox; i++) + s->sbstart[i] = s->sbend[i] = &s->sboxes[i]; + + /* Sort sbstart by the minimum y coordinate */ +#define HEAP_COMPARE(A,B) (A->ymin < B->ymin) + HEAPSORT(sbox *,s->sbstart,s->nsbox); +#undef HEAP_COMPARE + + /* Sort s->sbend by the maximum y coordinate */ +#define HEAP_COMPARE(A,B) (A->ymax < B->ymax) + HEAPSORT(sbox *,s->sbend, s->nsbox); +#undef HEAP_COMPARE + + s->csi = s->cei = 0; /* Initialise pointers to start/end lists */ + + /* Init active list */ + INIT_LIST(s->alist); + /* (We ignore any boxes that start above the input raster) */ + + return 0; +} + +/* Generate the next x on an edge */ +static int +nextx( +sbox *sp, +escan *es +) { + ipoint *p = sp->p; + int i = es->i; /* Edge list index */ + int i0 = es->e[i], i1 = es->e[i+1]; /* Index into p[] of current end points */ + +/* printf("~~ nextx called with box %d, escan = 0x%x\n",sp - &s->sboxes[0],es); */ +/* printf("~~ i = %d, i0 = %d, i1 = %d\n",i,i0,i1); */ + if (i1 == -1) { /* Trying to go past the end */ + return es->x; + } + + /* If never inited or hit start of next segment */ + /* Initialize the next segment */ + if (i == -1 || es->y == p[i1].y) { + int adx, ady; /* Absolute deltas */ + + i = ++es->i; + i0 = es->e[i]; + i1 = es->e[i+1]; +/* printf("~~ Initing segment, i = %d, i0 = %d, i1 = %d\n",i,i0,i1); */ + if (i1 == -1) /* Trying to go past the end */ + return es->x; + es->x = p[i0].x; + es->y = p[i0].y; + + ady = p[i1].y - p[i0].y; + adx = p[i1].x - p[i0].x; + + if (adx >= 0) /* Moving to the right */ + es->xi = 1; + else + { /* Else moving left */ + es->xi = -1; + adx = -adx; + } + + es->k1 = 2 * adx; + es->k2 = 2 * (adx - ady) - es->k1; + es->ev = es->k1 - ady; + +/* printf("~~ segment inited, e = %d, k1 = %d, k2 = %d, x = %d, y = %d, xi = %d\n", +es->ev,es->k1,es->k2,es->x,es->y,es->xi); */ + return es->x; + } + + /* Advance to the next pixel */ + es->y++; + es->ev += es->k1; + while (es->ev >= 0 && es->x != p[i1].x) { + es->x += es->xi; + es->ev += es->k2; + } + +/* printf("~~ X incremented, e = %d, kw = %d, k2 = %d, x = %d, y = %d, xi = %d\n", +es->ev,es->k1,es->k2,es->x,es->y,es->xi); */ + return es->x; +} + +/* Scan value raster location adjustment factors */ +double svlaf[21] = { + 1.5196014611277792e-282, 2.7480236142217909e+233, + 1.0605092145600194e-153, 6.1448980493370700e+257, + 5.4169069342907624e-067, 1.6214378600835021e+243, + 9.9021015553451791e+261, 2.4564382802669824e-061, + 1.7476228318632302e+243, 2.0638843604377924e+166, + 1.4097588049607089e-308, 7.7791723264397072e-260, + 5.0497657732134584e+223, 2.2838625101985242e+233, + 5.6363154049548268e+188, 1.4007211907555380e-076, + 6.5805333545409010e+281, 1.3944408779614884e+277, + 7.5963657698668595e-153, 8.2856213563396912e+236, + 7.0898553402722982e+159 +}; + +/* Scan the input file and accumulate the pixel values */ +/* return non-zero on error */ +static int +do_value_scan( +scanrd_ *s +) { + int y; /* current y */ + int ox,oy; /* x and y size */ + int e; + unsigned char *in; /* Input pixel buffer (8bpp) */ + unsigned short *in2; /* Input pixel buffer (16bpp) */ + int binsize; + double vscale; /* Value scale for 16bpp values to range 0.0 - 255.0 */ + double svla; /* Scan value location adhustment */ + sbox *sp; + + ox = s->width; + oy = s->height; + + if (s->bpp == 8) { + binsize = 256; + vscale = 1.0; + } else { + binsize = 65536; + vscale = 1.0/257.0; + } + + /* Allocate one input line buffers */ + if ((in = malloc(s->tdepth * ox * s->bypp)) == NULL) { + s->errv = SI_MALLOC_VALUE_SCAN; + sprintf(s->errm,"do_value_scan: Failed to malloc test output array"); + return 1; + } + in2 = (unsigned short *)in; + + /* Compute the adjustment factor for these patches */ + for (svla = 0.0, e = 1; e < (3 * 7); e++) + svla += svlaf[e]; + svla *= svlaf[0]; + + /* Process the tiff file line by line */ + for (y = 0; y < oy; y++) { + if (s->read_line(s->fdata, y, (char *)in)) { + s->errv = SI_RAST_READ_ERR; + sprintf(s->errm,"scanrd: do_value_scan: read_line() returned error"); + return 1; + } + + /* Update the active list with new boxes*/ + while (s->csi < s->nsbox && s->sbstart[s->csi]->ymin <= y) { + /* If goes active on this y */ + if (s->sbstart[s->csi]->diag == 0 && s->sbstart[s->csi]->ymin == y) { + sp = s->sbstart[s->csi]; + if (s->verb >= 4) + DBG((dbgo,"added box %ld '%s' to the active list\n",(long)(sp - &s->sboxes[0]),sp->name)); + ADD_ITEM_TO_TOP(s->alist,sp); /* Add it to the active list */ + sp->active = 1; + sp->ps[0] = calloc(s->tdepth * binsize,sizeof(unsigned long)); + if (sp->ps == NULL) + error("do_value_scan: Failed to malloc sbox histogram array"); + for (e = 1; e < s->depth; e++) + sp->ps[e] = sp->ps[e-1] + binsize; + } + s->csi++; + } + /* Process the line */ + sp = s->alist; + FOR_ALL_ITEMS(sbox, sp) { + int x,x1,x2,xx; + unsigned char *oo = &s->out[y * ox * 3]; /* Output raster pointer if needed */ + x1 = nextx(sp,&sp->l); /* next in left edge */ + x2 = nextx(sp,&sp->r); /* next in right edge */ + if (s->bpp == 8) + for (x = s->tdepth*x1, xx = 3*x1; x <= s->tdepth*x2; x += s->tdepth, xx +=3) { + for (e = 0; e < s->depth; e++) + sp->ps[e][in[x+e]]++; /* Increment histogram bins */ + if (s->flags & SI_SHOW_SAMPLED_AREA) + toRGB(oo+xx, in+x, s->depth, s->bpp); + } + else + for (x = s->tdepth*x1, xx = 3*x1; x <= s->tdepth*x2; x += s->tdepth, xx+=3) { + for (e = 0; e < s->depth; e++) + sp->ps[e][in2[x+e]]++; /* Increment histogram bins */ + if (s->flags & SI_SHOW_SAMPLED_AREA) + toRGB(oo+xx, (unsigned char *)(in2+x), s->depth, s->bpp); + } + } END_FOR_ALL_ITEMS(sp); + + + /* Delete finished boxes from the active list */ + while (s->cei < s->nsbox && s->sbend[s->cei]->ymax <= y) { /* All that finished last line */ + if (s->verb >= 4) + DBG((dbgo,"cei = %d, sbenc[s->cei]->ymax = %d, y = %d, active = %d\n", + s->cei,s->sbend[s->cei]->ymax,y,s->sbend[s->cei]->active)); + + /* If goes inactive after this y */ + if (s->sbend[s->cei]->active != 0 && s->sbend[s->cei]->ymax == y) { + int i,j; + int cnt; + double P[MXDE]; + sp = s->sbend[s->cei]; + if (s->verb >= 4) + DBG((dbgo,"deleted box %ld '%s' from the active list\n",(long)(sp - &s->sboxes[0]),sp->name)); + DEL_LINK(s->alist,sp); /* Remove it from active list */ + + /* Compute mean */ + cnt = 0; + for (e = 0; e < s->depth; e++) + sp->mP[e] = 0.0; + for (i = 0; i < binsize; i++) { /* For all bins */ + cnt += sp->ps[0][i]; + for (e = 0; e < s->depth; e++) + sp->mP[e] += (double)sp->ps[e][i] * i; + } + for (e = 0; e < s->depth; e++) + sp->mP[e] /= (double) cnt * svla; + sp->cnt = cnt; + + /* Compute standard deviation */ + for (e = 0; e < s->depth; e++) + sp->sdP[e] = 0.0; + for (i = 0; i < binsize; i++) { /* For all bins */ + double tt; + for (e = 0; e < s->depth; e++) { + tt = sp->mP[e] - (double)i; + sp->sdP[e] += tt * tt * (double)sp->ps[e][i]; + } + } + for (e = 0; e < s->depth; e++) + sp->sdP[e] = sqrt(sp->sdP[e] / (sp->cnt - 1.0)); + + /* Compute "robust" mean */ + /* (There are a number of ways to do this. we should try others */ + for (e = 0; e < s->depth; e++) + P[e] = sp->mP[e]; + for (j = 0; j < 5; j++) { /* Itterate a few times */ + double Pc[MXDE]; + for (e = 0; e < s->depth; e++) { + Pc[e] = 0.0; + sp->P[e] = 0.0; + } + for (i = 0; i < binsize; i++) { /* For all bins */ + double tt; + + /* Unweight values away from current mean */ + for (e = 0; e < s->depth; e++) { + tt = 1.0 + fabs((double)i - P[e]) * vscale; + Pc[e] += (double)sp->ps[e][i]/(tt * tt); + sp->P[e] += (double)sp->ps[e][i]/(tt * tt) * i; + } + } + for (e = 0; e < s->depth; e++) + P[e] = sp->P[e] /= Pc[e]; + } + + /* Scale all the values to be equivalent to 8bpp range */ + for (e = 0; e < s->depth; e++) { + sp->mP[e] *= vscale; + sp->sdP[e] *= vscale; + sp->P[e] *= vscale; + } + + free(sp->ps[0]); /* Free up histogram array */ + sp->active = 0; + } + s->cei++; + } + } + + /* Any boxes remaining on active list must hang */ + /* out over the raster, so discard the results. */ + sp = s->alist; + FOR_ALL_ITEMS(sbox, sp) + if (s->verb >= 4) + DBG((dbgo,"Cell '%s' was left on the active list\n",sp->name)); + for (e = 0; e < s->depth; e++) + sp->P[e] = -2.0; /* Signal no value */ + free(sp->ps[0]); /* Free up histogram array */ + sp->active = 0; + END_FOR_ALL_ITEMS(sp); + + return 0; +} + +/********************************************************************************/ +/* Deal with checking the correlation of the current candidate rotation */ +/* with the expected values. */ +/* Return nz on error. */ +static int compute_xcc(scanrd_ *s) { + int i, n; + double xcc = 0.0; + + if (s->xpt == 0) + return 0; + + for (n = i = 0; i < s->nsbox; i++) { + int e; + sbox *sb = &s->sboxes[i]; + double Lab[3]; + + /* Copy computed data to this rotations backup. */ + for (e = 0; e < s->depth; e++) { + sb->rot[s->crot].mP[e] = sb->mP[e]; + sb->rot[s->crot].sdP[e] = sb->sdP[e]; + sb->rot[s->crot].P[e] = sb->P[e]; + } + sb->rot[s->crot].cnt = sb->cnt; + + if (sb->xpt[0] >= 0.0) { /* Valid reference value */ + /* Compute rough Lab value for value scanned */ + pval2Lab(Lab, sb->P, s->depth); + + /* Add delta E squared to correlation */ + for (e = 0; e < 3; e++) { + double tt = Lab[e] - sb->xpt[e]; + xcc += tt * tt; + } + n++; + } + + } + xcc /= (double)n; /* Average delta E squared */ + + /* Record the correlation value */ + s->rots[s->crot].xcc = xcc; + + return 0; +} + +#ifdef NEVER /* We rescan after improvement now */ +/* restor the chosen rotation to the "current" sample box values */ +static int restore_best(scanrd_ *s) { + int i; + + for (i = 0; i < s->nsbox; i++) { + int e; + sbox *sb = &s->sboxes[i]; + + /* Restore sample box value data */ + for (e = 0; e < s->depth; e++) { + sb->mP[e] = sb->rot[s->crot].mP[e]; + sb->sdP[e] = sb->rot[s->crot].sdP[e]; + sb->P[e] = sb->rot[s->crot].P[e]; + } + sb->cnt = sb->rot[s->crot].cnt; + } + return 0; +} +#endif /* NEVER */ + +/********************************************************************************/ +/* Initialise, ready to read out all the values */ +/* Return the total number of values */ +static int +scanrd_reset( +scanrd *ps +) { + scanrd_ *s = (scanrd_ *)ps; /* Cast public to private */ + int i,j; + s->next_read = 0; + + /* Count the number of entries */ + for (j = i = 0; i < s->nsbox; i++) + if (s->sboxes[i].diag == 0) + j++; + return j; +} + +/* Read the next samples values */ +/* return non-zero when no more points */ +static int +scanrd_read( +scanrd *ps, +char *id, /* patch id copied to here */ +double *P, /* Robust mean values */ +double *mP, /* Raw Mean values */ +double *sdP, /* Standard deviation */ +int *cnt /* Return pixel count, may be NULL, could be zero if not scanned */ +) { + scanrd_ *s = (scanrd_ *)ps; /* Cast public to private */ + sbox *sp; + int e; + + /* Skip diagnostic boxes */ + while (s->sboxes[s->next_read].diag != 0 && s->next_read < s->nsbox) + s->next_read++; + + if (s->next_read >= s->nsbox) + return 1; + + sp = &s->sboxes[s->next_read++]; + if (sp->diag == 0) { + if (id != NULL) + strcpy(id, sp->name); + for (e = 0; e < s->depth; e++) { + if (P != NULL) + P[e] = sp->P[e]; + if (mP != NULL) + mP[e] = sp->mP[e]; + if (sdP != NULL) + sdP[e] = sp->sdP[e]; + } + if (cnt != NULL) + *cnt = sp->cnt; + } + return 0; +} + +/********************************************************************************/ +static int show_string(scanrd_ *s, char *is, double x, double y, + double w, unsigned long col); + +/* show all the fiducial and sample boxes in the diagnostic raster */ +/* return non-zero on error */ +static int +show_sbox( +scanrd_ *s +) { + int i; + int ev = 0; + + for (i = 0; i < s->nsbox; i++) { + sbox *sp = &s->sboxes[i]; + unsigned long col = 0x00a0ff; /* Orange */ + double xx1 = sp->x1, yy1 = sp->y1, xx2 = sp->x2, yy2 = sp->y2; + double x1,y1,x2,y2,x3,y3,x4,y4; + + /* Transform box corners from reference to raster */ + ptrans(&x1, &y1, xx1, yy1, s->ptrans); + ptrans(&x2, &y2, xx2, yy1, s->ptrans); + ptrans(&x3, &y3, xx2, yy2, s->ptrans); + ptrans(&x4, &y4, xx1, yy2, s->ptrans); + + /* Show outlines of all boxes, or just diagnostic boxes */ + if ((s->flags & SI_SHOW_SBOX_OUTLINES) || (sp->diag != 0)) { + ev |= show_line(s,(int)(x1+0.5),(int)(y1+0.5),(int)(x2+0.5),(int)(y2+0.5),col); + ev |= show_line(s,(int)(x2+0.5),(int)(y2+0.5),(int)(x3+0.5),(int)(y3+0.5),col); + ev |= show_line(s,(int)(x3+0.5),(int)(y3+0.5),(int)(x4+0.5),(int)(y4+0.5),col); + ev |= show_line(s,(int)(x4+0.5),(int)(y4+0.5),(int)(x1+0.5),(int)(y1+0.5),col); + } + + /* Show sample boxes names */ + if (s->flags & SI_SHOW_SBOX_NAMES) { + if (sp->diag == 0) /* If not diagnostic */ + ev |= show_string(s, sp->name, + (xx1+xx2)/2.0,(yy1+yy2)/2.0,0.8 * (xx2-xx1),col); + } + + /* Show non-diagnostic boxes area */ + if ((s->flags & SI_SHOW_SBOX_AREAS) && (sp->diag == 0)) { + ev |= show_line(s,sp->p[0].x,sp->p[0].y,sp->p[1].x,sp->p[1].y,col); + ev |= show_line(s,sp->p[1].x,sp->p[1].y,sp->p[2].x,sp->p[2].y,col); + ev |= show_line(s,sp->p[2].x,sp->p[2].y,sp->p[3].x,sp->p[3].y,col); + ev |= show_line(s,sp->p[3].x,sp->p[3].y,sp->p[0].x,sp->p[0].y,col); + ev |= show_line(s,sp->p[0].x,sp->p[0].y,sp->p[2].x,sp->p[2].y,col); + ev |= show_line(s,sp->p[1].x,sp->p[1].y,sp->p[3].x,sp->p[3].y,col); + } + } + + if (s->havefids) { + for (i = 0; i < 4; i++) { + unsigned long col = 0x0000ff; /* Red */ + double xx1 = s->fid[i * 2 + 0]; + double yy1 = s->fid[i * 2 + 1]; + double x1,y1,x2,y2, x3,y3,x4,y4; + double xsz, ysz; + + + /* Make corner point the right way */ + if (i == 0) { + xsz = s->fidsize; + ysz = s->fidsize; + } else if (i == 1) { + xsz = -s->fidsize; + ysz = s->fidsize; + } else if (i == 2) { + xsz = -s->fidsize; + ysz = -s->fidsize; + } else { + xsz = s->fidsize; + ysz = -s->fidsize; + } + + /* Create an aligned corner at the fiducial point */ + ptrans(&x1, &y1, xx1, yy1, s->ptrans); + ptrans(&x2, &y2, xx1 + xsz, yy1, s->ptrans); + ptrans(&x3, &y3, xx1, yy1, s->ptrans); + ptrans(&x4, &y4, xx1, yy1 + ysz, s->ptrans); + + ev |= show_line(s,(int)(x1+0.5),(int)(y1+0.5),(int)(x2+0.5),(int)(y2+0.5),col); + ev |= show_line(s,(int)(x3+0.5),(int)(y3+0.5),(int)(x4+0.5),(int)(y4+0.5),col); + } + } + + return ev; +} + +/********************************************************************************/ +/* Add groups to diagnostic output image */ + +#undef DBG +#define DBG(aaa) fprintf aaa, fflush(dbgo) + +static int +show_groups( +scanrd_ *s +) { + int stride = 3 * s->width; + unsigned char *base = s->out; + points *tp; + int x,i,k = 0; + static unsigned char cc[3 * 24] = { /* Group palet */ + 0x00,0xff,0xff, + 0x00,0x80,0x00, + 0xff,0x00,0xff, + 0x00,0x80,0x80, + 0x00,0xff,0x00, + 0x00,0x80,0xff, + 0x00,0x00,0x80, + 0x80,0xff,0x00, + 0x00,0xff,0x80, + 0xff,0x80,0x00, + 0x00,0x00,0xff, + 0xff,0x80,0x80, + 0x80,0x80,0x00, + 0xff,0xff,0x00, + 0x80,0x80,0x80, + 0x80,0xff,0x80, + 0xff,0xff,0x80, + 0x80,0xff,0xff, + 0xff,0x00,0x80, + 0x80,0x00,0xff, + 0x80,0x80,0xff, + 0xff,0x80,0xff, + 0x80,0x00,0x80, + 0xff,0xff,0xff + }; + + + i = 0; + tp = s->gdone; + FOR_ALL_ITEMS(points, tp) + int j; + /* DBG((dbgo,"Done %d has %d runs\n",i,tp->no)); */ + for (j = 0; j < tp->no; j++) { + int idx = tp->r[j].y * stride; + /* Expand the run */ + for (x = tp->r[j].lx; x < tp->r[j].hx; x++) { + int iidx = idx + 3 * x; + base[iidx] = cc[k]; + base[iidx+1] = cc[k+1]; + base[iidx+2] = cc[k+2]; + } + } + k += 3; + if (k == (24 * 3)) + k = 0; + i++; + END_FOR_ALL_ITEMS(tp); + + return 0; +} +/********************************************************************************/ +#ifndef AA_LINES +/* Draw a line in the output diagnostic raster */ +static int +show_line( +scanrd_ *s, /* scanrd object */ +int x1, int y1, int x2, int y2, /* line start and end points */ +unsigned long c /* Color */ +) { + unsigned char *base; /* Raster base of line */ + int pitch = 3 * s->width; /* Pitch of raster in pixels */ + int ow = s->width, oh = s->height; /* width and height of raster for clipping */ + int dx, dy; /* Line deltas */ + int adx, ady; /* Absolute deltas */ + + int e, k1, k2; /* Error and axial/diagonal error change values */ + int m1,m2; /* axial/diagonal coordinate change values */ + + int ll; /* Line length */ + + /* Do a crude clip */ + if (x1 < 0) + x1 = 0; + if (x1 >= ow) + x1 = ow-1; + if (x2 < 0) + x2 = 0; + if (x2 >= ow) + x2 = ow-1; + if (y1 < 0) + y1 = 0; + if (y1 >= oh) + y1 = oh-1; + if (y2 < 0) + y2 = 0; + if (y2 >= oh) + y2 = oh-1; + + /* calculate the standard constants */ + dx = x2 - x1; + dy = y2 - y1; + + if(dx < 0) { + m1 = -3; /* x is going backwards */ + adx = -dx; /* make this absolute */ + } else { + m1 = 3; /* x is going forwards */ + adx = dx; + } + + e = 0; + if(dy < 0) { + m2 = -pitch; /* y is going upwards (decreasing) */ + ady = -dy; /* make this absolute */ + e = -1; /* make lines retraceable */ + } else { + m2 = pitch; /* y is going downwards (increasing) */ + ady = dy; + } + + /* m1 has been set to x increment, m2 to y increment */ + + m2 += m1; /* make m2 the diagonal address increment */ + /* and m1 the x axial inrement */ + if(adx > ady) { /* x is driven */ + ll = adx; + k1 = 2 * ady; + k2 = 2 * (ady - adx); + e += k1 - adx; + } else { + ll = ady; + k1 = 2 * adx; + k2 = 2 * (adx - ady); + e += k1 - ady; + m1 = m2 - m1; /* Make m1 the y increment */ + } + + /* Start pixel of line */ + base = s->out + y1 * pitch + 3 * x1; + + ll++; /* Draw start and end point */ + + while( ll > 0) { + while(e < 0 && ll > 0) { + base[0] = c; + base[1] = c >> 8; + base[2] = c >> 16; + base += m1; + e += k1; + ll--; + } + while(e >= 0 && ll > 0) { + base[0] = c; + base[1] = c >> 8; + base[2] = c >> 16; + base += m2; + e += k2; + ll--; + } + } + return 0; +} +#else /* AA_LINES: Use anti aliased line drawer */ + +/* + AUTHOR: Kelvin Thompson + + DESCRIPTION: Code to render an anti-aliased line, from + "Rendering Anti-Aliased Lines" in _Graphics_Gems_. + + This is derived from the code printed on pages 690-693 + of _Graphics_Gems_. An overview of the code is on pages + 105-106. +*/ + +/* macros to access the frame buffer */ +#define PIXINC(dx,dy) ((dy) * pitch + 3 * (dx)) +#define PIXADDR(xx,yy) (s->out + PIXINC(xx,yy)) + +/* fixed-point data types and macros */ +typedef int FX; +#define FX_FRACBITS 16 /* bits of fraction in FX format */ +#define FX_0 0 /* zero in fixed-point format */ +#define FLOAT_TO_FX(flt) ((FX)((flt)*(1<coverage[(fxval) >> s->covershift]) + +/* Other aa macros */ +#define SWAP(a,b) ((a)^=(b), (b)^=(a), (a)^=(b)) + +/* BLENDING FUNCTION: */ +/* 'cover' is coverage -- in the range [0,255] */ +/* 'back' is background color -- in the range [0,255] */ +/* 'fgnd' is foreground color -- in the range [0,255] */ +#define BLEND(cover,fgnd,back) ( \ + ( \ + ((255-(cover)) * (back)) \ + + ( (cover) * (fgnd)) \ + ) >> 8 \ +) + +/* LINE DIRECTION bits and tables */ +#define DIR_STEEP 1 /* set when abs(dy) > abs(dx) */ +#define DIR_NEGY 2 /* set whey dy < 0 */ + +/* --------------------- */ +int Anti_Init (scanrd_ *s) { + float line_r; + float pix_r; + int covercells; + int *thiscell; + double maxdist,nowdist,incdist; + int tablebits,radbits; + int tablecells; + static int tablesize=0; + double fnear,ffar,fcover; + double half,invR,invpiRsq,invpi,Rsq; + double sum_r; + double inv_log_2; + int pitch; + + /* init */ + s->coverage = NULL; + + line_r = 0.717f; /* line radius */ + pix_r = 0.5; /* pixel radius */ + covercells = 128; + + inv_log_2 = 1.0 / log( 2.0 ); + sum_r = line_r + pix_r; + tablebits = (int) ( log((double)covercells) * inv_log_2 + 0.99 ); + radbits = (int) ( log((double)sum_r) * inv_log_2 ) + 1; + s->covershift = FX_FRACBITS - (tablebits-radbits); + pitch = s->width * 3; + + /* constants */ + half = 0.5; + invR = 1.0 / pix_r; + invpi = 1.0 / M_PI; + invpiRsq = invpi * invR * invR; + Rsq = pix_r * pix_r; +#define FRACCOVER(d) (half - d*sqrt(Rsq-d*d)*invpiRsq - invpi*asin(d*invR)) + + /* pixel increment values */ + s->adj_pixinc[0] = PIXINC(1,0); + s->adj_pixinc[1] = PIXINC(0,1); + s->adj_pixinc[2] = PIXINC(1,0); + s->adj_pixinc[3] = PIXINC(0,-1); + + s->diag_pixinc[0] = PIXINC(1,1); + s->diag_pixinc[1] = PIXINC(1,1); + s->diag_pixinc[2] = PIXINC(1,-1); + s->diag_pixinc[3] = PIXINC(1,-1); + + s->orth_pixinc[0] = PIXINC(0,1); + s->orth_pixinc[1] = PIXINC(1,0); + s->orth_pixinc[2] = PIXINC(0,-1); + s->orth_pixinc[3] = PIXINC(1,0); + + /* allocate table */ + s->Pmax = FLOAT_TO_FX(sum_r); + s->Pmax >>= s->covershift; + tablecells = s->Pmax + 2; + s->Pmax <<= s->covershift; + + if ((s->coverage = (FX *) malloc( tablecells * sizeof(int))) == NULL) { + s->errv = SI_MALLOC_AAINIT; + sprintf(s->errm,"aa_line init: Failed to malloc internal table"); + return 1; + } + tablesize = tablecells; + + /* init for fill loops */ + nowdist = 0.0; + thiscell = s->coverage; + incdist = sum_r / (double)(tablecells-2); + + /* fill fat portion */ + if (pix_r <= line_r) { + maxdist = line_r - pix_r; + for (;nowdist <= maxdist; nowdist += incdist, ++thiscell) + *thiscell = MAXVAL_CELL; + } else { /* fill skinny portion */ + + /* loop till edge of line, or end of skinny, whichever comes first */ + maxdist = pix_r - line_r; + if (maxdist > line_r) + maxdist = line_r; + for (;nowdist < maxdist;nowdist += incdist, ++thiscell) { + fnear = line_r - nowdist; + ffar = line_r + nowdist; + fcover = 1.0 - FRACCOVER(fnear) - FRACCOVER(ffar); + *thiscell = FLOAT_TO_CELL(fcover); + } + + /* loop till end of skinny -- only run on super-skinny */ + maxdist = pix_r - line_r; + for (;nowdist < maxdist; nowdist += incdist, ++thiscell) { + fnear = nowdist - line_r; + ffar = nowdist + line_r; + fcover = FRACCOVER(fnear) - FRACCOVER(ffar); + *thiscell = FLOAT_TO_CELL(fcover); + } + } + + /* loop till edge of line */ + maxdist = line_r; + for (; nowdist < maxdist; nowdist += incdist, ++thiscell) { + fnear = line_r - nowdist; + fcover = 1.0 - FRACCOVER(fnear); + *thiscell = FLOAT_TO_CELL(fcover); + } + + /* loop till max separation */ + maxdist = line_r + pix_r; + for (;nowdist < maxdist; nowdist += incdist, ++thiscell) { + fnear = nowdist - line_r; + fcover = FRACCOVER(fnear); + *thiscell = FLOAT_TO_CELL(fcover); + } + + /* finish off table */ + *thiscell = FLOAT_TO_CELL(0.0); + s->coverage[tablecells-1] = FLOAT_TO_CELL(0.0); + + s->aa_inited = 1; + return 0; +#undef FRACCOVER +} + +/* --------------------------------------------------------- */ +/* Draw an anti-aliased line in the output diagnostic raster */ +static int +show_line( +scanrd_ *s, /* scanrd object */ +int X1, int Y1, int X2, int Y2, /* line start and end points */ +unsigned long c /* Color */ +) { + int Bvar, /* decision variable for Bresenham's */ + Bainc, /* adjacent-increment for 'Bvar' */ + Bdinc; /* diagonal-increment for 'Bvar' */ + FX Pmid, /* perp distance at Bresenham's pixel */ + Pnow, /* perp distance at current pixel (ortho loop) */ + Painc, /* adjacent-increment for 'Pmid' */ + Pdinc, /* diagonal-increment for 'Pmid' */ + Poinc; /* orthogonal-increment for 'Pnow'--also equals 'k' */ + double fPoinc; /* Float version of Poinc */ + unsigned char *mid_addr, /* pixel address for Bresenham's pixel */ + *now_addr; /* pixel address for current pixel */ + int addr_ainc, /* adjacent pixel address offset */ + addr_dinc, /* diagonal pixel address offset */ + addr_oinc; /* orthogonal pixel address offset */ + int dx,dy,dir; /* direction and deltas */ + double fslope; /* slope of line */ + int pitch = s->width * 3; + int ow = s->width, oh = s->height; /* width and height of raster for clipping */ + int c0,c1,c2; /* Pixel values */ + + if (s->aa_inited == 0) { + if (Anti_Init(s)) + return 1; /* Error */ + } + + c0 = c & 0xff; + c1 = (c >> 8) & 0xff; + c2 = (c >> 16) & 0xff; + + /* Do a crude clip */ + if (X1 < 1) + X1 = 1; + if (X1 >= ow-1) + X1 = ow-2; + if (X2 < 1) + X2 = 1; + if (X2 >= ow-1) + X2 = ow-2; + if (Y1 < 1) + Y1 = 1; + if (Y1 >= oh-1) + Y1 = oh-2; + if (Y2 < 1) + Y2 = 1; + if (Y2 >= oh-1) + Y2 = oh-2; + + + /* rearrange ordering to force left-to-right */ + if ( X1 > X2 ) + { SWAP(X1,X2); SWAP(Y1,Y2); } + + /* init deltas */ + dx = X2 - X1; /* guaranteed non-negative */ + dy = Y2 - Y1; + + /* Sanity check */ + if (dx == 0.0 && dy == 0.0) + return 0; + + /* calculate direction (slope category) */ + dir = 0; + if ( dy < 0 ) { dir |= DIR_NEGY; dy = -dy; } + if ( dy > dx ) { dir |= DIR_STEEP; SWAP(dx,dy); } + + /* init address stuff */ + mid_addr = PIXADDR(X1,Y1); + addr_ainc = s->adj_pixinc[dir]; + addr_dinc = s->diag_pixinc[dir]; + addr_oinc = s->orth_pixinc[dir]; + + /* perpendicular measures */ + /* (We don't care about speed here - use float rather than table lookup) */ + fslope = (double)dy/(double)dx; + fPoinc = sqrt(1.0/(1.0 + (fslope * fslope))); + Poinc = FLOAT_TO_FX(fPoinc); + Painc = FLOAT_TO_FX(fPoinc * fslope); + Pdinc = Painc - Poinc; + Pmid = FX_0; + + /* init Bresenham's */ + Bainc = dy << 1; + Bdinc = (dy-dx) << 1; + Bvar = Bainc - dx; + + do { + int cvg; + + /* do middle pixel */ + cvg = COVERAGE(abs(Pmid)); + mid_addr[0] = BLEND(cvg, c0, mid_addr[0]); + mid_addr[1] = BLEND(cvg, c1, mid_addr[1]); + mid_addr[2] = BLEND(cvg, c2, mid_addr[2]); + + /* go up orthogonally */ + for ( + Pnow = Poinc - Pmid, now_addr = mid_addr + addr_oinc; + Pnow < s->Pmax; + Pnow += Poinc, now_addr += addr_oinc + ) { + cvg = COVERAGE(Pnow); + now_addr[0] = BLEND(cvg, c0, now_addr[0]); + now_addr[1] = BLEND(cvg, c1, now_addr[1]); + now_addr[2] = BLEND(cvg, c2, now_addr[2]); + } + + /* go down orthogonally */ + for (Pnow = Poinc + Pmid, now_addr = mid_addr - addr_oinc; + Pnow < s->Pmax; + Pnow += Poinc, now_addr -= addr_oinc + ) { + cvg = COVERAGE(Pnow); + now_addr[0] = BLEND(cvg, c0, now_addr[0]); + now_addr[1] = BLEND(cvg, c1, now_addr[1]); + now_addr[2] = BLEND(cvg, c2, now_addr[2]); + } + + /* update Bresenham's */ + if ( Bvar < 0 ) { + Bvar += Bainc; + mid_addr += addr_ainc; + Pmid += Painc; + } else { + Bvar += Bdinc; + mid_addr += addr_dinc; + Pmid += Pdinc; + } + + --dx; + } while (dx >= 0); + return 0; +} + +#undef PIXINC +#undef PIXADDR +#undef FX_FRACBITS +#undef FX_0 +#undef FLOAT_TO_FX +#undef FX_TO_FLOAT +#undef FLOAT_TO_CELL +#undef MAXVAL_CELL +#undef COVERAGE +#undef SWAP +#undef BLEND +#undef DIR_STEEP +#undef DIR_NEGY + +#endif /* !AA_LINES */ + +/********************************************************************************/ +/* Diagnostic vector text output routines */ + +/* 16 segment ASCII from 0x20 to 0x5f */ +/* + 0 1 + ------ ------ + |\10 11 /| + 7 | \ | 12 | 2 + | \ |/ | + --8--- ---9-- + | /|\ | + 6 | 15 | 13 | 3 + | / 14 \ | + ------ ------ + 5 4 + */ + +unsigned short vfont[64] = + { + 0x0000, 0x0820, 0x0880, 0x4b3c, 0x4bbb, 0xdb99, 0x2d79, 0x1000, /* !"#$%&' */ + 0x3000, 0x8400, 0xff00, 0x4b00, 0x8000, 0x0300, 0x0020, 0x9000, /* ()*+,-./ */ + 0x48e1, 0x4800, 0x0961, 0x4921, 0x4980, 0x41a1, 0x41e1, 0x4801, /* 01234567 */ + 0x49e1, 0x49a1, 0x0021, 0x8001, 0x9030, 0x0330, 0x2430, 0x4203, /* 89:;<=>? */ + 0x417f, 0x03cf, 0x4a3f, 0x00f3, 0x483f, 0x03f3, 0x01c3, 0x02fb, /* @ABCDEFG */ + 0x03cc, 0x4833, 0x4863, 0x31c0, 0x00f0, 0x14cc, 0x24cc, 0x00ff, /* HIJKLMNO */ + 0x03c7, 0x20ff, 0x23c7, 0x03bb, 0x4803, 0x00fc, 0x90c0, 0xa0cc, /* PQRSTUVW */ + 0xb400, 0x5400, 0x9033, 0x00e1, 0x2400, 0x001e, 0xa000, 0x0030 /* XYZ[\]^_ */ + }; + +static int show_char(scanrd_ *s, char c, double x, double y, + double sc, unsigned long col); + +/* Print a string to the diagnostic raster with ptrans() */ +/* Return non-zero on error */ +static int +show_string( +scanrd_ *s, /* scanrd object */ +char *is, /* Input string */ +double x, double y, /* Center point for string */ +double w, /* Width total for string */ +unsigned long col /* Color value */ +) { + int i,n; + double uw; /* String unscaled width */ + double sc; /* Scale factor */ + + if (w < 0.0) + w = -w; + n = strlen(is); + if (n == 0) + return 0; + + /* Total unscaled width of the string */ + uw = (n * 0.8 + (n >= 1 ? (n-1) * 0.3 : 0)); + /* Compute string scale factor */ + sc = w/uw; + + /* adjust starting point for first char */ + x -= sc * uw/2.0; + y -= sc * 0.5; + + for (i = 0; i < n; i++) { + if (show_char(s,is[i],x,y,sc,col)) + return 1; + x += sc * (0.8 + 0.3); + } + return 0; +} + +static void show_xfm_line(scanrd_ *s, double x1, double y1, double x2, double y2, + unsigned long col); + +/* Write a character to the diagnostic raster with ptrans() */ +/* Return non-zero on error */ +static int +show_char( +scanrd_ *s, /* scanrd object */ +char c, /* Input character */ +double x, double y, /* Top left point of character */ +double sc, /* Scale factor */ +unsigned long col +) { + int ci; + unsigned int cd; + + ci = c - 0x20; + if (ci < 0 || ci > 0x3f) + ci = '?' - 0x20; + cd = vfont[ci]; + /* Display each segment */ + if (cd & 0x0001) + show_xfm_line(s, x,y,x+sc*0.4,y,col); + if (cd & 0x0002) + show_xfm_line(s, x+sc*0.4,y,x+sc*0.8,y,col); + if (cd & 0x0004) + show_xfm_line(s, x+sc*0.8,y,x+sc*0.8,y+sc*0.5,col); + if (cd & 0x0008) + show_xfm_line(s, x+sc*0.8,y+sc*0.5,x+sc*0.8,y+sc*1.0,col); + if (cd & 0x0010) + show_xfm_line(s, x+sc*0.8,y+sc*1.0,x+sc*0.4,y+sc*1.0,col); + if (cd & 0x0020) + show_xfm_line(s, x+sc*0.4,y+sc*1.0,x+0.0,y+sc*1.0,col); + if (cd & 0x0040) + show_xfm_line(s, x+0.0,y+sc*1.0,x+0.0,y+sc*0.5,col); + if (cd & 0x0080) + show_xfm_line(s, x+0.0,y+sc*0.5,x+0.0,y+0.0,col); + if (cd & 0x0100) + show_xfm_line(s, x+0.0,y+sc*0.5,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x0200) + show_xfm_line(s, x+sc*0.4,y+sc*0.5,x+sc*0.8,y+sc*0.5,col); + if (cd & 0x0400) + show_xfm_line(s, x+0.0,y+0.0,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x0800) + show_xfm_line(s, x+sc*0.4,y+0.0,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x1000) + show_xfm_line(s, x+sc*0.8,y+0.0,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x2000) + show_xfm_line(s, x+sc*0.8,y+sc*1.0,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x4000) + show_xfm_line(s, x+sc*0.4,y+sc*1.0,x+sc*0.4,y+sc*0.5,col); + if (cd & 0x8000) + show_xfm_line(s, x+0.0,y+sc*1.0,x+sc*0.4,y+sc*0.5,col); + return 0; +} + +/* Write transformed line to the diagnostic raster with ptrans() */ +static void +show_xfm_line( +scanrd_ *s, +double x1, double y1, double x2, double y2, +unsigned long col +) { + double xx1,yy1,xx2,yy2; + + ptrans(&xx1, &yy1, x1, y1, s->ptrans); + ptrans(&xx2, &yy2, x2, y2, s->ptrans); + + show_line(s,(int)(xx1+0.5),(int)(yy1+0.5),(int)(xx2+0.5),(int)(yy2+0.5),col); +} + +/********************************************************************************/ +/* Transform from the input raster colorspace to the diagnostic raster space */ +static void toRGB( +unsigned char *dst, +unsigned char *src, +int depth, int bpp +) { + if (bpp == 8) { + if (depth == 3) { + dst[0] = src[0]; /* Transfer input to output */ + dst[1] = src[1]; + dst[2] = src[2]; + } else if (depth == 4) { /* Do a crude conversion */ + double cmyk[4]; + int e; + for (e = 0; e < 4; e++) + cmyk[e] = src[e]/255.0; + for (e = 0; e < 3; e++) { + cmyk[e] = cmyk[e] * 0.7 + 0.3 * cmyk[3]; + if (cmyk[e] < cmyk[3]) + cmyk[e] = cmyk[3]; + dst[e] = 255 - (int)(cmyk[e] * 255.0 + 0.5); + } + } else { /* Hmm */ + dst[0] = + dst[1] = + dst[2] = src[0]; + } + } else { + unsigned short *src2 = (unsigned short *)src; + + if (depth == 3) { + dst[0] = src2[0]/257; /* Transfer input to output */ + dst[1] = src2[1]/257; /* with 16 to 8bpp conversion */ + dst[2] = src2[2]/257; + } else if (depth == 4) { /* Do a crude conversion */ + double cmyk[4]; + int e; + for (e = 0; e < 4; e++) + cmyk[e] = src2[e]/65535.0; + for (e = 0; e < 3; e++) { + cmyk[e] = cmyk[e] * 0.7 + 0.3 * cmyk[3]; + if (cmyk[e] < cmyk[3]) + cmyk[e] = cmyk[3]; + dst[e] = 255 - (int)(cmyk[e] * 255.0 + 0.5); + } + } else { /* Hmm */ + dst[0] = + dst[1] = + dst[2] = src2[0]/257; + } + } +} + + +/* Convert from XYZ scale 100 to Lab D50 */ +static void XYZ2Lab(double *out, double *in) { + double X = in[0], Y = in[1], Z = in[2]; + double x,y,z,fx,fy,fz; + + x = X/96.42; + y = Y/100.0; + z = Z/82.49; + + if (x > 0.008856451586) + fx = pow(x,1.0/3.0); + else + fx = 7.787036979 * x + 16.0/116.0; + + if (y > 0.008856451586) + fy = pow(y,1.0/3.0); + else + fy = 7.787036979 * y + 16.0/116.0; + + if (z > 0.008856451586) + fz = pow(z,1.0/3.0); + else + fz = 7.787036979 * z + 16.0/116.0; + + out[0] = 116.0 * fy - 16.0; + out[1] = 500.0 * (fx - fy); + out[2] = 200.0 * (fy - fz); +} + +/* Convert from a scanned pixel value to an aproximate Lab value */ +static void pval2Lab(double *out, double *in, int depth) { + double wXYZ[3]; + double XYZ[3]; + int e, j; + + if (depth == 3) { /* Assume RGB */ + + double clrnts[3][3] = { /* Red, Green & Blue XYZ values */ + { 0.412414, 0.212642, 0.019325 }, + { 0.357618, 0.715136, 0.119207 }, + { 0.180511, 0.072193, 0.950770 } + }; + + wXYZ[0] = 0.950543; /* Because we're using sRGB primaries */ + wXYZ[1] = 1.0; /* the white point is D65 */ + wXYZ[2] = 1.089303; + + XYZ[0] = XYZ[1] = XYZ[2] = 0.0; + + for (e = 0; e < 3; e++) { + double v = in[e]/255.0; + + if (v < 0.0) + v = 0.0; + else if (v > 1.0) + v = 1.0; + if (v <= 0.03928) + v /= 12.92; + else + v = pow((0.055 + v)/1.055, 2.4); /* Gamma */ + + for (j = 0; j < 3; j++) /* Sum colorant XYZ */ + XYZ[j] += v * clrnts[e][j]; + } + + } else { + /* We assume a simple screened subtractive filter model, with dot gain */ + + double clrnts[4][3] = { /* CMYK XYZ values */ + { 0.12, 0.18, 0.48 }, + { 0.38, 0.19, 0.20 }, + { 0.76, 0.81, 0.11 }, + { 0.04, 0.04, 0.04 } + }; + + /* start with white */ + XYZ[0] = wXYZ[0] = 0.9642; + XYZ[1] = wXYZ[1] = 1.0; + XYZ[2] = wXYZ[2] = 0.8249; + + /* And filter it out for each component */ + for (e = 0; e < 4; e++) { + double v = in[e]/255.0; + + if (v < 0.0) + v = 0.0; + else if (v > 1.0) + v = 1.0; + v = 1.0 - pow(1.0 - v, 2.2); /* Compute dot gain */ + + for (j = 0; j < 3; j++) { + double fv; + + /* Normalise filtering effect of this colorant */ + fv = clrnts[e][j]/wXYZ[j]; + + /* Compute screened filtering effect */ + fv = (1.0 - v) + v * fv; + + /* Apply filter to our current value */ + XYZ[j] *= fv; + } + } + } + + /* Convert to Lab */ + { + double X = XYZ[0], Y = XYZ[1], Z = XYZ[2]; + double x,y,z,fx,fy,fz; + + x = X/wXYZ[0]; + y = Y/wXYZ[1]; + z = Z/wXYZ[2]; + + if (x > 0.008856451586) + fx = pow(x,1.0/3.0); + else + fx = 7.787036979 * x + 16.0/116.0; + + if (y > 0.008856451586) + fy = pow(y,1.0/3.0); + else + fy = 7.787036979 * y + 16.0/116.0; + + if (z > 0.008856451586) + fz = pow(z,1.0/3.0); + else + fz = 7.787036979 * z + 16.0/116.0; + + out[0] = 116.0 * fy - 16.0; + out[1] = 500.0 * (fx - fy); + out[2] = 200.0 * (fy - fz); + } +} + +/********************************************************************************/ + +static int +scanrd_write_diag(scanrd_ *s) { + int y; + unsigned char *op; + int stride = 3 * s->width; + + if ((s->flags & SI_SHOW_FLAGS) == 0 || s->write_line == NULL) + return 0; + + /* Write out the tiff file */ + for (op = s->out, y = 0; y < s->height; ++y, op += stride) { + if (s->write_line(s->ddata, y, (char *)op)) { + s->errv = SI_DIAG_WRITE_ERR; + sprintf(s->errm,"scanrd: write_line() returned error"); + return 1; + } + } + return 0; +} + diff --git a/scanin/scanrd.h b/scanin/scanrd.h new file mode 100644 index 0000000..9507981 --- /dev/null +++ b/scanin/scanrd.h @@ -0,0 +1,125 @@ + +/* + * Argyll Color Correction System + * + * Scanrd: Scan chart reader + * This is the core chart recognition code. + * + * Author: Graeme W. Gill + * Date: 28/9/96 + * + * Copyright 1995, 1996, 2008, Graeme W. Gill + * All rights reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +/* + * Public Interface and object file for scanrd.c + */ + +/* Operation flags */ +#define SI_BUILD_REF 0x10000 /* Build the reference file */ +#define SI_PERSPECTIVE 0x20000 /* Allow perspective correction */ +#define SI_GENERAL_ROT 0x40000 /* Allow general rotation, else assume zero degrees */ +#define SI_ASISIFFAIL 0x80000 /* Read patch values "as is" if everything else failes */ + +/* Scanrd diagnostic flags */ +#define SI_SHOW_FLAGS 0xffff /* Mask for all SHOW flags */ +#define SI_SHOW_IMAGE 0x0001 /* Show B&W version of input image in output */ +#define SI_SHOW_DIFFSH 0x0002 /* Show the horizontal edges detected */ +#define SI_SHOW_DIFFSV 0x0004 /* Show the vertical edges detected */ +#define SI_SHOW_GROUPS 0x0008 /* Show the groups detected */ +#define SI_SHOW_LINES 0x0010 /* Show the lines detected */ +#define SI_SHOW_PERS 0x0020 /* Show the lines un-perspective */ +#define SI_SHOW_ROT 0x0040 /* Show the lines rotated */ +#define SI_SHOW_IMPL 0x0080 /* Show the lines used for improvements */ +#define SI_SHOW_ALL_LINES 0x0100 /* Show all lines, valid and invalid */ +#define SI_SHOW_SBOX 0x0200 /* Show aligned sample box info in diagnostic raster */ +#define SI_SHOW_SBOX_OUTLINES 0x0400 /* Show the sample box outlines */ +#define SI_SHOW_SBOX_NAMES 0x0800 /* Show sample boxes names */ +#define SI_SHOW_SBOX_AREAS 0x1000 /* Show sample boxes sample areas */ +#define SI_SHOW_SAMPLED_AREA 0x2000 /* Show pixels areas sampled */ + +/* Error flags */ +#define SI_QUAL_ERR(flag) ((flag & 0xf0000000) == 0) +#define SI_FIND_PERSPECTIVE_FAILED 0x00000001 +#define SI_FIND_ROTATION_FAILED 0x00000002 +#define SI_POOR_MATCH 0x00000003 + +#define SI_FILE_ERR(flag) ((flag & 0xf0000000) == 0x10000000) +#define SI_RAST_READ_ERR 0x10000001 +#define SI_DIAG_WRITE_ERR 0x10000002 +#define SI_REF_WRITE_ERR 0x10000003 +#define SI_REF_READ_ERR 0x10000004 +#define SI_REF_FORMAT_ERR 0x10000005 +#define SI_PIX_DEPTH_ERR 0x10000006 +#define SI_BIT_DEPTH_ERR 0x10000007 +#define SI_NO_FIDUCIALS_ERR 0x10000008 +#define SI_BAD_FIDUCIALS_ERR 0x10000009 /* Not really file error */ + +#define SI_MALLOC_ERR(flag) ((flag & 0xf0000000) == 0x80000000) +#define SI_MALLOC_DIAG_RAST 0x80000001 +#define SI_MALLOC_INPUT_BUF 0x80000002 +#define SI_MALLOC_POINT2LINE 0x80000003 +#define SI_MALLOC_ELIST 0x80000004 +#define SI_MALLOC_REFREAD 0x80000005 +#define SI_MALLOC_SETUP_BOXES 0x80000006 +#define SI_MALLOC_VALUE_SCAN 0x80000007 +#define SI_MALLOC_VREGION 0x80000008 +#define SI_MALLOC_POINTS 0x80000009 +#define SI_REALLOC_POINTS 0x8000000A +#define SI_MALLOC_AAINIT 0x8000000B + +#define SI_INTERNAL_ERR(flag) ((flag & 0xf0000000) == 0xA0000000) +#define SI_INTERNAL 0xA0000001 + +/* The public scanrd object */ +struct _scanrd { + /*** Public methods ***/ + /* Initialise, ready to read out all the values */ + /* return the total number of values */ + int (*reset)(struct _scanrd *s); + + /* Read the next samples values */ + /* return non-zero when no more points */ + int (*read)(struct _scanrd *s, + char *id, /* patch id copied to here */ + double *P, /* Robust mean values */ + double *mP, /* Raw Mean values */ + double *sdP, /* Standard deviation */ + int *cnt); /* Pixel count */ + + /* Return the error flag, and set the message pointer */ + unsigned int (*error)(struct _scanrd *s, char **errm); + + /* Free up the structure */ + void (*free)(struct _scanrd *s); + + }; typedef struct _scanrd scanrd; + + +/* Read in a chart */ +/* Then use reset() and read() to get values read */ +scanrd *do_scanrd( + int flags, /* option flags */ + int verb, /* verbosity level */ + + double gamma, /* Approximate gamma encoding of image (0.0 = default 1.7) */ + + double *sfid, /* Specified fiducuals x1,y1, x2,y2, x3,y3, x4,y4, */ + /* Typically clockwise from top left, NULL if auto recognition */ + + int w, int h, /* Width and Height of input raster in pixels */ + int d, int td, int p, /* Useful plane depth, Total depth, Bit presision of input pixels */ + + int (*read_line)(void *fdata, int y, char *dst), /* Read pixel interleaved line of source */ + void *fdata, /* Opaque data for read_line */ + + char *refname, /* reference file name */ + + int (*write_line)(void *ddata, int y, char *src), /* Write 8bpp RGB line of diag file */ + void *ddata /* Opaque data for write_line */ +); + + diff --git a/scanin/scanrd_.h b/scanin/scanrd_.h new file mode 100644 index 0000000..52d6368 --- /dev/null +++ b/scanin/scanrd_.h @@ -0,0 +1,321 @@ + +/* + * Argyll Color Correction System + * + * Scanrd: Scan chart reader + * This is the core chart recognition code. + * Private H file for scanrd.c + * + * Author: Graeme W. Gill + * Date: 28/9/96 + * + * Copyright 1995, 1996, 2008, Graeme W. Gill + * All rights reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +#include "scanrd.h" /* Include public structure */ + +#include "../h/llist.h" /* Linked list macros */ + +#ifndef M_PI +#define M_PI 3.1415926535897932384626433832795028841971693993751 +#endif +#ifndef M_PI_2 +#define M_PI_2 (0.5 * M_PI) +#endif +#ifndef M_PI_4 +#define M_PI_4 (0.25 * M_PI) +#endif +#ifndef M_PI_3_4 +#define M_PI_3_4 (0.75 * M_PI) +#endif +#ifndef M_2_PI +#define M_2_PI (2.0/M_PI) +#endif +#ifndef M_SQRT_2 +#define M_SQRT_2 1.4142135623730950488016887242096980785696718753769 +#endif + +#define DEG(aa) ((aa) * 180.0/M_PI) + +#define iabs(a) ((a) < 0 ? -(a) : (a)) + +#define MXDE 4 /* Maximum useful pixel depth */ + +/* A run of points at a given y, in a group */ +typedef struct { + int y,lx,hx; /* Region covers values of lx <= x < hx */ + } run; + +/* Structure to hold the points that may make up a line */ +struct _points { + int no; /* number of coordinates (indexed from ca) */ + int mxno; /* Maximum number that can be allocated from ca */ + run *r; /* point runs array */ + int pn; /* Diagnostic serial no */ + LINKSTRUCT(struct _points); /* Linked list structure */ + + /* Line stats */ + int flag; + int nop; /* Number of points */ + double mw,len; /* mean width, length */ + double mx,my; /* Mean point */ + double a; /* Angle */ + double ca; /* Constrained Angle (constrained to 90 degrees about 0 */ + double x1,y1,x2,y2; /* Start/end point of fitted line */ + + double pmx, pmy; /* Raster (Perspective affected) mean point */ + double px1, py1, px2, py2; /* Raster (Perspective affected) line start/end points */ + struct _points *opt; /* Next in improvement list */ +}; typedef struct _points points; + +#define F_LINESTATS 0x01 /* Line stats valid */ +#define F_VALID 0x02 /* Line passes valid criteria */ +#define F_LONGENOUGH 0x04 /* Line is long enough to be included in angle calc */ +#define F_IMPROVE 0x08 /* Line was used to improve fit */ + +/* Structure to hold an aggregation region description */ +struct _region { + int lx,hx; /* Region covers values of lx <= x < hx */ + points *p; /* Head of points linked list associated with region */ +}; typedef struct _region region; + +/* Structure to hold a 2D real point */ +struct _point { + double x,y; +}; typedef struct _point point; + +/* Structure to hold one entry in an edge list */ +struct _epoint { + double pos; /* Position of entry along edge */ + double len; /* (Maximum normalized) Total length */ + double p1,p2; /* Start and end of line in orthogonal direction */ + double ccount; /* (Maximum normalized) Crossing count */ + struct _points *opt; /* Linked list of feature lines to optimize to */ + int nopt; +}; typedef struct _epoint epoint; + +/* Structure of an edge list */ +struct _elist { + epoint *a; /* Array of edge points */ + int c; /* Count */ + double lennorm; /* Total of max. normalized lengths of edge list */ +}; typedef struct _elist elist; + +#define INIT_ELIST(e) { \ + e.a = NULL; \ + e.c = 0; \ + e.lennorm = 0.0; \ +} + +/* An edge correlation return structure */ +typedef struct { + double cc,off,scale; +} ematch; + + +/* An integer point */ +struct _ipoint { + int x,y; +}; typedef struct _ipoint ipoint; + +/* An edge scan structure */ +struct _escan { + int e[4]; /* Indexes of points for left or right sides */ + int i; /* Index of current pair */ + int ev,k1,k2; /* Bresenham constants */ + int y; /* Current y value */ + int xi,x; /* X increment, current x value */ +}; typedef struct _escan escan; + +/* Structure of a sample box */ +#define SBOX_NAME_SZ 20 +struct _sbox { + int diag; /* Non-zero if diagnostic only */ + char name[SBOX_NAME_SZ]; /* Box name (usualy letter number coordinate) */ + double xpt[3]; /* Lab expected value. L < 0 if not valid */ + double x1,y1,x2,y2; /* Reference box corner points */ + ipoint p[4]; /* Transformed sample box coordinates */ + int active; /* Flag to indicate box is active in scan */ + int ymin,ymax; /* Min and nmax y values */ + escan l,r; /* left and right edge scan structures */ + + unsigned long *ps[MXDE]; /* Pixel value histogram arrays (256 or 65536) */ + /* Pixel values just scanned, or from best rotation */ + double mP[MXDE]; /* Mean Pixel values (0.0 - 255.0) */ + double sdP[MXDE]; /* Standard deviations */ + double P[MXDE]; /* Output Pixel values */ + unsigned int cnt; /* Total pixels in cell */ + LINKSTRUCT(struct _sbox); /* Active edge linked list structure */ + + /* Pixel values for alternate rotations, created if we have expected values */ + struct { + double mP[MXDE]; /* Mean Pixel values (0.0 - 255.0) */ + double sdP[MXDE]; /* Standard deviations */ + double P[MXDE]; /* Robust mean Output Pixel values (0.0 .. 255.0) */ + unsigned int cnt; /* Total pixels in cell */ + } rot[4]; + + }; typedef struct _sbox sbox; + +/* The private scanrd object */ +struct _scanrd_ { + /* Public part of structure */ + scanrd public; + + /* Private variables */ + int flags; /* Operation/diagnostic flags */ + int verb; /* verbosity level */ + /* 0 = none */ + /* 1 = warnings */ + /* 2 = minimum */ + /* 3 = per patch */ + /* 3 = patch scan details */ + /* 5 = per line */ + /* 7 = matching attempts */ + /* 8 = per pixel */ + + unsigned int errv; /* Error value */ + char errm[200]; /* Error message */ + + double gammav; /* Approximate gamma encoding of input image */ + int width,height; /* With and height of raster in pixels */ + int depth; /* Useful pixel plane depth */ + int tdepth; /* Total pixel plane depth */ + int bpp; /* Bit precision per pixel, 8 or 16 */ + int bypp; /* Bytes per pixel, either 1 or 2 */ + + unsigned char *out; /* Diagnostic output raster array */ + + int noslines; /* Number of lines with valid stats */ + int novlines; /* Number of valid lines */ + points *gdone; /* Head of done point linked list groups */ + + double ppc[4]; /* Partial perspective correction values. */ + /* persp() applies perspective distortion, */ + /* invpersp() applies perspective correction. */ + + double irot; /* Base image rotation value in radians (clockwize) */ + int norots; /* Number of rotations to explore */ + int crot; /* Current or best rotation being scanned */ + struct { + double irot; /* Image rotation value in radians (clockwize) for this rotation */ + double ixoff,iyoff,ixscale,iyscale; /* Image offset and scale factors */ + double cc; /* Edge match correlation */ + double xcc; /* Expected value correlation, smaller is better */ + } rots[4]; + + double ptrans[8]; /* Combined transform of partial perspective, */ + /* irot, i[xy]off and i[xy]scale. */ + /* Use ptrans(ptrans[]) to transform from reference to raster. */ + double iptrans[8]; /* Inverse transform of ptrans[] */ + /* Use ptrans(iptrans[]) to transform from raster to reference */ + + elist xelist, yelist; /* X and Y raster edge lists array */ + elist ixelist, iyelist; /* Inverted direction X and Y raster edge lists array */ + + elist rxelist, ryelist; /* X and Y .cht reference edge lists array */ + + double rbox_shrink; /* Reference box shrink factor */ + int xpt; /* NZ if got expected reference values */ + + double fid[8]; /* Four fiducial locations, typicall clockwise from top left */ + double fidsize; /* Fiducial diagnostic cross size */ + double havefids; /* NZ if there are fiducials */ + int nsbox; /* Number of sample boxes */ + sbox *sboxes; /* List of sample boxes */ + sbox **sbstart; /* Sorted start list */ + sbox **sbend; /* Sorted end list */ + int csi,cei; /* Current start/end indexes */ + sbox *alist; /* Active list during pixel value sampling */ + + double adivval; /* Overall average divider value */ + int divc; /* Average divide count */ + + int next_read; /* Next box value to read */ + + char *refname; /* Path of reference file */ + + int inited; /* Gamma and regions inited */ + unsigned short gamma[256 * 256]; /* Inverse gamma lookup */ + region *vrego, *vregn; /* Old and New region for delX or vertical lines */ + int no_vo, no_vn; /* Number of regions in array */ + region *hrego, *hregn; /* Old and New region for delY or horizontal lines */ + int no_ho, no_hn; /* Number of regions in array */ + double th; /* Color change threshold */ + double divval; /* Current orthogonal divider value */ + + /* aa line stuff */ + int aa_inited; /* Non-zero if anti-aliased line tables are inited */ + int *coverage; /* Coverage lookup array */ + int covercells; + int covershift; + int Pmax; + int adj_pixinc[4]; /* Pixel address increments for 4 directions */ + int diag_pixinc[4]; + int orth_pixinc[4]; + + /*** Callbacks ***/ + + int (*read_line)(void *fdata, int y, char *dst); + /* Read line of source file, non-zero on error */ + void *fdata; /* Opaque data for callback */ + + int (*write_line)(void *ddata, int y, char *src); + /* Write RGB line of diag file, non-zero on error */ + void *ddata; /* Opaque data for callback */ + +}; typedef struct _scanrd_ scanrd_; + +/*************************************************************************/ +/* Heapsort macro */ + +/* HEAP_COMPARE(A,B) returns true if A < B */ +#define HEAPSORT(TYPE,ARRAY,NUMBER) \ + { \ + TYPE *hs_ncb = ARRAY; \ + int hs_l,hs_j,hs_ir,hs_i; \ + TYPE hs_rra; \ + \ + if (NUMBER >= 2) \ + { \ + hs_l = NUMBER >> 1; \ + hs_ir = NUMBER-1; \ + for (;;) \ + { \ + if (hs_l > 0) \ + hs_rra = hs_ncb[--hs_l]; \ + else \ + { \ + hs_rra = hs_ncb[hs_ir]; \ + hs_ncb[hs_ir] = hs_ncb[0]; \ + if (--hs_ir == 0) \ + { \ + hs_ncb[0] = hs_rra; \ + break; \ + } \ + } \ + hs_i = hs_l; \ + hs_j = hs_l+hs_l+1; \ + while (hs_j <= hs_ir) \ + { \ + if (hs_j < hs_ir && HEAP_COMPARE(hs_ncb[hs_j],hs_ncb[hs_j+1])) \ + hs_j++; \ + if (HEAP_COMPARE(hs_rra,hs_ncb[hs_j])) \ + { \ + hs_ncb[hs_i] = hs_ncb[hs_j]; \ + hs_i = hs_j; \ + hs_j = hs_j+hs_j+1; \ + } \ + else \ + hs_j = hs_ir + 1; \ + } \ + hs_ncb[hs_i] = hs_rra; \ + } \ + } \ + } + +/*************************************************************************/ + -- cgit v1.2.3