home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / pbmplus / patch10dec91 / part04 < prev    next >
Encoding:
Text File  |  1991-12-14  |  55.2 KB  |  1,818 lines

  1. Newsgroups: comp.sources.misc
  2. From: jef@well.sf.ca.us (Jef Poskanzer)
  3. Subject:  v26i109:  pbmplus - Extended Portable Bitmap Toolkit, Patch10dec91, Part04/05
  4. Message-ID: <1991Dec15.014818.20591@sparky.imd.sterling.com>
  5. X-Md4-Signature: dc43b90192afb57db82a35673f079043
  6. Date: Sun, 15 Dec 1991 01:48:18 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jef@well.sf.ca.us (Jef Poskanzer)
  10. Posting-number: Volume 26, Issue 109
  11. Archive-name: pbmplus/patch10dec91/part04
  12. Environment: UNIX
  13. Patch-To: pbmplus: Volume 23, Issue 36-59
  14.  
  15. #!/bin/sh
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file ppm/ppmforge.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 4; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test ! -f _shar_wnt_.tmp; then
  32.     echo 'x - still skipping ppm/ppmforge.c'
  33. else
  34. echo 'x - continuing file ppm/ppmforge.c'
  35. sed 's/^X//' << 'SHAR_EOF' >> 'ppm/ppmforge.c' &&
  36. X        byc = byf + n;
  37. X        t = by - floor(by);
  38. X        t1 = 1 - t;
  39. X    }
  40. X
  41. X    if (clouds) {
  42. X
  43. X        /* Render the FFT output as clouds. */
  44. X
  45. X        for (j = 0; j < screenxsize; j++) {
  46. X        double r = t1 * u1[j] * cp[byf + bxf[j]] +
  47. X               t  * u1[j] * cp[byc + bxf[j]] +
  48. X               t  * u[j]  * cp[byc + bxc[j]] +
  49. X               t1 * u[j]  * cp[byf + bxc[j]];
  50. X        pixval w = (r > 127.0) ? (RGBQuant * ((r - 127.0) / 128.0)) :
  51. X               0;
  52. X
  53. X        PPM_ASSIGN(*(pixels + j), w, w, RGBQuant);
  54. X        }
  55. X    } else if (stars) {
  56. X
  57. X        /* Generate a starry sky.  Note  that no FFT is performed;
  58. X           the output is  generated  directly  from  a  power  law
  59. X           mapping    of  a  pseudorandom sequence into intensities. */
  60. X
  61. X        for (j = 0; j < screenxsize; j++) {
  62. X        etoile(pixels + j);
  63. X        }
  64. X    } else {
  65. X        for (j = 0; j < screenxsize; j++) {
  66. X        PPM_ASSIGN(*(pixels + j), 0, 0, 0);
  67. X        }
  68. X        azimuth = asin(((((double) i) / (screenysize - 1)) * 2) - 1);
  69. X        icet = pow(abs(sin(azimuth)), 1.0 / icelevel) - 0.5;
  70. X        lcos = (screenysize / 2) * abs(cos(azimuth));
  71. X        rpix = pixels + (screenxsize / 2) - lcos;
  72. X        for (j = (screenxsize / 2) - lcos;
  73. X         j <= (screenxsize / 2) + lcos; j++) {
  74. X        double r = t1 * u1[j] * cp[byf + bxf[j]] +
  75. X               t  * u1[j] * cp[byc + bxf[j]] +
  76. X               t  * u[j]  * cp[byc + bxc[j]] +
  77. X               t1 * u[j]  * cp[byf + bxc[j]],
  78. X               ice;
  79. X        int ir, ig, ib;
  80. X        static unsigned char pgnd[][3] = {
  81. X           {206, 205, 0}, {208, 207, 0}, {211, 208, 0},
  82. X           {214, 208, 0}, {217, 208, 0}, {220, 208, 0},
  83. X           {222, 207, 0}, {225, 205, 0}, {227, 204, 0},
  84. X           {229, 202, 0}, {231, 199, 0}, {232, 197, 0},
  85. X           {233, 194, 0}, {234, 191, 0}, {234, 188, 0},
  86. X           {233, 185, 0}, {232, 183, 0}, {231, 180, 0},
  87. X           {229, 178, 0}, {227, 176, 0}, {225, 174, 0},
  88. X           {223, 172, 0}, {221, 170, 0}, {219, 168, 0},
  89. X           {216, 166, 0}, {214, 164, 0}, {212, 162, 0},
  90. X           {210, 161, 0}, {207, 159, 0}, {205, 157, 0},
  91. X           {203, 156, 0}, {200, 154, 0}, {198, 152, 0},
  92. X           {195, 151, 0}, {193, 149, 0}, {190, 148, 0},
  93. X           {188, 147, 0}, {185, 145, 0}, {183, 144, 0},
  94. X           {180, 143, 0}, {177, 141, 0}, {175, 140, 0},
  95. X           {172, 139, 0}, {169, 138, 0}, {167, 137, 0},
  96. X           {164, 136, 0}, {161, 135, 0}, {158, 134, 0},
  97. X           {156, 133, 0}, {153, 132, 0}, {150, 132, 0},
  98. X           {147, 131, 0}, {145, 130, 0}, {142, 130, 0},
  99. X           {139, 129, 0}, {136, 128, 0}, {133, 128, 0},
  100. X           {130, 127, 0}, {127, 127, 0}, {125, 127, 0},
  101. X           {122, 127, 0}, {119, 127, 0}, {116, 127, 0},
  102. X           {113, 127, 0}, {110, 128, 0}, {107, 128, 0},
  103. X           {104, 128, 0}, {102, 127, 0}, { 99, 126, 0},
  104. X           { 97, 124, 0}, { 95, 122, 0}, { 93, 120, 0},
  105. X           { 92, 117, 0}, { 92, 114, 0}, { 92, 111, 0},
  106. X           { 93, 108, 0}, { 94, 106, 0}, { 96, 104, 0},
  107. X           { 98, 102, 0}, {100, 100, 0}, {103,    99, 0},
  108. X           {106,  99, 0}, {109,  99, 0}, {111, 100, 0},
  109. X           {114, 101, 0}, {117, 102, 0}, {120, 103, 0},
  110. X           {123, 102, 0}, {125, 102, 0}, {128, 100, 0},
  111. X           {130,  98, 0}, {132,  96, 0}, {133,    94, 0},
  112. X           {134,  91, 0}, {134,  88, 0}, {134,    85, 0},
  113. X           {133,  82, 0}, {131,  80, 0}, {129,    78, 0}
  114. X        };
  115. X
  116. X        if (r >= 128) {
  117. X            int ix = ((r - 128) * (ELEMENTS(pgnd) - 1)) / 127;
  118. X
  119. X            /* Land area.  Look up colour based on elevation from
  120. X               precomputed colour map table. */
  121. X
  122. X            ir = pgnd[ix][0];
  123. X            ig = pgnd[ix][1];
  124. X            ib = pgnd[ix][2];
  125. X        } else {
  126. X
  127. X            /* Water.  Generate clouds above water based on
  128. X               elevation.  */
  129. X
  130. X            ir = ig = r > 64 ? (r - 64) * 4 : 0;
  131. X            ib = 255;
  132. X        }
  133. X
  134. X        /* Generate polar ice caps. */
  135. X
  136. X        ice = max(0.0, (icet + glaciers * max(-0.5, (r - 128) / 128.0)));
  137. X        if  (ice > 0.125) {
  138. X            ir = ig = ib = 255;
  139. X        }
  140. X
  141. X        /* Apply limb darkening by cosine rule. */
  142. X
  143. X        {   double dx = 2 * (((screenxsize / 2) - j) /
  144. X                ((double) screenysize)),
  145. X               dxsq = dx * dx,
  146. X               ds, di, inx;
  147. X            double dsq, dsat;
  148. X            di = svx * dx + svy + svz * sqrt(1.0 - dxsq);
  149. #define         PlanetAmbient  0.05
  150. X            if (di < 0)
  151. X            di = 0;
  152. X            di = min(1.0, di);
  153. X
  154. X            ds = sqrt(dxsq + dysq);
  155. X            ds = min(1.0, ds);
  156. X
  157. X            /* Calculate  atmospheric absorption  based on the
  158. X               thickness of atmosphere traversed by  light  on
  159. X               its way to the surface. */
  160. X
  161. #define         AtSatFac 1.0
  162. X            dsq = ds * ds;
  163. X            dsat = AtSatFac * ((sqrt(Atthick * Atthick - dsq) -
  164. X                sqrt(1.0 * 1.0 - dsq)) / athfac);
  165. #define         AtSat(x,y) x = ((x)*(1.0-dsat))+(y)*dsat
  166. X            AtSat(ir, 127);
  167. X            AtSat(ig, 127);
  168. X            AtSat(ib, 255);
  169. X
  170. X            inx = PlanetAmbient + (1.0 - PlanetAmbient) * di;
  171. X            ir *= inx;
  172. X            ig *= inx;
  173. X            ib *= inx;
  174. X        }
  175. X
  176. X        PPM_ASSIGN(*rpix, ir, ig, ib);
  177. X        rpix++;
  178. X        }
  179. X
  180. X        /* Left stars */
  181. X
  182. #define StarClose    2
  183. X        for (j = 0; j < (screenxsize / 2) - (lcos + StarClose); j++) {
  184. X        etoile(pixels + j);
  185. X        }
  186. X
  187. X        /* Right stars */
  188. X
  189. X        for (j = (screenxsize / 2) + (lcos + StarClose);
  190. X         j < screenxsize; j++) {
  191. X        etoile(pixels + j);
  192. X        }
  193. X    }
  194. X    ppm_writeppmrow(stdout, pixels, screenxsize, RGBQuant, FALSE);
  195. X    }
  196. X    pm_close(stdout);
  197. X
  198. X    ppm_freerow(pixels);
  199. X    if (!stars) {
  200. X    free((char *) cp);
  201. X    free((char *) u);
  202. X    free((char *) u1);
  203. X    free((char *) bxf);
  204. X    free((char *) bxc);
  205. X    }
  206. }
  207. X
  208. /*  PLANET  --    Make a planet.    */
  209. X
  210. static Boolean planet()
  211. {
  212. X    float *a = (float *) 0;
  213. X    int i, j;
  214. X    double rmin = 1e50, rmax = -1e50, rmean, rrange;
  215. X
  216. X    if (!seedspec) {
  217. X    initseed();
  218. X    }
  219. X    initgauss(rseed);
  220. X
  221. X    if (!stars) {
  222. X
  223. X    spectralsynth(&a, meshsize, 3.0 - fracdim);
  224. X    if (a == (float *) 0) {
  225. X        return FALSE;
  226. X    }
  227. X
  228. X    /* Apply power law scaling if non-unity scale is requested. */
  229. X
  230. X    if (powscale != 1.0) {
  231. X        for (i = 0; i < meshsize; i++) {
  232. X        for (j = 0; j < meshsize; j++) {
  233. X           double r = Real(a, i, j);
  234. X
  235. X            if (r > 0) {
  236. X            Real(a, i, j) = pow(r, powscale);
  237. X            }
  238. X        }
  239. X        }
  240. X    }
  241. X
  242. X    /* Compute extrema for autoscaling. */
  243. X
  244. X    for (i = 0; i < meshsize; i++) {
  245. X        for (j = 0; j < meshsize; j++) {
  246. X        double r = Real(a, i, j);
  247. X
  248. X        rmin = min(rmin, r);
  249. X        rmax = max(rmax, r);
  250. X        }
  251. X    }
  252. X    rmean = (rmin + rmax) / 2;
  253. X    rrange = (rmax - rmin) / 2;
  254. X    for (i = 0; i < meshsize; i++) {
  255. X        for (j = 0; j < meshsize; j++) {
  256. X        Real(a, i, j) = (Real(a, i, j) - rmean) / rrange;
  257. X        }
  258. X    }
  259. X    }
  260. X    genplanet(a, meshsize);
  261. X    if (a != (float *) 0) {
  262. X    free((char *) a);
  263. X    }
  264. X    return TRUE;
  265. }
  266. X
  267. /*  MAIN  --  Main program.  */
  268. X
  269. int main(argc, argv)
  270. X  int argc;
  271. X  char *argv[];
  272. {
  273. X    int i;
  274. X    char *usage = "\n\
  275. X      [-width|-xsize <x>] [-height|-ysize <y>] [-mesh <n>]\n\
  276. X      [-clouds] [-dimension <f>] [-power <f>] [-seed <n>]\n\
  277. X      [-hour <f>] [-inclination|-tilt <f>] [-ice <f>] [-glaciers <f>]\n\
  278. X      [-night] [-stars <n>] [-saturation <n>]";
  279. X    Boolean dimspec = FALSE, meshspec = FALSE, powerspec = FALSE,
  280. X        widspec = FALSE, hgtspec = FALSE, icespec = FALSE,
  281. X        glacspec = FALSE, starspec = FALSE, starcspec = FALSE;
  282. X
  283. X    ppm_init(&argc, argv);
  284. X    i = 1;
  285. X    while ((i < argc) && (argv[i][0] == '-') && (argv[i][1] != '\0')) {
  286. X
  287. X        if (pm_keymatch(argv[i], "-clouds", 2)) {
  288. X        clouds = TRUE;
  289. X        } else if (pm_keymatch(argv[i], "-night", 2)) {
  290. X        stars = TRUE;
  291. X        } else if (pm_keymatch(argv[i], "-dimension", 2)) {
  292. X        if (dimspec) {
  293. X                pm_error("already specified a dimension");
  294. X        }
  295. X        i++;
  296. X            if ((i == argc) || (sscanf(argv[i], "%lf", &fracdim)  != 1))
  297. X        pm_usage(usage);
  298. X        if (fracdim <= 0.0) {
  299. X                pm_error("fractal dimension must be greater than 0");
  300. X        }
  301. X        dimspec = TRUE;
  302. X        } else if (pm_keymatch(argv[i], "-hour", 3)) {
  303. X        if (hourspec) {
  304. X                pm_error("already specified an hour");
  305. X        }
  306. X        i++;
  307. X            if ((i == argc) || (sscanf(argv[i], "%lf", &hourangle) != 1))
  308. X        pm_usage(usage);
  309. X         hourangle = (M_PI / 12.0) * (hourangle + 12.0);
  310. X         hourspec = TRUE;
  311. X        } else if (pm_keymatch(argv[i], "-inclination", 3) ||
  312. X                   pm_keymatch(argv[i], "-tilt", 2)) {
  313. X        if (inclspec) {
  314. X                pm_error("already specified an inclination/tilt");
  315. X        }
  316. X        i++;
  317. X            if ((i == argc) || (sscanf(argv[i], "%lf", &inclangle) != 1))
  318. X        pm_usage(usage);
  319. X        inclangle = (M_PI / 180.0) * inclangle;
  320. X        inclspec = TRUE;
  321. X        } else if (pm_keymatch(argv[i], "-mesh", 2)) {
  322. X        unsigned int j;
  323. X
  324. X        if (meshspec) {
  325. X                pm_error("already specified a mesh size");
  326. X        }
  327. X        i++;
  328. X            if ((i == argc) || (sscanf(argv[i], "%d", &meshsize) != 1))
  329. X        pm_usage(usage);
  330. X
  331. X        /* Force FFT mesh to the next larger power of 2. */
  332. X
  333. X        for (j = meshsize; (j & 1) == 0; j >>= 1) ;
  334. X
  335. X        if (j != 1) {
  336. X        for (j = 2; j < meshsize; j <<= 1) ;
  337. X        meshsize = j;
  338. X        }
  339. X        meshspec = TRUE;
  340. X        } else if (pm_keymatch(argv[i], "-power", 2)) {
  341. X        if (powerspec) {
  342. X                pm_error("already specified a power factor");
  343. X        }
  344. X        i++;
  345. X            if ((i == argc) || (sscanf(argv[i], "%lf", &powscale) != 1))
  346. X        pm_usage(usage);
  347. X        if (powscale <= 0.0) {
  348. X                pm_error("power factor must be greater than 0");
  349. X        }
  350. X        powerspec = TRUE;
  351. X        } else if (pm_keymatch(argv[i], "-ice", 3)) {
  352. X        if (icespec) {
  353. X                pm_error("already specified ice cap level");
  354. X        }
  355. X        i++;
  356. X            if ((i == argc) || (sscanf(argv[i], "%lf", &icelevel) != 1))
  357. X        pm_usage(usage);
  358. X        if (icelevel <= 0.0) {
  359. X                pm_error("ice cap level must be greater than 0");
  360. X        }
  361. X        icespec = TRUE;
  362. X        } else if (pm_keymatch(argv[i], "-glaciers", 2)) {
  363. X        if (glacspec) {
  364. X                pm_error("already specified glacier level");
  365. X        }
  366. X        i++;
  367. X            if ((i == argc) || (sscanf(argv[i], "%lf", &glaciers) != 1))
  368. X        pm_usage(usage);
  369. X        if (glaciers <= 0.0) {
  370. X                pm_error("glacier level must be greater than 0");
  371. X        }
  372. X        glacspec = TRUE;
  373. X        } else if (pm_keymatch(argv[i], "-stars", 3)) {
  374. X        if (starspec) {
  375. X                pm_error("already specified a star fraction");
  376. X        }
  377. X        i++;
  378. X            if ((i == argc) || (sscanf(argv[i], "%d", &starfraction) != 1))
  379. X        pm_usage(usage);
  380. X        starspec = TRUE;
  381. X        } else if (pm_keymatch(argv[i], "-saturation", 3)) {
  382. X        if (starcspec) {
  383. X                pm_error("already specified a star colour saturation");
  384. X        }
  385. X        i++;
  386. X            if ((i == argc) || (sscanf(argv[i], "%d", &starcolour) != 1))
  387. X        pm_usage(usage);
  388. X        starcspec = TRUE;
  389. X        } else if (pm_keymatch(argv[i], "-seed", 3)) {
  390. X        if (seedspec) {
  391. X                pm_error("already specified a random seed");
  392. X        }
  393. X        i++;
  394. X            if ((i == argc) || (sscanf(argv[i], "%d", &rseed) != 1))
  395. X        pm_usage(usage);
  396. X        seedspec = TRUE;
  397. X        } else if (pm_keymatch(argv[i], "-xsize", 2) ||
  398. X                   pm_keymatch(argv[i], "-width", 2)) {
  399. X        if (widspec) {
  400. X                pm_error("already specified a width/xsize");
  401. X        }
  402. X        i++;
  403. X            if ((i == argc) || (sscanf(argv[i], "%d", &screenxsize) != 1))
  404. X        pm_usage(usage);
  405. X        widspec = TRUE;
  406. X        } else if (pm_keymatch(argv[i], "-ysize", 2) ||
  407. X                   pm_keymatch(argv[i], "-height", 3)) {
  408. X        if (hgtspec) {
  409. X                pm_error("already specified a height/ysize");
  410. X        }
  411. X        i++;
  412. X            if ((i == argc) || (sscanf(argv[i], "%d", &screenysize) != 1))
  413. X        pm_usage(usage);
  414. X        hgtspec = TRUE;
  415. X    } else {
  416. X        pm_usage(usage);
  417. X    }
  418. X    i++;
  419. X    }
  420. X
  421. X    /* Set defaults when explicit specifications were not given.
  422. X
  423. X       The  default  fractal  dimension  and  power  scale depend upon
  424. X       whether we're generating a planet or clouds. */
  425. X
  426. X    if (!dimspec) {
  427. X    fracdim = clouds ? 2.15 : 2.4;
  428. X    }
  429. X    if (!powerspec) {
  430. X    powscale = clouds ? 0.75 : 1.2;
  431. X    }
  432. X    if (!icespec) {
  433. X    icelevel = 0.4;
  434. X    }
  435. X    if (!glacspec) {
  436. X    glaciers = 0.75;
  437. X    }
  438. X    if (!starspec) {
  439. X    starfraction = 100;
  440. X    }
  441. X    if (!starcspec) {
  442. X    starcolour = 125;
  443. X    }
  444. X
  445. X    /* Force  screen to be at least  as wide as it is high.  Long,
  446. X       skinny screens  cause  crashes  because    picture  width    is
  447. X       calculated based on height.  */
  448. X
  449. X    screenxsize = max(screenysize, screenxsize);
  450. X    screenxsize = (screenxsize + 1) & (~1);
  451. X    exit(planet() ? 0 : 1);
  452. }
  453. SHAR_EOF
  454. echo 'File ppm/ppmforge.c is complete' &&
  455. chmod 0664 ppm/ppmforge.c ||
  456. echo 'restore of ppm/ppmforge.c failed'
  457. Wc_c="`wc -c < 'ppm/ppmforge.c'`"
  458. test 27513 -eq "$Wc_c" ||
  459.     echo 'ppm/ppmforge.c: original size 27513, current size' "$Wc_c"
  460. rm -f _shar_wnt_.tmp
  461. fi
  462. # ============= ppm/autocad.h ==============
  463. if test -f 'ppm/autocad.h' -a X"$1" != X"-c"; then
  464.     echo 'x - skipping ppm/autocad.h (File already exists)'
  465.     rm -f _shar_wnt_.tmp
  466. else
  467. > _shar_wnt_.tmp
  468. echo 'x - extracting ppm/autocad.h (Text)'
  469. sed 's/^X//' << 'SHAR_EOF' > 'ppm/autocad.h' &&
  470. X
  471. /* The following table maps the  256 standard AutoCAD colours into RGB
  472. X   values with a Maxval of 255.  These colours are actually derived in
  473. X   an  algorithmic way from the HLS colour system, but it's easier and
  474. X   faster  to  just provide a table than to compute the RGB components
  475. X   on the fly from the colour index. */
  476. X
  477. static unsigned char acadcol[256][3] = {
  478. X    {0, 0, 0}, {255, 0, 0}, {255, 255, 0}, {0, 255, 0}, {0, 255, 255},
  479. X    {0, 0, 255}, {255, 0, 255}, {255, 255, 255}, {255, 255, 255},
  480. X    {255, 255, 255}, {255, 0, 0}, {255, 127, 127}, {165, 0, 0}, {165, 82, 82},
  481. X    {127, 0, 0}, {127, 63, 63}, {76, 0, 0}, {76, 38, 38}, {38, 0, 0},
  482. X    {38, 19, 19}, {255, 63, 0}, {255, 159, 127}, {165, 41, 0}, {165, 103, 82},
  483. X    {127, 31, 0}, {127, 79, 63}, {76, 19, 0}, {76, 47, 38}, {38, 9, 0},
  484. X    {38, 23, 19}, {255, 127, 0}, {255, 191, 127}, {165, 82, 0}, {165, 124, 82},
  485. X    {127, 63, 0}, {127, 95, 63}, {76, 38, 0}, {76, 57, 38}, {38, 19, 0},
  486. X    {38, 28, 19}, {255, 191, 0}, {255, 223, 127}, {165, 124, 0},
  487. X    {165, 145, 82}, {127, 95, 0}, {127, 111, 63}, {76, 57, 0}, {76, 66, 38},
  488. X    {38, 28, 0}, {38, 33, 19}, {255, 255, 0}, {255, 255, 127}, {165, 165, 0},
  489. X    {165, 165, 82}, {127, 127, 0}, {127, 127, 63}, {76, 76, 0}, {76, 76, 38},
  490. X    {38, 38, 0}, {38, 38, 19}, {191, 255, 0}, {223, 255, 127},
  491. X    {124, 165, 0}, {145, 165, 82}, {95, 127, 0}, {111, 127, 63}, {57, 76, 0},
  492. X    {66, 76, 38}, {28, 38, 0}, {33, 38, 19}, {127, 255, 0}, {191, 255, 127},
  493. X    {82, 165, 0}, {124, 165, 82}, {63, 127, 0}, {95, 127, 63}, {38, 76, 0},
  494. X    {57, 76, 38}, {19, 38, 0}, {28, 38, 19}, {63, 255, 0}, {159, 255, 127},
  495. X    {41, 165, 0}, {103, 165, 82}, {31, 127, 0}, {79, 127, 63}, {19, 76, 0},
  496. X    {47, 76, 38}, {9, 38, 0}, {23, 38, 19}, {0, 255, 0}, {127, 255, 127},
  497. X    {0, 165, 0}, {82, 165, 82}, {0, 127, 0}, {63, 127, 63}, {0, 76, 0},
  498. X    {38, 76, 38}, {0, 38, 0}, {19, 38, 19}, {0, 255, 63}, {127, 255, 159},
  499. X    {0, 165, 41}, {82, 165, 103}, {0, 127, 31}, {63, 127, 79}, {0, 76, 19},
  500. X    {38, 76, 47}, {0, 38, 9}, {19, 38, 23}, {0, 255, 127}, {127, 255, 191},
  501. X    {0, 165, 82}, {82, 165, 124}, {0, 127, 63}, {63, 127, 95}, {0, 76, 38},
  502. X    {38, 76, 57}, {0, 38, 19}, {19, 38, 28}, {0, 255, 191}, {127, 255, 223},
  503. X    {0, 165, 124}, {82, 165, 145}, {0, 127, 95}, {63, 127, 111}, {0, 76, 57},
  504. X    {38, 76, 66}, {0, 38, 28}, {19, 38, 33}, {0, 255, 255}, {127, 255, 255},
  505. X    {0, 165, 165}, {82, 165, 165}, {0, 127, 127}, {63, 127, 127}, {0, 76, 76},
  506. X    {38, 76, 76}, {0, 38, 38}, {19, 38, 38}, {0, 191, 255}, {127, 223, 255},
  507. X    {0, 124, 165}, {82, 145, 165}, {0, 95, 127}, {63, 111, 127}, {0, 57, 76},
  508. X    {38, 66, 76}, {0, 28, 38}, {19, 33, 38}, {0, 127, 255}, {127, 191, 255},
  509. X    {0, 82, 165}, {82, 124, 165}, {0, 63, 127}, {63, 95, 127}, {0, 38, 76},
  510. X    {38, 57, 76}, {0, 19, 38}, {19, 28, 38}, {0, 63, 255}, {127, 159, 255},
  511. X    {0, 41, 165}, {82, 103, 165}, {0, 31, 127}, {63, 79, 127}, {0, 19, 76},
  512. X    {38, 47, 76}, {0, 9, 38}, {19, 23, 38}, {0, 0, 255}, {127, 127, 255},
  513. X    {0, 0, 165}, {82, 82, 165}, {0, 0, 127}, {63, 63, 127}, {0, 0, 76},
  514. X    {38, 38, 76}, {0, 0, 38}, {19, 19, 38}, {63, 0, 255}, {159, 127, 255},
  515. X    {41, 0, 165}, {103, 82, 165}, {31, 0, 127}, {79, 63, 127}, {19, 0, 76},
  516. X    {47, 38, 76}, {9, 0, 38}, {23, 19, 38}, {127, 0, 255}, {191, 127, 255},
  517. X    {82, 0, 165}, {124, 82, 165}, {63, 0, 127}, {95, 63, 127}, {38, 0, 76},
  518. X    {57, 38, 76}, {19, 0, 38}, {28, 19, 38}, {191, 0, 255}, {223, 127, 255},
  519. X    {124, 0, 165}, {145, 82, 165}, {95, 0, 127}, {111, 63, 127}, {57, 0, 76},
  520. X    {66, 38, 76}, {28, 0, 38}, {33, 19, 38}, {255, 0, 255}, {255, 127, 255},
  521. X    {165, 0, 165}, {165, 82, 165}, {127, 0, 127}, {127, 63, 127}, {76, 0, 76},
  522. X    {76, 38, 76}, {38, 0, 38}, {38, 19, 38}, {255, 0, 191}, {255, 127, 223},
  523. X    {165, 0, 124}, {165, 82, 145}, {127, 0, 95}, {127, 63, 111}, {76, 0, 57},
  524. X    {76, 38, 66}, {38, 0, 28}, {38, 19, 33}, {255, 0, 127}, {255, 127, 191},
  525. X    {165, 0, 82}, {165, 82, 124}, {127, 0, 63}, {127, 63, 95}, {76, 0, 38},
  526. X    {76, 38, 57}, {38, 0, 19}, {38, 19, 28}, {255, 0, 63}, {255, 127, 159},
  527. X    {165, 0, 41}, {165, 82, 103}, {127, 0, 31}, {127, 63, 79},    {76, 0, 19},
  528. X    {76, 38, 47}, {38, 0, 9}, {38, 19, 23}, {84, 84, 84}, {118, 118, 118},
  529. X    {152, 152, 152}, {186, 186, 186}, {220, 220, 220}, {255, 255, 255}
  530. };
  531. SHAR_EOF
  532. chmod 0664 ppm/autocad.h ||
  533. echo 'restore of ppm/autocad.h failed'
  534. Wc_c="`wc -c < 'ppm/autocad.h'`"
  535. test 4290 -eq "$Wc_c" ||
  536.     echo 'ppm/autocad.h: original size 4290, current size' "$Wc_c"
  537. rm -f _shar_wnt_.tmp
  538. fi
  539. # ============= ppm/ppmtoacad.1 ==============
  540. if test -f 'ppm/ppmtoacad.1' -a X"$1" != X"-c"; then
  541.     echo 'x - skipping ppm/ppmtoacad.1 (File already exists)'
  542.     rm -f _shar_wnt_.tmp
  543. else
  544. > _shar_wnt_.tmp
  545. echo 'x - extracting ppm/ppmtoacad.1 (Text)'
  546. sed 's/^X//' << 'SHAR_EOF' > 'ppm/ppmtoacad.1' &&
  547. .TH ppmtoacad 1 "10 October 1991"
  548. .IX ppmtoacad
  549. .IX AutoCAD
  550. .SH NAME
  551. ppmtoacad - convert portable pixmap to AutoCAD database or slide
  552. .SH SYNOPSIS
  553. .na
  554. .B ppmtoacad
  555. 'in 15n
  556. .RB [ -dxb ]
  557. .RB [ -poly ]
  558. .RB [ -background
  559. .IR colour ]
  560. .RB [ -white ]
  561. .RB [ -aspect
  562. .IR ratio ]
  563. .RB [ -8 ]
  564. .RI [ ppmfile ]
  565. .in -15n
  566. .ad
  567. .SH DESCRIPTION
  568. Reads a portable pixmap as input.  Produces an AutoCAD\*R slide file or
  569. binary database import (.dxb) file as output.
  570. If no
  571. .I ppmfile
  572. is specified, input is read from standard input.
  573. .SH OPTIONS
  574. .TP
  575. .B -dxb
  576. An AutoCAD binary database import (.dxb) file is written.  This file
  577. is read with the DXBIN command and, once loaded, becomes part of
  578. the AutoCAD geometrical database and can be viewed and edited like
  579. any other object.  Each sequence of identical pixels becomes a
  580. separate object in the database; this can result in very large AutoCAD
  581. drawing files.  However, if you want to trace over a bitmap, it lets
  582. you zoom and pan around the bitmap as you wish.
  583. .TP
  584. .B -poly
  585. If the
  586. .B -dxb
  587. option is not specified, the output of
  588. .B ppmtoacad
  589. is an AutoCAD slide file.  Normally each row of pixels is
  590. represented by an AutoCAD line entity.  If
  591. .B -poly
  592. is selected, the pixels are rendered as filled polygons.  If the
  593. slide is viewed on a display with higher resolution than the source
  594. pixmap, this will cause the pixels to expand instead of appearing as
  595. discrete lines against the screen background colour.  Regrettably,
  596. this representation yields slide files which occupy more disc space
  597. and take longer to display.
  598. .TP
  599. .BI -background " colour"
  600. Most AutoCAD display drivers can be configured to use any available
  601. colour as the screen background.  Some users perfer a black screen
  602. background, others white, while splinter groups advocate burnt ocher,
  603. tawny puce, and shocking grey.  Discarding pixels whose closest
  604. AutoCAD colour representation is equal to the background colour can
  605. substantially reduce the size of the AutoCAD database or slide file
  606. needed to represent a bitmap.  If no
  607. .B -background
  608. colour is specified, the screen background colour is assumed to be
  609. black.  Any AutoCAD colour number may be specified as the screen
  610. background; colour numbers are assumed to specify the hues defined
  611. in the standard AutoCAD 256 colour palette.
  612. .TP
  613. .B -white
  614. Since many AutoCAD users choose a white screen background, this option
  615. is provided as a short-cut.  Specifying
  616. .B -white
  617. is identical in effect to
  618. .BR "-background 7" .
  619. .TP
  620. .BI -aspect " ratio"
  621. If the source pixmap had non-square pixels, the ratio of the pixel
  622. width to pixel height should be specified as
  623. .IR ratio .
  624. The resulting slide or .dxb file will be corrected so that pixels on
  625. the AutoCAD screen will be square.  For example, to correct an image made
  626. for a 320x200 VGA/MCGA screen, specify
  627. .BR "-aspect 0.8333" .
  628. .TP
  629. .B -8
  630. Restricts the colours in the output file to the 8 RGB shades.
  631. .PP
  632. All flags can be abbreviated to their shortest unique prefix.
  633. .SH BUGS
  634. AutoCAD has a fixed palette of 256 colours, distributed along the hue,
  635. lightness, and saturation axes.  Pixmaps which contain many
  636. nearly-identical colours, or colours not closely approximated by
  637. AutoCAD's palette, may be poorly rendered.
  638. .PP
  639. .B ppmtoacad
  640. works best if the system displaying its output supports the full 256
  641. colour AutoCAD palette.  Monochrome, 8 colour, and 16 colour
  642. configurations will produce less than optimal results.
  643. .PP
  644. When creating a .dxb file or a slide file with the
  645. .B -poly
  646. option,
  647. .B ppmtoacad
  648. finds both vertical and horizontal runs of identical pixels and
  649. consolidates them into rectangular regions to reduce the size of the
  650. output file.  This is effective for images with large areas of
  651. constant colour but it's no substitute for true raster to vector
  652. conversion.  In particular, thin diagonal lines are not optimised at
  653. all by this process.
  654. .PP
  655. Output files can be huge.
  656. .SH "SEE ALSO"
  657. AutoCAD Reference Manual:
  658. .I Slide File Format
  659. and
  660. .IR "Binary Drawing Interchange (DXB) Files" ,
  661. .BR ppm (5)
  662. .SH AUTHOR
  663. .RS 5
  664. .nf
  665. John Walker
  666. Autodesk SA
  667. Avenue des Champs-Montants 14b
  668. CH-2074 MARIN
  669. Suisse/Schweiz/Svizzera/Svizra/Switzerland
  670. .PD 0
  671. .TP 9
  672. Usenet:
  673. kelvin@Autodesk.com
  674. .TP
  675. Fax:
  676. 038/33 88 15
  677. .TP
  678. Voice:
  679. 038/33 76 33
  680. .fi
  681. .RE
  682. .PD
  683. .PP
  684. Permission to use, copy, modify, and distribute this software and its
  685. documentation for any purpose and without fee is hereby granted,
  686. without any conditions or restrictions.  This software is provided ``as
  687. is'' without express or implied warranty.
  688. .PP
  689. AutoCAD and Autodesk are registered trademarks of Autodesk, Inc.
  690. SHAR_EOF
  691. chmod 0664 ppm/ppmtoacad.1 ||
  692. echo 'restore of ppm/ppmtoacad.1 failed'
  693. Wc_c="`wc -c < 'ppm/ppmtoacad.1'`"
  694. test 4541 -eq "$Wc_c" ||
  695.     echo 'ppm/ppmtoacad.1: original size 4541, current size' "$Wc_c"
  696. rm -f _shar_wnt_.tmp
  697. fi
  698. # ============= ppm/ppmtoacad.c ==============
  699. if test -f 'ppm/ppmtoacad.c' -a X"$1" != X"-c"; then
  700.     echo 'x - skipping ppm/ppmtoacad.c (File already exists)'
  701.     rm -f _shar_wnt_.tmp
  702. else
  703. > _shar_wnt_.tmp
  704. echo 'x - extracting ppm/ppmtoacad.c (Text)'
  705. sed 's/^X//' << 'SHAR_EOF' > 'ppm/ppmtoacad.c' &&
  706. /*
  707. X
  708. X      Convert a portable pixmap to an AutoCAD slide or DXB file
  709. X
  710. X    Author:
  711. X        John Walker
  712. X        Autodesk SA
  713. X        Avenue des Champs-Montants 14b
  714. X        CH-2074 MARIN
  715. X        Switzerland
  716. X        Usenet: kelvin@Autodesk.com
  717. X        Fax:    038/33 88 15
  718. X        Voice:  038/33 76 33
  719. X
  720. X    Permission    to  use, copy, modify, and distribute this software and
  721. X    its documentation  for  any  purpose  and  without    fee  is  hereby
  722. X    granted,  without any conditions or restrictions.  This software is
  723. X    provided "as is" without express or implied warranty.
  724. X
  725. */
  726. X
  727. #include <stdio.h>
  728. #include "ppm.h"
  729. #include "ppmcmap.h"
  730. X
  731. #define TRUE     1
  732. #define FALSE     0
  733. X
  734. #define EOS     '\0'
  735. X
  736. #define MAXHIST     32767          /* Colour histogram maximum size */
  737. X
  738. static pixel **pixels;              /* Input pixel map */
  739. static colorhash_table cht;          /* Colour hash table */
  740. static int curcol = -1;           /* Current slide output colour */
  741. static int polymode = FALSE;          /* Output filled polygons ? */
  742. static int dxbmode = FALSE;          /* Output .dxb format ? */
  743. static int bgcol = -1;              /* Screen background colour */
  744. static double aspect = 1.0;          /* Pixel aspect ratio correction */
  745. static int gamut = 256;           /* Output colour gamut */
  746. X
  747. #include "autocad.h"                  /* AutoCAD standard colour assignments */
  748. X
  749. /*  OUTRUN  --    Output a run of pixels. */
  750. X
  751. static void outrun(colour, ysize, y, xstart, xend)
  752. X  int colour, ysize, y, xstart, xend;
  753. {
  754. X    if (colour == 0) {
  755. X    return;               /* Let screen background handle this */
  756. X    }
  757. X
  758. X    if (curcol != colour) {
  759. X    if (dxbmode) {
  760. X        putchar(136);
  761. X        (void) pm_writelittleshort(stdout, colour);
  762. X    } else {
  763. X        (void) pm_writelittleshort(stdout, 0xFF00 | colour);
  764. X    }
  765. X    curcol = colour;
  766. X    }
  767. X    if (polymode) {
  768. X    int v, yb = (ysize - y) + 1, yspan = 1;
  769. X
  770. X        /* Since  we're emitting filled polygons,  let's scan downward
  771. X       in the pixmap and see if we can extend the run on this line
  772. X       vertically  as  well.   If  so, emit a polygon that handles
  773. X       both the horizontal and vertical run and clear  the    pixels
  774. X       in the subsequent lines to the background colour. */
  775. X
  776. X    for (v = y + 1; v <= ysize; v++) {
  777. X        int j, mismatch = FALSE;
  778. X
  779. X        for (j = xstart; j <= xend; j++) {
  780. X        if (PPM_GETR(pixels[y][j]) != PPM_GETR(pixels[v][j])) {
  781. X            mismatch = TRUE;
  782. X            break;
  783. X        }
  784. X        }
  785. X        if (mismatch) {
  786. X        break;
  787. X        }
  788. X        for (j = xstart; j <= xend; j++) {
  789. X        PPM_ASSIGN(pixels[v][j], 0, 0, 0);
  790. X        }
  791. X    }
  792. X    yspan = v - y;
  793. X
  794. X    if (dxbmode) {
  795. X        putchar(11);          /* Solid */
  796. X        (void) pm_writelittleshort(
  797. X        stdout, (int) (xstart * aspect + 0.4999));
  798. X        (void) pm_writelittleshort(stdout, yb);
  799. X
  800. X        (void) pm_writelittleshort(
  801. X        stdout, (int) ((xend + 1) * aspect + 0.4999));
  802. X        (void) pm_writelittleshort(stdout, yb);
  803. X
  804. X        (void) pm_writelittleshort(
  805. X        stdout, (int) (xstart * aspect + 0.4999));
  806. X        (void) pm_writelittleshort(stdout, yb - yspan);
  807. X
  808. X        (void) pm_writelittleshort(
  809. X        stdout, (int) ((xend + 1) * aspect + 0.4999));
  810. X        (void) pm_writelittleshort(stdout, yb - yspan);
  811. X    } else {
  812. X        (void) pm_writelittleshort(stdout, 0xFD00); /* Solid fill header */
  813. X        (void) pm_writelittleshort(stdout, 4);      /* Vertices to follow */
  814. X        (void) pm_writelittleshort(stdout, -2);     /* Fill type */
  815. X
  816. X        (void) pm_writelittleshort(stdout, 0xFD00); /* Solid fill vertex */
  817. X        (void) pm_writelittleshort(stdout, xstart);
  818. X        (void) pm_writelittleshort(stdout, yb);
  819. X
  820. X        (void) pm_writelittleshort(stdout, 0xFD00); /* Solid fill vertex */
  821. X        (void) pm_writelittleshort(stdout, xend + 1);
  822. X        (void) pm_writelittleshort(stdout, yb);
  823. X
  824. X        (void) pm_writelittleshort(stdout, 0xFD00);    /* Solid fill vertex */
  825. X        (void) pm_writelittleshort(stdout, xend + 1);
  826. X        (void) pm_writelittleshort(stdout, yb - yspan);
  827. X
  828. X        (void) pm_writelittleshort(stdout, 0xFD00); /* Solid fill vertex */
  829. X        (void) pm_writelittleshort(stdout, xstart);
  830. X        (void) pm_writelittleshort(stdout, yb - yspan);
  831. X
  832. X        (void) pm_writelittleshort(stdout, 0xFD00);    /* Solid fill trailer */
  833. X        (void) pm_writelittleshort(stdout, 4); /* Vertices that precede */
  834. X        (void) pm_writelittleshort(stdout, -2);     /* Fill type */
  835. X    }
  836. X    } else {
  837. X    (void) pm_writelittleshort(stdout, xstart);     /* Vector:  From X */
  838. X    (void) pm_writelittleshort(stdout, ysize - y);  /*          From Y */
  839. X    (void) pm_writelittleshort(stdout, xend);       /*          To   X */
  840. X    (void) pm_writelittleshort(stdout, ysize - y);  /*          To   Y */
  841. X    }
  842. }
  843. X
  844. /*  SLIDEOUT  --  Write an AutoCAD slide.  */
  845. X
  846. static void slideout(xdots, ydots, ncolours, red, green, blue)
  847. X  int xdots, ydots, ncolours;
  848. X  unsigned char *red, *green, *blue;
  849. {
  850. X    static char sldhead[18] = "AutoCAD Slide\r\n\32";
  851. X    static char dxbhead[20] = "AutoCAD DXB 1.0\r\n\32";
  852. X    unsigned char *acadmap;
  853. X    int i, xsize, ysize;
  854. X
  855. X    /* If the user has specified a non-black screen background colour,
  856. X       swap the screen background colour into colour  index  zero  and
  857. X       move  black into the slot previously occupied by the background
  858. X       colour. */
  859. X
  860. X    if (bgcol > 0) {
  861. X    acadcol[0][0] = acadcol[bgcol][0];
  862. X    acadcol[0][1] = acadcol[bgcol][1];
  863. X    acadcol[0][2] = acadcol[bgcol][2];
  864. X    acadcol[bgcol][0] = acadcol[bgcol][1] = acadcol[bgcol][2] = 0;
  865. X    }
  866. X
  867. X    acadmap = (unsigned char *) pm_allocrow(ncolours, sizeof(unsigned char));
  868. X    xsize = polymode ? xdots : (xdots - 1);
  869. X    ysize = polymode ? ydots : (ydots - 1);
  870. X    if (dxbmode) {
  871. X    fwrite(dxbhead, 19, 1, stdout); /* DXB file header */
  872. X    putchar(135);              /* Number mode */
  873. X    (void) pm_writelittleshort(stdout, 0);          /* ...short integers */
  874. X    } else {
  875. X    fwrite(sldhead, 17, 1, stdout); /* Slide file header */
  876. X    putchar(86);              /* Number format indicator */
  877. X    putchar(2);              /* File level number */
  878. X    (void) pm_writelittleshort(stdout, xsize); /* Max X co-ordinate value */
  879. X    (void) pm_writelittleshort(stdout, ysize); /* Max Y co-ordinate value */
  880. X                      /* Aspect ratio indicator */
  881. X    (void) pm_writelittlelong(
  882. X        stdout, (long) ((((double) xsize) / ysize) * aspect * 1E7));
  883. X    (void) pm_writelittleshort(stdout, 2);          /* Polygon fill type */
  884. X    (void) pm_writelittleshort(stdout, 0x1234);   /* Byte order indicator */
  885. X    }
  886. X
  887. X    /* Now  build  a  mapping  from  the  image's computed colour map
  888. X       indices to the closest representation  of  each    colour    within
  889. X       AutoCAD's colour repertoire. */
  890. X
  891. X    for (i = 0; i < ncolours; i++) {
  892. X    int best, j;
  893. X    long dist = 3 * 256 * 256;
  894. X
  895. X    for (j = 0; j < gamut; j++) {
  896. X        long dr = red[i] - acadcol[j][0],
  897. X         dg = green[i] - acadcol[j][1],
  898. X         db = blue[i] - acadcol[j][2];
  899. X        long tdist = dr * dr + dg * dg + db * db;
  900. X
  901. X        if (tdist < dist) {
  902. X        dist = tdist;
  903. X        best = j;
  904. X        }
  905. X    }
  906. X    acadmap[i] = best;
  907. X    }
  908. X
  909. X    /* Swoop  over the entire map and replace each  RGB pixel with its
  910. X       closest    AutoCAD  colour  representation.   We  do  this  in  a
  911. X       separate  pass  since it avoids repetitive mapping of pixels as
  912. X       we examine them for compression. */
  913. X
  914. X    for (i = 0; i < ydots; i++) {
  915. X    int x;
  916. X
  917. X    for (x = 0; x < xdots; x++) {
  918. X        PPM_ASSIGN(pixels[i][x],
  919. X        acadmap[ppm_lookupcolor(cht, &pixels[i][x])], 0 ,0);
  920. X    }
  921. X    }
  922. X
  923. X    /* Output a run-length encoded expression of the pixmap as AutoCAD
  924. X       vectors. */
  925. X
  926. X    for (i = 0; i < ydots; i++) {
  927. X    int x, rx, rpix = -1, nrun = 0;
  928. X
  929. X    for (x = 0; x < xdots; x++) {
  930. X        int pix = PPM_GETR(pixels[i][x]);
  931. X
  932. X        if (pix != rpix) {
  933. X        if (nrun > 0) {
  934. X            if (rpix > 0) {
  935. X            outrun(rpix, ydots - 1, i, rx, x - 1);
  936. X            }
  937. X        }
  938. X        rpix = pix;
  939. X        rx = x;
  940. X        nrun = 1;
  941. X        }
  942. X    }
  943. X    if ((nrun > 0) && (rpix > 0)) {
  944. X        outrun(rpix, ydots - 1, i, rx, xdots - 1);
  945. X    }
  946. X    }
  947. X    if (dxbmode) {
  948. X    putchar(0);              /* DXB end sentinel */
  949. X    } else {
  950. X    (void) pm_writelittleshort(stdout, 0xFC00); /* End of file marker */
  951. X    }
  952. X    pm_freerow((char *) acadmap);
  953. }
  954. X
  955. /*  Main program.  */
  956. X
  957. int main(argc, argv)
  958. X  int argc;
  959. X  char* argv[];
  960. {
  961. X    FILE *ifp;
  962. X    int argn, rows, cols, ncolours, i;
  963. X    int aspectspec = FALSE;
  964. X    pixval maxval;
  965. X    colorhist_vector chv;
  966. X    unsigned char *Red, *Green, *Blue;
  967. X    char *usage =
  968. X        "[-poly] [-dxb] [-white] [-background <col>]\n\
  969. X                  [-aspect <f>] [-8] [ppmfile]";
  970. X
  971. X    ppm_init(&argc, argv);
  972. X
  973. X    argn = 1;
  974. X    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != EOS) {
  975. X        if (pm_keymatch(argv[argn], "-dxb", 2)) {
  976. X        dxbmode = polymode = TRUE;
  977. X        } else if (pm_keymatch(argv[argn], "-poly", 2)) {
  978. X        polymode = TRUE;
  979. X        } else if (pm_keymatch(argv[argn], "-white", 2)) {
  980. X        if (bgcol >= 0) {
  981. X                pm_error("already specified a background colour");
  982. X        }
  983. X        bgcol = 7;
  984. X        } else if (pm_keymatch(argv[argn], "-background", 2)) {
  985. X        if (bgcol >= 0) {
  986. X                pm_error("already specified a background colour");
  987. X        }
  988. X        argn++;
  989. X            if ((argn == argc) || (sscanf(argv[argn], "%d", &bgcol) != 1))
  990. X        pm_usage(usage);
  991. X        if (bgcol < 0) {
  992. X                pm_error("background colour must be >= 0 and <= 255");
  993. X        }
  994. X        } else if (pm_keymatch(argv[argn], "-aspect", 2)) {
  995. X        if (aspectspec) {
  996. X                pm_error("already specified an aspect ratio");
  997. X        }
  998. X        argn++;
  999. X            if ((argn == argc) || (sscanf(argv[argn], "%lf", &aspect) != 1))
  1000. X        pm_usage(usage);
  1001. X        if (aspect <= 0.0) {
  1002. X                pm_error("aspect ratio must be greater than 0");
  1003. X        }
  1004. X        aspectspec = TRUE;
  1005. X        } else if (pm_keymatch(argv[argn], "-8", 2)) {
  1006. X        gamut = 8;
  1007. X    } else {
  1008. X        pm_usage(usage);
  1009. X    }
  1010. X    argn++;
  1011. X    }
  1012. X
  1013. X    if (argn < argc) {
  1014. X    ifp = pm_openr(argv[argn]);
  1015. X    argn++;
  1016. X    } else {
  1017. X    ifp = stdin;
  1018. X    }
  1019. X
  1020. X    if (argn != argc) {
  1021. X    pm_usage(usage);
  1022. X    }
  1023. X
  1024. X    pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
  1025. X
  1026. X    pm_close(ifp);
  1027. X
  1028. X    /* Figure out the colormap.  Logic for squeezing depth to limit the
  1029. X       number of colours in the image was swiped from ppmquant.c. */
  1030. X
  1031. X    while (TRUE) {
  1032. X    int row, col;
  1033. X    pixval newmaxval;
  1034. X    pixel *pP;
  1035. X
  1036. X        pm_message("computing colourmap...");
  1037. X    chv = ppm_computecolorhist(pixels, cols, rows, MAXHIST, &ncolours);
  1038. X    if (chv != (colorhist_vector) 0)
  1039. X        break;
  1040. X    newmaxval = maxval / 2;
  1041. X    pm_message(
  1042. X        "scaling colours from maxval=%d to maxval=%d to improve clustering...",
  1043. X           maxval, newmaxval );
  1044. X    for (row = 0; row < rows; ++row) {
  1045. X        for (col = 0, pP = pixels[row]; col < cols; ++col, ++pP) {
  1046. X        PPM_DEPTH(*pP, *pP, maxval, newmaxval);
  1047. X        }
  1048. X    }
  1049. X    maxval = newmaxval;
  1050. X    }
  1051. X    pm_message("%d colours found", ncolours);
  1052. X
  1053. X    /* Scale the colour map derived for the PPM file into one compatible
  1054. X       with AutoCAD's convention of 8 bit intensities. */
  1055. X
  1056. X    if (maxval != 255) {
  1057. X        pm_message("maxval is not 255 - automatically rescaling colours");
  1058. X    }
  1059. X    Red = (unsigned char *) pm_allocrow(ncolours, sizeof(unsigned char));
  1060. X    Green = (unsigned char *) pm_allocrow(ncolours, sizeof(unsigned char));
  1061. X    Blue = (unsigned char *) pm_allocrow(ncolours, sizeof(unsigned char));
  1062. X
  1063. X    for (i = 0; i < ncolours; ++i) {
  1064. X    if ( maxval == 255 ) {
  1065. X        Red[i] = PPM_GETR(chv[i].color);
  1066. X        Green[i] = PPM_GETG(chv[i].color);
  1067. X        Blue[i] = PPM_GETB( chv[i].color );
  1068. X    } else {
  1069. X        Red[i] = ((int) PPM_GETR(chv[i].color) * 255) / maxval;
  1070. X        Green[i] = ((int) PPM_GETG(chv[i].color) * 255) / maxval;
  1071. X        Blue[i] = ((int) PPM_GETB(chv[i].color) * 255) / maxval;
  1072. X    }
  1073. X    }
  1074. X
  1075. X    /* And make a hash table for fast lookup. */
  1076. X
  1077. X    cht = ppm_colorhisttocolorhash(chv, ncolours);
  1078. X    ppm_freecolorhist(chv);
  1079. X
  1080. X    slideout(cols, rows, ncolours, Red, Green, Blue);
  1081. X    pm_freerow((char *) Red);
  1082. X    pm_freerow((char *) Green);
  1083. X    pm_freerow((char *) Blue);
  1084. X    exit(0);
  1085. }
  1086. SHAR_EOF
  1087. chmod 0664 ppm/ppmtoacad.c ||
  1088. echo 'restore of ppm/ppmtoacad.c failed'
  1089. Wc_c="`wc -c < 'ppm/ppmtoacad.c'`"
  1090. test 11612 -eq "$Wc_c" ||
  1091.     echo 'ppm/ppmtoacad.c: original size 11612, current size' "$Wc_c"
  1092. rm -f _shar_wnt_.tmp
  1093. fi
  1094. # ============= ppm/sldtoppm.1 ==============
  1095. if test -f 'ppm/sldtoppm.1' -a X"$1" != X"-c"; then
  1096.     echo 'x - skipping ppm/sldtoppm.1 (File already exists)'
  1097.     rm -f _shar_wnt_.tmp
  1098. else
  1099. > _shar_wnt_.tmp
  1100. echo 'x - extracting ppm/sldtoppm.1 (Text)'
  1101. sed 's/^X//' << 'SHAR_EOF' > 'ppm/sldtoppm.1' &&
  1102. .TH sldtoppm 1 "10 October 1991"
  1103. .IX sldtoppm
  1104. .IX AutoCAD
  1105. .SH NAME
  1106. sldtoppm - convert an AutoCAD slide file into a portable pixmap
  1107. .SH SYNOPSIS
  1108. .na
  1109. .B sldtoppm
  1110. 'in 14n
  1111. .RB [ -adjust ]
  1112. .RB [ -dir ]
  1113. .RB [ -height | -ysize
  1114. .IR s ]
  1115. .RB [ -info ]
  1116. .RB [ -lib | -Lib
  1117. .IR name ]
  1118. .RB [ -scale
  1119. .IR s ]
  1120. .RB [ -verbose ]
  1121. .RB [ -width | -xsize
  1122. .IR s ]
  1123. .RI [ slidefile ]
  1124. .in -14n
  1125. .ad
  1126. .SH DESCRIPTION
  1127. Reads an AutoCAD\*R slide file and outputs a portable pixmap.
  1128. If no
  1129. .I slidefile
  1130. is specified, input is read from standard input.
  1131. The ppmdraw library is used to convert the vector and polygon
  1132. information in the slide file to a pixmap; see the file ppmdraw.h for
  1133. details on this package.
  1134. .SH OPTIONS
  1135. .TP
  1136. .B -adjust
  1137. If the display on which the slide file was created had non-square
  1138. pixels, when the slide is processed with
  1139. .B sldtoppm
  1140. and the
  1141. .B -adjust
  1142. option is not present, the following warning will appear:
  1143. .in +.2i
  1144. Warning - pixels on source screen were non-square.
  1145. .br
  1146. Specifying
  1147. .B -adjust
  1148. will correct image width to compensate.
  1149. .in -.2i
  1150. Specifying the
  1151. .B -adjust
  1152. option causes
  1153. .B sldtoppm
  1154. to scale the width of the image so that pixels in the resulting
  1155. portable pixmap are square (and hence circles appear as true circles,
  1156. not ellipses).  The scaling is performed in the vector domain, before
  1157. scan converting the objects.  The results are, therefore, superior in
  1158. appearance to what you'd obtain were you to perform the equivalent
  1159. scaling with
  1160. .B pnmscale
  1161. after the bitmap had been created.
  1162. .TP
  1163. .B -dir
  1164. The input is assumed to be an AutoCAD slide library file.  A directory
  1165. listing each slide in the library is printed on standard error.
  1166. .TP
  1167. .BI -height " size"
  1168. Scales the image in the vector domain so it is
  1169. .I size
  1170. pixels in height.  If no
  1171. .B -width
  1172. or
  1173. .B -xsize
  1174. option is specified, the width will be adjusted to preserve the
  1175. pixel aspect ratio. 
  1176. .TP
  1177. .B -info
  1178. Dump the slide file header on standard error, displaying the original
  1179. screen size and aspect ratio among other information.
  1180. .TP
  1181. .BI -lib " name"
  1182. Extracts the slide with the given
  1183. .I name
  1184. from the slide library given as input.  The specified
  1185. .I name
  1186. is converted to upper case.
  1187. .TP
  1188. .BI -Lib " name"
  1189. Extracts the slide with the given
  1190. .I name
  1191. from the slide library given as input.  The
  1192. .I name
  1193. is used exactly as specified; it is not converted to upper case.
  1194. .TP
  1195. .BI -scale " s"
  1196. Scales the image by factor
  1197. .IR s ,
  1198. which may be any floating point value greater than zero.  Scaling is
  1199. done after aspect ratio adjustment, if any.  Since scaling is
  1200. performed in the vector domain, before rasterisation, the results look
  1201. much better than running the output of
  1202. .B sldtoppm
  1203. through
  1204. .BR pnmscale .
  1205. .TP
  1206. .B -verbose
  1207. Dumps the slide file header and lists every vector and polygon in the
  1208. file on standard error.
  1209. .TP
  1210. .BI -width " size"
  1211. Scales the image in the vector domain so it is
  1212. .I size
  1213. pixels wide.  If no
  1214. .B -height
  1215. or
  1216. .B -ysize
  1217. option is specified, the height will be adjusted to preserve the
  1218. pixel aspect ratio. 
  1219. .TP
  1220. .BI -xsize " size"
  1221. Scales the image in the vector domain so it is
  1222. .I size
  1223. pixels wide.  If no
  1224. .B -height
  1225. or
  1226. .B -ysize
  1227. option is specified, the height will be adjusted to preserve the
  1228. pixel aspect ratio. 
  1229. .TP
  1230. .BI -ysize " size"
  1231. Scales the image in the vector domain so it is
  1232. .I size
  1233. pixels in height.  If no
  1234. .B -width
  1235. or
  1236. .B -xsize
  1237. option is specified, the width will be adjusted to preserve the
  1238. pixel aspect ratio. 
  1239. .PP
  1240. All flags can be abbreviated to their shortest unique prefix.
  1241. .SH BUGS
  1242. Only Level 2 slides are converted.  Level 1 format has been obsolete
  1243. since the advent of AutoCAD Release 9 in 1987, and was not portable
  1244. across machine architectures.
  1245. .PP
  1246. Slide library items with names containing 8 bit (such as ISO) or 16
  1247. bit (Kanji, for example) characters may not be found when chosen with the
  1248. .B -lib
  1249. option unless
  1250. .B sldtoppm
  1251. has been built with character set conversion functions appropriate to
  1252. the locale.  You can always retrieve slides from libraries regardless
  1253. of the character set by using the
  1254. .B -Lib
  1255. option and specifying the precise name of library member.  Use the
  1256. .B -dir
  1257. option to list the slides in a library if you're unsure of the
  1258. exact name.
  1259. .SH "SEE ALSO"
  1260. AutoCAD Reference Manual:
  1261. .IR "Slide File Format" ,
  1262. .BR pnmscale (1),
  1263. .BR ppm (5)
  1264. .SH AUTHOR
  1265. .RS 5
  1266. .nf
  1267. John Walker
  1268. Autodesk SA
  1269. Avenue des Champs-Montants 14b
  1270. CH-2074 MARIN
  1271. Suisse/Schweiz/Svizzera/Svizra/Switzerland
  1272. .PD 0
  1273. .TP 9
  1274. Usenet:
  1275. kelvin@Autodesk.com
  1276. .TP
  1277. Fax:
  1278. 038/33 88 15
  1279. .TP
  1280. Voice:
  1281. 038/33 76 33
  1282. .fi
  1283. .RE
  1284. .PD
  1285. .PP
  1286. Permission to use, copy, modify, and distribute this software and its
  1287. documentation for any purpose and without fee is hereby granted,
  1288. without any conditions or restrictions.  This software is provided ``as
  1289. is'' without express or implied warranty.
  1290. .PP
  1291. AutoCAD and Autodesk are registered trademarks of Autodesk, Inc.
  1292. SHAR_EOF
  1293. chmod 0664 ppm/sldtoppm.1 ||
  1294. echo 'restore of ppm/sldtoppm.1 failed'
  1295. Wc_c="`wc -c < 'ppm/sldtoppm.1'`"
  1296. test 4785 -eq "$Wc_c" ||
  1297.     echo 'ppm/sldtoppm.1: original size 4785, current size' "$Wc_c"
  1298. rm -f _shar_wnt_.tmp
  1299. fi
  1300. # ============= ppm/sldtoppm.c ==============
  1301. if test -f 'ppm/sldtoppm.c' -a X"$1" != X"-c"; then
  1302.     echo 'x - skipping ppm/sldtoppm.c (File already exists)'
  1303.     rm -f _shar_wnt_.tmp
  1304. else
  1305. > _shar_wnt_.tmp
  1306. echo 'x - extracting ppm/sldtoppm.c (Text)'
  1307. sed 's/^X//' << 'SHAR_EOF' > 'ppm/sldtoppm.c' &&
  1308. /*
  1309. X
  1310. X      Convert an AutoCAD slide (.sld) file to PPM format
  1311. X
  1312. X    An AutoCAD slide is a compressed sequence of  vectors  and    filled
  1313. X    polygons.    The  ppmdraw  package  is  used  to scan convert these
  1314. X    geometrical objects into a portable pixmap.
  1315. X
  1316. X    Author:
  1317. X        John Walker
  1318. X        Autodesk SA
  1319. X        Avenue des Champs-Montants 14b
  1320. X        CH-2074 MARIN
  1321. X        Switzerland
  1322. X        Usenet: kelvin@Autodesk.com
  1323. X        Fax:    038/33 88 15
  1324. X        Voice:  038/33 76 33
  1325. X
  1326. X    Permission    to  use, copy, modify, and distribute this software and
  1327. X    its documentation  for  any  purpose  and  without    fee  is  hereby
  1328. X    granted,  without any conditions or restrictions.  This software is
  1329. X    provided "as is" without express or implied warranty.
  1330. X
  1331. */
  1332. X
  1333. #include "ppm.h"
  1334. #include "ppmdraw.h"
  1335. #ifdef DEBUG
  1336. #include <assert.h>
  1337. #else
  1338. #define assert(x)
  1339. #endif
  1340. X
  1341. /*  Define a variable type accepting numbers -127 <= n <= 127.    But note
  1342. X    that we still expect it to act UNSIGNED. */
  1343. X
  1344. #define smallint unsigned char          /* Small integers */
  1345. X
  1346. #define TRUE     1
  1347. #define FALSE     0
  1348. X
  1349. #define EOS     '\0'
  1350. X
  1351. /* Screen point */
  1352. X
  1353. struct spoint {
  1354. X    int x, y;
  1355. };
  1356. X
  1357. /* Screen polygon */
  1358. X
  1359. struct spolygon { 
  1360. X    int npoints,              /* Number of points in polygon */
  1361. X          fill;              /* Fill type */
  1362. X    struct spoint pt[11];          /* Actual points */
  1363. };
  1364. X
  1365. /* Screen vector */
  1366. X
  1367. struct svector {
  1368. X    struct spoint f;          /* From point */
  1369. X    struct spoint t;          /* To point */
  1370. };
  1371. X
  1372. X
  1373. static int ixdots, iydots;          /* Screen size in dots */
  1374. static FILE *slfile;              /* Slide file descriptor */
  1375. static int blither = FALSE;          /* Dump slide file information ? */
  1376. static int info = FALSE;          /* Print header information */
  1377. static pixel **pixels;              /* Pixel map */
  1378. static int pixcols, pixrows;          /* Pixel map size */
  1379. #define pixmaxval 255              /* Largest pixel value */
  1380. static double uscale = -1;          /* Uniform scale factor */
  1381. static int sxsize = -1, sysize = -1;  /* Scale to X, Y size ? */
  1382. X
  1383. #include "autocad.h"                  /* AutoCAD standard colour assignments */
  1384. X
  1385. /*  Local variables  */
  1386. X
  1387. struct slhead {
  1388. X    char slh[17];              /* Primate-readable header */
  1389. X    char sntype;              /* Machine type (for number compat) */
  1390. X    char slevel;              /* Format type */
  1391. X    short sxdots, sydots;          /* Display X, Y dots */
  1392. X    double sdsar;              /* Display aspect ratio */
  1393. X    short shwfill;              /* Display hardware fill type */
  1394. X    char spad;                  /* Pad to even byte length */
  1395. };
  1396. X
  1397. static int adjust = FALSE;          /* Adjust to correct aspect ratio ? */
  1398. static struct slhead slfrof;          /* Slide file header */
  1399. static long xfac, yfac;           /* Aspect ratio scale factors */
  1400. X
  1401. static int sdrawkcab;              /* Slide drawing kinematic conversion of
  1402. X                     ass-backwards data flag */
  1403. X
  1404. /*  EXTEND  --    Turn a smallint into an int with sign extension, whether
  1405. X        or not that happens automatically.  */
  1406. X
  1407. static int extend(ch)
  1408. X  smallint ch;
  1409. {
  1410. X    return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
  1411. }
  1412. X
  1413. /*  SLI  --  Input word from slide file  */
  1414. X
  1415. static int sli()
  1416. {
  1417. X    short wd;
  1418. X
  1419. X    if (fread(&wd, sizeof wd, 1, slfile) != 1) {
  1420. X        pm_error("error reading slide file");
  1421. X    } else {
  1422. X    if (sdrawkcab) {
  1423. X        wd = ((wd >> 8) & 0xFF) | (wd << 8);
  1424. X    }
  1425. X    }
  1426. X    return wd;
  1427. }
  1428. X
  1429. /*  SLIB  --  Input byte from slide file  */
  1430. X
  1431. static int slib()
  1432. {
  1433. X    smallint ch = 0;
  1434. X
  1435. X    if (fread(&ch, sizeof ch, 1, slfile) != 1) {
  1436. X        pm_error("error reading slide file");
  1437. X    }
  1438. X    return extend(ch);
  1439. }
  1440. X
  1441. /*  VSCALE -- scale screen coordinates for mismatched display.    */
  1442. X
  1443. static void vscale(px, py)
  1444. X  int *px, *py;
  1445. {
  1446. X    *px = (((unsigned) *px) * xfac) >> 16;
  1447. X    *py = (((unsigned) *py) * yfac) >> 16;
  1448. }
  1449. X
  1450. /*  SLIDER  --    Read slide file.  This is called with the name of the
  1451. X        file to be read and function pointers to the routines
  1452. X        which process vectors and polygon fill requests
  1453. X        respectively.
  1454. */
  1455. X
  1456. static void slider(slvec, slflood)
  1457. X  void (*slvec)();
  1458. X  void (*slflood)();
  1459. {
  1460. X    int i, rescale;
  1461. X    unsigned char ubfr[4];          /* Utility character buffer */
  1462. X    int lx, ly;               /* Last x and y point */
  1463. X    int slx, sly;              /* Last x and y scaled screen point */
  1464. X    struct svector vec;           /* Screen vector */
  1465. X    struct spolygon poly;          /* Screen polygon */
  1466. X    unsigned short cw;              /* Control word */
  1467. X    double dsar;              /* Screen aspect ratio */
  1468. X    long ldsar;               /* Scaled long DSAR */
  1469. X    short rtest;              /* Value to test byte reversal */
  1470. X    short btest = 0x1234;          /* Value to test byte-reversal */
  1471. X    static struct slhead slhi =       /* Master slide header sample */
  1472. X        {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
  1473. X    int curcolour = 7;              /* Current vector colour */
  1474. X    pixel rgbcolour;              /* Pixel used to clear pixmap */
  1475. X
  1476. X    lx = ly = 32000;
  1477. X
  1478. X    /* Process the header of the slide file.  */
  1479. X
  1480. X    sdrawkcab = FALSE;              /* Initially guess byte order is OK */
  1481. X    fread(slfrof.slh, 17, 1, slfile);
  1482. X    fread(&slfrof.sntype, sizeof(char), 1, slfile);
  1483. X    fread(&slfrof.slevel, sizeof(char), 1, slfile);
  1484. X    fread(&slfrof.sxdots, sizeof(short), 1, slfile);
  1485. X    fread(&slfrof.sydots, sizeof(short), 1, slfile);
  1486. X    fread(ubfr, 4, 1, slfile);
  1487. X    fread(&slfrof.shwfill, sizeof(short), 1, slfile);
  1488. X    fread(&rtest, sizeof rtest, 1, slfile);
  1489. X
  1490. X    /* Verify that slide format is compatible with this program. */
  1491. X
  1492. X    if (strcmp(slfrof.slh, slhi.slh) != 0) {
  1493. X        pm_error("this is not an AutoCAD slide file.");
  1494. X    }
  1495. X
  1496. X    /* Verify that the number format and file level in the header  are
  1497. X       compatible.  All slides written by versions of AutoCAD released
  1498. X       since September of 1987 are compatible with this format.  */
  1499. X
  1500. X    if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) {
  1501. X        pm_error("incompatible slide file format");
  1502. X    }
  1503. X
  1504. X    /* Build SDSAR value from long scaled version. */
  1505. X
  1506. X    ldsar = 0L;
  1507. X    for (i = 3; i >= 0; i--) {
  1508. X    ldsar = (ldsar << 8) | ubfr[i];
  1509. X    }
  1510. X    slfrof.sdsar = ((double) ldsar) / 1E7;
  1511. X
  1512. X    /* Examine the byte order test value.   If it's backwards, set the
  1513. X       byte-reversal flag and correct all of the values we've read  in
  1514. X       so far. */
  1515. X
  1516. X    if (btest != rtest) {
  1517. X    sdrawkcab = TRUE;
  1518. #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
  1519. X    rshort(slfrof.sxdots);
  1520. X    rshort(slfrof.sydots);
  1521. X    rshort(slfrof.shwfill);
  1522. #undef rshort
  1523. X    }
  1524. X
  1525. X    /* Dump the header if we're blithering. */
  1526. X
  1527. X    if (blither || info) {
  1528. X        pm_message("Slide file type %d, level %d, hwfill type %d.",
  1529. X        slfrof.sntype, slfrof.slevel, slfrof.shwfill);
  1530. X        pm_message("Original screen size %dx%d, aspect ratio %.3f.",
  1531. X        slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
  1532. X        pm_message("Byte order is %s.",
  1533. X            sdrawkcab ? "being reversed" : "the same");
  1534. X    }
  1535. X
  1536. X    /* If the display aspect ratio indicates that the  pixels  on  the
  1537. X       sending    screen    were  not  square,  adjust  the  size  of  the
  1538. X       generated bitmap to correct the    aspect    ratio  to  square  the
  1539. X       pixels.
  1540. X
  1541. X       We  always  correct  the aspect ratio by adjusting the width of
  1542. X       the image.  This guarantees that output from the SHADE command,
  1543. X       which  is  essentially  scan-line  data written in vector form,
  1544. X       will not be corrupted. */
  1545. X
  1546. X    dsar = ((double) slfrof.sxdots) / slfrof.sydots;
  1547. X    if (abs(slfrof.sdsar - dsar) > 0.0001) {
  1548. X    if (adjust) {
  1549. X        ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
  1550. X        iydots = slfrof.sydots;
  1551. X        dsar = ((double) ixdots) / iydots;
  1552. X    } else {
  1553. X            pm_message("Warning - pixels on source screen were non-square.");
  1554. X            pm_message("          Specifying -adjust will correct image width to compensate.");
  1555. X        ixdots = slfrof.sxdots;
  1556. X        iydots = slfrof.sydots;
  1557. X        dsar = slfrof.sdsar;
  1558. X    }
  1559. X    } else {
  1560. X    /* Source pixels were square. */
  1561. X    ixdots = slfrof.sxdots;
  1562. X    iydots = slfrof.sydots;
  1563. X    dsar = slfrof.sdsar;
  1564. X    adjust = FALSE;           /* Mark no adjustment needed */
  1565. X    }
  1566. X
  1567. X    /* If there's a uniform scale factor specified, apply it. */
  1568. X
  1569. X    if (uscale > 0) {
  1570. X    ixdots = (ixdots * uscale) + 0.5;
  1571. X    iydots = (iydots * uscale) + 0.5;
  1572. X    }
  1573. X
  1574. X    /* If the image is to be stretched    to  a  given  width,  set  the
  1575. X       output  image  sizes accordingly.  If only a height or width is
  1576. X       given, scale the other direction proportionally to preserve the
  1577. X       aspect ratio. */
  1578. X
  1579. X    if (sxsize > 0) {
  1580. X    if (sysize > 0) {
  1581. X        iydots = sysize - 1;
  1582. X    } else {
  1583. X        iydots = ((((long) iydots) * (sxsize - 1)) +
  1584. X              (iydots / 2)) / ixdots;
  1585. X    }
  1586. X    ixdots = sxsize - 1;
  1587. X    } else if (sysize > 0) {
  1588. X    if (sxsize > 0) {
  1589. X        ixdots = sxsize - 1;
  1590. X    } else {
  1591. X        ixdots = ((((long) ixdots) * (sysize - 1)) +
  1592. X              (ixdots / 2)) / iydots;
  1593. X    }
  1594. X    iydots = sysize - 1;
  1595. X    }
  1596. X
  1597. X    if (adjust) {
  1598. X    pm_message(
  1599. X            "Resized from %dx%d to %dx%d to correct pixel aspect ratio.",
  1600. X        slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
  1601. X    }
  1602. X
  1603. X    /* Allocate image buffer and clear it to black. */
  1604. X
  1605. X    pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
  1606. X    PPM_ASSIGN(rgbcolour, 0, 0, 0);
  1607. X    ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
  1608. X     pixcols, pixrows, PPMD_NULLDRAWPROC,
  1609. X     (char *) &rgbcolour);
  1610. X
  1611. X    if ((rescale = slfrof.sxdots != ixdots ||
  1612. X    slfrof.sydots != iydots ||
  1613. X    slfrof.sdsar != dsar) != 0) {
  1614. X
  1615. X        /* Rescale all coords. so they'll look (more or less)
  1616. X       right on this display.  */
  1617. X
  1618. X    xfac = (ixdots + 1) * 0x10000L;
  1619. X    xfac /= (long) (slfrof.sxdots + 1);
  1620. X    yfac = (iydots + 1) * 0x10000L;
  1621. X    yfac /= (long) (slfrof.sydots + 1);
  1622. X    if (dsar < slfrof.sdsar) {
  1623. X        yfac = yfac * dsar / slfrof.sdsar;
  1624. X       } else {
  1625. X        xfac = xfac * slfrof.sdsar / dsar;
  1626. X    }
  1627. X    }
  1628. X
  1629. X    poly.npoints = 0;              /* No flood in progress. */
  1630. X
  1631. X    while ((cw = sli()) != 0xFC00) {
  1632. X    switch (cw & 0xFF00) {
  1633. X        case 0xFB00:          /*  Short vector compressed  */
  1634. X        vec.f.x = lx + extend(cw & 0xFF);
  1635. X        vec.f.y = ly + slib();
  1636. X        vec.t.x = lx + slib();
  1637. X        vec.t.y = ly + slib();
  1638. X        lx = vec.f.x;
  1639. X        ly = vec.f.y;
  1640. X        if (rescale) {
  1641. X            vscale(&vec.f.x, &vec.f.y);
  1642. X            vscale(&vec.t.x, &vec.t.y);
  1643. X        }
  1644. X        (*slvec)(&vec, curcolour);/* Draw vector on screen */
  1645. X        slx = vec.f.x;          /* Save scaled point */
  1646. X        sly = vec.f.y;
  1647. X        break;
  1648. X
  1649. X        case 0xFC00:          /*  End of file  */
  1650. X        break;
  1651. X
  1652. X        case 0xFD00:          /*  Flood command  */
  1653. X        vec.f.x = sli();
  1654. X        vec.f.y = sli();
  1655. X        if ((int) vec.f.y < 0) { /* start or end */
  1656. X            if (poly.npoints != 0) { /* end?  */
  1657. X            if (poly.npoints > 2 && poly.npoints < 11) {
  1658. X                (*slflood)(&poly, curcolour);
  1659. X            } else {
  1660. X                            pm_error("Bad polygon vertex count (%d)",
  1661. X                   poly.npoints);
  1662. X            }
  1663. X            poly.npoints = 0;
  1664. X            } else {
  1665. X            poly.fill = -vec.f.y;  /* Start */
  1666. X            }
  1667. X        } else {          /* Polygon vertex */
  1668. X            if (poly.npoints < 10) {
  1669. X            if (rescale) {
  1670. X                vscale(&vec.f.x, &vec.f.y);
  1671. X            }
  1672. X            poly.pt[poly.npoints].x = vec.f.x;
  1673. X            poly.pt[poly.npoints].y = vec.f.y;
  1674. X            }
  1675. X            poly.npoints++;
  1676. X        }
  1677. X        break;
  1678. X
  1679. X        case 0xFE00:          /*  Common endpoint compressed  */
  1680. X        vec.f.x = lx + extend(cw & 0xFF);
  1681. X        vec.f.y = ly + slib();
  1682. X        lx = vec.f.x;
  1683. X        ly = vec.f.y;
  1684. X        vec.t.x = slx;
  1685. X        vec.t.y = sly;
  1686. X        if (rescale) {
  1687. X            vscale(&vec.f.x, &vec.f.y);
  1688. X        }
  1689. X        (*slvec)(&vec, curcolour);/* Draw vector */
  1690. X        slx = vec.f.x;          /* Save scaled point */
  1691. X        sly = vec.f.y;
  1692. X        break;
  1693. X
  1694. X        case 0xFF00:          /*  Change colour  */
  1695. X        curcolour = cw & 0xFF;
  1696. X        break;
  1697. X
  1698. X        default:              /*  Co-ordinates    */
  1699. X        lx = vec.f.x = cw;
  1700. X        ly = vec.f.y = sli();
  1701. X        vec.t.x = sli();
  1702. X        vec.t.y = sli();
  1703. X        if (rescale) {
  1704. X           vscale(&vec.f.x, &vec.f.y);
  1705. X           vscale(&vec.t.x, &vec.t.y);
  1706. X        }
  1707. X        (*slvec)(&vec, curcolour);
  1708. X        slx = vec.f.x;          /* Save scaled point */
  1709. X        sly = vec.f.y;
  1710. X        break;
  1711. X    }
  1712. X    }
  1713. }
  1714. X
  1715. /*  SLIDEFIND  --  Find  a  slide  in  a  library  or,    if  DIRONLY is
  1716. X           nonzero, print a directory listing of the  library.
  1717. X           If  UCASEN  is nonzero, the requested slide name is
  1718. X           converted to upper case. */
  1719. X
  1720. static void slidefind(sname, dironly, ucasen)
  1721. X  char *sname;
  1722. X  int dironly, ucasen;
  1723. {
  1724. X    char uname[32];
  1725. X    unsigned char libent[36];
  1726. X    long pos;
  1727. X
  1728. X    if (dironly) {
  1729. X        pm_message("Slides in library:");
  1730. X    } else {
  1731. X    int i;
  1732. X    char *ip = sname;
  1733. X
  1734. X    for (i = 0; i < 31; i++) {
  1735. X        char ch = *ip++;
  1736. X        if (ch == EOS) {
  1737. X        break;
  1738. X        }
  1739. X        if (ucasen && islower(ch)) {
  1740. X        ch = toupper(ch);
  1741. X        }
  1742. X        uname[i] = ch;
  1743. X    }
  1744. X    uname[i] = EOS;
  1745. X    }
  1746. X
  1747. X    /* Read slide library header and verify. */
  1748. X
  1749. X    if ((fread(libent, 32, 1, slfile) != 1) ||
  1750. X        (strcmp(libent, "AutoCAD Slide Library 1.0\015\012\32") != 0)) {
  1751. X        pm_error("not an AutoCAD slide library file.");
  1752. X    }
  1753. X    pos = 32;
  1754. X
  1755. X    /* Search for a slide with the requested name. */
  1756. X
  1757. X    while (TRUE) {
  1758. X    if ((fread(libent, 36, 1, slfile) != 1) ||
  1759. X        (strlen(libent) == 0)) {
  1760. X        if (dironly) {
  1761. X        return;
  1762. X        }
  1763. X            pm_error("slide %s not in library.", sname);
  1764. X    }
  1765. X    pos += 36;
  1766. X    if (dironly) {
  1767. X            pm_message("  %s", libent);
  1768. X    } else if (strcmp(libent, uname) == 0) {
  1769. X        long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
  1770. X                 libent[33]) << 8) | libent[32];
  1771. X        if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
  1772. X        dpos -= pos;
  1773. X
  1774. X        while (dpos-- > 0) {
  1775. X            (void) getc(slfile);
  1776. X        }
  1777. X        }
  1778. X        break;
  1779. X    }
  1780. X    }
  1781. }
  1782. X
  1783. /*  DRAW  --  Draw a vector in the given AutoCAD colour.  */
  1784. X
  1785. static void draw(vec, colour)
  1786. X  struct svector *vec;
  1787. X  int colour;
  1788. {
  1789. X    pixel rgbcolour;
  1790. X
  1791. X    if (blither) {
  1792. X        pm_message("Vector (%d, %d) - (%d, %d)  Colour %d",
  1793. X           vec->f.x, vec->f.y, vec->t.x, vec->t.y, colour);
  1794. X    }
  1795. X    assert(vec->f.x >= 0 && vec->f.x < pixcols);
  1796. X    assert(vec->f.y >= 0 && vec->f.y < pixrows);
  1797. X    assert(vec->t.x >= 0 && vec->t.x < pixcols);
  1798. X    assert(vec->t.y >= 0 && vec->t.y < pixrows);
  1799. X    PPM_ASSIGN(rgbcolour,
  1800. X           acadcol[colour][0], acadcol[colour][1], acadcol[colour][2]);
  1801. X    ppmd_line(pixels, pixcols, pixrows, pixmaxval,
  1802. X          vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
  1803. X          PPMD_NULLDRAWPROC,
  1804. X          (char *) &rgbcolour);
  1805. SHAR_EOF
  1806. true || echo 'restore of ppm/sldtoppm.c failed'
  1807. fi
  1808. echo 'End of  part 4'
  1809. echo 'File ppm/sldtoppm.c is continued in part 5'
  1810. echo 5 > _shar_seq_.tmp
  1811. exit 0
  1812. exit 0 # Just in case...
  1813. -- 
  1814. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1815. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1816. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1817. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1818.