|
|
1.1 ! root 1: .so ../ADM/mac ! 2: .XX pico 423 "Pico \(em A Language For Composing Digital Images" ! 3: .nr dP 2 ! 4: .nr dV 3p ! 5: .EQ ! 6: delim @# ! 7: .EN ! 8: .ND July, 1989 ! 9: .TL ! 10: Pico \(em A Language For Composing Digital Images ! 11: .AU "MH 2C-521" 6335 ! 12: Gerard J. Holzmann ! 13: .AI ! 14: .MH ! 15: .AB ! 16: \fIPico\fP is a small expression language for picture compositions. ! 17: It can be used either interactively with a display or stand alone as a ! 18: picture file editor. ! 19: The following \fIpico\fP script, for instance, turns an arbitrary digitized ! 20: image stored in a file ! 21: .CW in ! 22: upside down, rotates it by 90 degrees, ! 23: and writes its negative into a file ! 24: .CW out : ! 25: .P1 20n ! 26: $ pico ! 27: 1: new = Z-$in[X-y,x] ! 28: 2: w out ! 29: 3: q ! 30: $ ! 31: .P2 ! 32: .PP ! 33: Numerous examples of ! 34: .I pico ! 35: transformations of pictures are included throughout this volume. ! 36: .AE ! 37: .2C ! 38: .NH ! 39: Black&White Images ! 40: .PP ! 41: The pictures that can be manipulated by \fIpico\fP are stored as ! 42: regular files in the picture file format described in ! 43: .I picfile (5). ! 44: The picture editor is most conveniently used interactively ! 45: with a Metheus frame buffer display. ! 46: The result of picture transformations is then directly visible ! 47: and can be used to correct or enhance the mistakes that one is ! 48: bound to make. ! 49: .SH ! 50: New and Old ! 51: .PP ! 52: Assuming that you want to work interactively and have access to one ! 53: of the Metheus frame buffers, e.g. on ! 54: .CW pipe , ! 55: a session with \fIpico\fP can be started by typing ! 56: .P1 0 ! 57: $ pico -m\fIN\fP ! 58: b&w, 512x512 pel, Metheus display ! 59: 1: ! 60: .P2 ! 61: where ! 62: .I N ! 63: is the device number of the frame buffer to be used. ! 64: By default, ! 65: .I N ! 66: is zero and opens ! 67: .CW /dev/om0 . ! 68: Also by default the size of the workarea is 512x512 pixels. ! 69: If you need to work with larger images, you ! 70: can override the default by explicitly setting a different ! 71: window width and height, for instance: ! 72: .P1 0 ! 73: $ pico -m5 -w1024 -h1024 ! 74: b&w, 1024x1024 pel, Metheus display ! 75: 1: ! 76: .P2 ! 77: The maximum size image that the Metheus frame buffer ! 78: can display is 1280x1024 pixels. ! 79: .PP ! 80: The number followed by a colon in the example above ! 81: is \fIpico\fP's prompt for commands. ! 82: .PP ! 83: The result of the last edit operation (initially an all black image) ! 84: is accessible under the predefined name ! 85: .CW old , ! 86: and ! 87: the destination of the image transformations is known as ! 88: .CW new . ! 89: To quickly get a picture into the workbuffer, you can use the command ! 90: .CW get ! 91: followed by the name of the file with the image. ! 92: .P1 0 ! 93: 1: get "pjw" ! 94: .P2 ! 95: The most frequently used command in \fIpico\fP is ! 96: .CW x , ! 97: short for ! 98: .CW execute . ! 99: To make a black&white negative from the current picture ! 100: the command would be: ! 101: .P1 0 ! 102: 2: x new=Z-old ! 103: .P2 ! 104: where Z is a predefined constant with the value of maximum white (255). ! 105: By default the transformation is applied to every pixel on the screen. ! 106: .PP ! 107: Assume we have two image files with portraits. ! 108: We can open these files by using ! 109: .CW get , ! 110: or we can specify them ! 111: on the \fIpico\fP command line, as follows, using ! 112: .CW /dev/om5 : ! 113: .P1 0 ! 114: $ pico -m5 ./face/rob ./face/pjw ! 115: b&w, 512x512 pel, Metheus display ! 116: 1: ! 117: .P2 ! 118: We can create a new image, for instance, by averaging the two faces: ! 119: .P1 0 ! 120: $ pico -m5 ./face/rob ./face/pjw ! 121: b&w, 512x512 pel, Metheus display ! 122: 1: x new=($rob+$pjw)/2 ! 123: 2: ! 124: .P2 ! 125: The transformation is written as an assignment of an ! 126: expression to the destination ! 127: .CW new . ! 128: Names preceded by a dollar sign refer to picture files, ! 129: for instance as specified on the command line. ! 130: A long name such as ! 131: .CW ./face/rob ! 132: can be abbreviated ! 133: to its base name ! 134: .CW rob ! 135: (the part following the last slash). ! 136: Not all file names have to be provided on the command line though. ! 137: We can also ! 138: .CW append ! 139: a new file ! 140: .CW doug , ! 141: without reading it, by typing: ! 142: .P1 0 ! 143: 2: a "doug" ! 144: .P2 ! 145: The double quotes are necessary. ! 146: They avoid confusion when, for instance, ! 147: .CW / ! 148: symbols ! 149: are part of the filename. ! 150: We can check which files are currently open by typing ! 151: .CW f : ! 152: .P1 0 ! 153: 3: f ! 154: $0: old color resident ! 155: $1: rob b&w resident ! 156: $2: pjw b&w resident ! 157: $3: doug b&w absent ! 158: .P2 ! 159: The numbers in the first column serve as a shorthand for the file names. ! 160: Typing ! 161: .CW $1 ! 162: therefore is equivalent to typing ! 163: .CW $rob . ! 164: We will use both notations ! 165: .CW $1 ! 166: and ! 167: .CW $rob ! 168: below. ! 169: The first line ! 170: .CW $0 ! 171: is a shorthand for ! 172: .CW old ! 173: and refers to ! 174: the workarea (the screen in interactive usage). ! 175: .PP ! 176: We have a black and white image on the screen that is an average ! 177: of the two files ! 178: .CW rob ! 179: and ! 180: .CW pjw . ! 181: To see ! 182: .CW rob ! 183: separately we could type: ! 184: .P1 0 ! 185: 4: x new=$1 ! 186: .P2 ! 187: but that is hardly an inspiring procedure. ! 188: Let's just take the left half ! 189: or rob's face combined with the right half of peter's: ! 190: .P1 0 ! 191: 5: x new=(x<256)?$rob:$pjw ! 192: .P2 ! 193: or to make a mirror image: ! 194: .P1 0 ! 195: 5: x new=(x<256)?$rob[x,y]:$rob[X-x,y] ! 196: .P2 ! 197: The variable ! 198: .CW x ! 199: used in the expression is predefined. ! 200: Don't confuse it with the first ! 201: .CW x ! 202: on the command line ! 203: which identifies the type of command to ! 204: be executed. ! 205: The variable ! 206: .CW x ! 207: gives the current x-coordinate of a pixel ! 208: during transformations. ! 209: Since in this case 512 pixels fit on one scan line, a pixel in ! 210: the middle of the screen has an ! 211: .CW x -coordinate ! 212: of 256. ! 213: The maximum value of ! 214: .CW x ! 215: is given by a predefined variable ! 216: .CW X . ! 217: .CW X/2 , ! 218: therefore, is a safer way to specify the middle of a scan line. ! 219: .PP ! 220: The expression above is a conditional of the form: ! 221: .P1 0 ! 222: \fIcondition\fP ? \fIiftrue\fP : \fIiffalse\fP ! 223: .P2 ! 224: For every screen position where the condition holds the ! 225: .I iftrue ! 226: part ! 227: of the expression applies and everywhere else the ! 228: .I iffalse ! 229: part applies. ! 230: Another predefined variable of this type is ! 231: .CW y ! 232: (the y-coordinate of the destination). ! 233: The maximum ! 234: .CW y ! 235: value is called ! 236: .CW Y . ! 237: Since ! 238: .CW $0 ! 239: refers to the screen we can turn the picture ! 240: on the screen upside down by typing: ! 241: .P1 0 ! 242: 6: x new = $0[x, Y-y] ! 243: .P2 ! 244: All pixels in the black&white picture are internally represented by a ! 245: value in the range 0..255, where 0 means black and 255 means white. ! 246: To reverse an image, therefore it would suffice to subtract the current ! 247: value of each pixel from its maximum value 255, which is stored in constant ! 248: .CW Z . ! 249: Getting very bold we can turn the picture on its side, ! 250: and make it negative by saying: ! 251: .P1 0 ! 252: 8: x new = 255 - old[y,511-x] ! 253: .P2 ! 254: or, slightly more abstract ! 255: .P1 0 ! 256: 9: x new = Z - old[y,Y-x] ! 257: .P2 ! 258: Note that we swapped x and y to turn the picture on its side. ! 259: Nothing can stop us now: ! 260: .P1 0 ! 261: 10: x new=(x<X/3)?$1:(x>X*2/3)?$2: \*(cr ! 262: 3*((x-X/3)*$2+(X*2/3-x)*$1)/X ! 263: .P2 ! 264: fades ! 265: .CW rob ! 266: slowly into ! 267: .CW pjw . ! 268: (We have used \*(cr to break the line into ! 269: two pieces for lay-out purposes. ! 270: When using \fIpico\fP, it should be typed as one complete line.) ! 271: Actually this last transformation is easier to read as a little \fIpico\fP ! 272: program. ! 273: To see how this works, and what the defaults in the above expression ! 274: are, the above expression could be typed as: ! 275: .P1 0 ! 276: 10: x { ! 277: int L, R ! 278: ! 279: L = X/3; R = X*2/3 ! 280: ! 281: for (y = 0; y < Y; y++) ! 282: for (x = 0; x < X; x++) ! 283: { if (x < L) ! 284: new[x,y] = $1 ! 285: else if (x > R) ! 286: new[x,y] = $2 ! 287: else ! 288: new[x,y] = 3*((x-L)* \*(cr ! 289: $2+(R-x)*$1)/X ! 290: } ! 291: } ! 292: .P2 ! 293: There fewer defaults here, though an assignment to ! 294: .CW new ! 295: is still ! 296: interpreted as a parallel assignment to all three color channels in the ! 297: picture. ! 298: You can override also these defaults by making the program still more explicit, ! 299: for instance by using the suffixes ! 300: .CW red , ! 301: .CW grn , ! 302: and ! 303: .CW blu ! 304: to access ! 305: color channels separately: ! 306: .CW new[x,y].red , ! 307: .CW new[x,y].grn , ! 308: and ! 309: .CW new[x,y].blu . ! 310: To see the effect you need to set the workbuffer to color mode first ! 311: with the command ! 312: .CW color . ! 313: (You go back to the default black&white mode with the command ! 314: .CW nocolor ). ! 315: .PP ! 316: All normal arithmetic operators from C are available. ! 317: The ! 318: .CW ^ ! 319: operator, for instance, makes an ! 320: .I "exclusive or" ! 321: of its operands. ! 322: Thus, ! 323: .P1 0 ! 324: 11: x new=x^y^$rob ! 325: .P2 ! 326: is a particularly striking effect, and ! 327: .P1 0 ! 328: 13: x new = $rob +(Z - $rob[x+2, y+2]) ! 329: .P2 ! 330: is an attempt to make a relief. ! 331: .PP ! 332: There is no range checking on explicit or implicit array indexing. ! 333: The use of ! 334: .CW x+2 ! 335: in the last expression is therefore risky ! 336: and is best protected with a conditional: ! 337: .P1 0 ! 338: 13: x new=$rob+(Z-(x<509 && y<509)? \*(cr ! 339: $rob[x+2,y+2]:Z) ! 340: .P2 ! 341: or more conveniently with the builtins ! 342: .CW xclamp ! 343: and ! 344: .CW yclamp : ! 345: .P1 0 ! 346: 14: x new=$rob+(Z-$rob[xclamp(x+2), \*(cr ! 347: yclamp(y+2)]) ! 348: .P2 ! 349: Another promising attempt to make a core dump would be to type ! 350: something like ! 351: .P1 0 ! 352: 14: x new=$rob[x*y, x/y] ! 353: .P2 ! 354: .NH ! 355: Color Images ! 356: .PP ! 357: A complete picture specifies pixel values for each of three ! 358: separate color channels: red, green, and blue. ! 359: When the editor is used in black&white mode only the ! 360: red channel is used. ! 361: When a black&white picture is converted to color mode, ! 362: all three channels are made equal. ! 363: The omission of a channel suffix to ! 364: .CW old , ! 365: .CW new ! 366: or a file name ! 367: is similarly interpreted to mean that a transformation expression will ! 368: apply equally to all three color channels. ! 369: By specifying an explicit suffix ! 370: .CW red , ! 371: .CW grn , ! 372: or ! 373: .CW blu , ! 374: however, we can write each channel separately. ! 375: So: ! 376: .P1 0 ! 377: 14: color ! 378: 15: x new.red=$rob ! 379: 16: x new.grn=$rob ! 380: 17: x new.blu=255-$rob ! 381: .P2 ! 382: will write ! 383: .CW rob ! 384: on the red and green channels, and its negative on the ! 385: blue channel. ! 386: If ! 387: .CW rob ! 388: is a black&white picture then typing ! 389: .CW $rob ! 390: is, of course, ! 391: equivalent to typing ! 392: .CW $rob.red . ! 393: We could also have combined the first two lines in a chain assignment: ! 394: .P1 0 ! 395: 18: x new.red=new.grn=$rob ! 396: .P2 ! 397: We can also write a separate value to each channel ! 398: by using ! 399: .CW composites . ! 400: A color composite is written as a comma separated list ! 401: of three values, enclosed in square brackets: ! 402: .P1 0 ! 403: 19: x new.rgb=[$rob,$rob,Z-$rob ] ! 404: .P2 ! 405: The channels are addressed by the three fields of the composite in ! 406: the order: [red, green, blue]. ! 407: Omitting to specify a composite when an ! 408: .CW rgb ! 409: destination is ! 410: used typically results in only the red channel being written. ! 411: As expected, ! 412: .P1 0 ! 413: 20: x new.rgb=[old.grn,old.blu,old.red ] ! 414: .P2 ! 415: rotates the colors of the picture. ! 416: And, of course, you can freely combine ! 417: the color suffixes with array indexing: ! 418: .CW $rob.blu ! 419: is just a shorthand ! 420: for ! 421: .CW "$rob[x, y].blu " ! 422: where the variables ! 423: .CW x , ! 424: and ! 425: .CW y ! 426: can be replaced by just any monstrous C-style expression. ! 427: .NH ! 428: The Color Maps ! 429: .PP ! 430: When working interactively, ! 431: the color map in the Metheus frame buffer display ! 432: can be set with one of the commands ! 433: .CW cmap ! 434: (all channels), ! 435: .CW cmap.red , ! 436: .CW cmap.grn , or ! 437: .CW cmap.blu . ! 438: The color map is a mapping table that can arbitrarily map ! 439: pixel brightness values in the range 0..255 to other ! 440: brightness values, within the same range 0..255. ! 441: The update, however, only happens on the screen and is not stored ! 442: when the image file is written. ! 443: The variable ! 444: .CW i ! 445: is used to index the color map. ! 446: For instance: ! 447: .P1 0 ! 448: 21: x cmap = Z-i ! 449: .P2 ! 450: will very quickly make a negative, and ! 451: .P1 0 ! 452: 22: x cmap = i ! 453: .P2 ! 454: turns the picture back to normal. ! 455: To fake color in a black and white image you can try: ! 456: .P1 0 ! 457: 23: x cmap.red = (i<=85)?i:0 ! 458: 24: x cmap.grn = (i>85 && i<170)?i:0 ! 459: 25: x cmap.blu = (i>=170)?i:0 ! 460: .P2 ! 461: Remember that changing the color map only changes the appearance ! 462: of the picture on the screen, not its definition in memory. ! 463: .NH ! 464: Read, Write, and Windows ! 465: .PP ! 466: The ! 467: .CW append ! 468: command, to add files to the list of dollar arguments ! 469: was discussed before. ! 470: Using the command ! 471: .CW get ! 472: instead of ! 473: .CW a ! 474: will also put the file into $0, ! 475: that is on the screen. ! 476: To save the current state of the display in a file, use: ! 477: .P1 0 ! 478: 26: w filename ! 479: .P2 ! 480: A raw black&white picture file, without the picture file header, ! 481: can be written by using ! 482: .CW "w -" ! 483: instead of ! 484: .CW w ! 485: (for instance when dumping a file to be processed ! 486: by software uneducated in picture file headers). ! 487: The size of the file written conforms to the ! 488: current window size of the editor (see also below). ! 489: To close a no longer used file and free up some memory for others, say: ! 490: .P1 0 ! 491: 27: d doug ! 492: .P2 ! 493: or ! 494: .P1 0 ! 495: 27: d $1 ! 496: .P2 ! 497: giving the file's base name or its dollar number. ! 498: To restrict the updates to a window on the screen you can set: ! 499: .P1 0 ! 500: 30: window 10 100 200 300 ! 501: .P2 ! 502: which makes a window with origin at (x,y) = (10,100), 200 pixels wide ! 503: and 300 pixels deep. ! 504: And, if you really want to exit \fIpico\fP you can type a control-D ! 505: or resort to the ! 506: .CW quit ! 507: command: ! 508: .P1 0 ! 509: 32: q ! 510: .P2 ! 511: .NH ! 512: Programs ! 513: .PP ! 514: As shown in one of the examples above, it is possible to write ! 515: small \fIpico\fP programs for the more difficult transformations ! 516: that cannot be handled by the defaults. ! 517: The control structure for the \fIpico\fP programs is again stolen from C. ! 518: .PP ! 519: A \fIpico\fP program starts with a left curly brace ! 520: .CW { ! 521: followed by ! 522: zero or more declarations of (long) integers or arrays. ! 523: For instance, ! 524: .P1 0 ! 525: 33: x { ! 526: int a, b; array ken[100] ! 527: ! 528: ... ! 529: .P2 ! 530: Note carefully that the left curly brace turns off the default control ! 531: flow over all the pixels in a picture; the control flow in a program ! 532: must be specified explicitly. ! 533: The above program fragment declares two local integers ! 534: .CW a ! 535: and ! 536: .CW b ! 537: which ! 538: by default will be initialized to zero, ! 539: and an array of 100 (long) integers named ! 540: .CW ken , ! 541: also initialized to zeros. ! 542: To initialize it to another value, use constants: ! 543: .P1 0 ! 544: int a = 9 ! 545: .P2 ! 546: Statements can either be separated by newlines or by explicit semicolons. ! 547: Here then is a list of valid types of statements: ! 548: .P1 0 ! 549: \fIlvalue\fP = \fIexpr\fP ! 550: if (\fIexpr\fP) \fIstmnt\fP ! 551: if (\fIexpr\fP) \fIstmnt\fP else \fIstmnt\fP ! 552: for (\fIexpr\fP; \fIexpr\fP; \fIexpr\fP) \fIstmnt\fP ! 553: while (\fIexpr\fP) \fIstmnt\fP ! 554: do \fIstmnt\fP while (\fIexpr\fP) ! 555: \fIlabel\fP: \fIstmnt\fP ! 556: goto label ! 557: { \fIstmnt\fP } ! 558: .P2 ! 559: An \fIlvalue\fP is an explicitly declared local variable or array element, ! 560: one of the predefined variables ! 561: .CW x , ! 562: or ! 563: .CW y , ! 564: or a picture ! 565: element. ! 566: A picture element can again be a file name such as ! 567: .CW $doug ! 568: with a ! 569: default selection of the pixel inside it, ! 570: .CW $doug[x,y] , ! 571: or it can be ! 572: more elaborate as in ! 573: .CW "$doug[x/2, y<<1].red" . ! 574: The destination of the transformation, is again referred to by ! 575: the keyword ! 576: .CW new , ! 577: but this time it needs an explicit array indexing. ! 578: The equivalent of ! 579: .P1 0 ! 580: 34: x new=old[y,x] ! 581: .P2 ! 582: to turn the picture on its side, can be written as a \fIpico\fP program: ! 583: .P1 0 ! 584: 35: x { ! 585: for (y = 0; y < 512; y++) ! 586: for (x = 0; x < 512; x++) ! 587: new[x,y] = old[y,x] ! 588: } ! 589: .P2 ! 590: Note that also the control flow must be explicit. ! 591: Typing only ! 592: .P1 0 ! 593: 36: x { new[x,y] = old[y,x] } ! 594: .P2 ! 595: would use the initial (zero) values of ! 596: .CW x ! 597: and ! 598: .CW y ! 599: and ! 600: merely assign ! 601: .CW "new[0,0] = old[0,0]" . ! 602: .NH ! 603: Array Indexing and Control Flow Defaults ! 604: .PP ! 605: One more word about defaults. ! 606: \fIPico\fP tries to be smart about assigning types to values. ! 607: When a single rvalue is needed and a color composite is available ! 608: and average of the color channels is the default, for instance: ! 609: .P1 0 ! 610: .CW old becomes ! 611: .CW (old[x,y].red+old[x,y].grn+old[x,y].blu)/3 . ! 612: .P2 ! 613: If on the other hand a value is available and a composite is ! 614: needed the value will be replicated into a fake composite. ! 615: To override the defaults assignments can of course always ! 616: be made more explicit. ! 617: Normal cases should work as expected, for instance, by default: ! 618: .P1 0 ! 619: new = old ! 620: .P2 ! 621: truly means ! 622: .P1 0 ! 623: new.red=old.red; ! 624: new.grn=old.grn; ! 625: new.blu=old.blu ! 626: .P2 ! 627: .NH ! 628: Procedures ! 629: .PP ! 630: There is a facility in \fIpico\fP to declare named segments of code and ! 631: use these as functions or procedures. ! 632: As an example, the following command declares a procedure ! 633: .CW doit ! 634: that makes a histogram of a window of pixels on the screen. ! 635: It is equivalent to the sequence: ! 636: .P1 0 ! 637: 37: window a b w d ! 638: 38: x { global array histog[256]; } ! 639: 39: x histo[old]++ ! 640: 40: window 0 0 512 512 ! 641: .P2 ! 642: In a procedure this is written as: ! 643: .P1 0 ! 644: 37: def doit(a, b, w, d) { ! 645: global array histog[256] ! 646: ! 647: for (y = a; y < a+w; y++) ! 648: for (x = b; x < b+d; x++) ! 649: histog[old[x,y]]++ ! 650: } ! 651: .P2 ! 652: The declaration prefix ! 653: .CW global ! 654: extends the scope of an array so that it can be ! 655: referred to in subsequent procedures, programs or expressions. ! 656: We can now call the procedure and use the histogram to arbitrarily ! 657: change the color map: ! 658: .P1 0 ! 659: 38: x { doit(0,0,512,512); } ! 660: 39: x cmap = histog[i]%256 ! 661: .P2 ! 662: Or more usefully, to calculate and apply a simple ! 663: histogram equalization: ! 664: .P1 0 ! 665: 40: x { ! 666: int ave, i, j, R, L, Hint; ! 667: global array eqlz[256] ! 668: ! 669: .P3 ! 670: for (i = ave = 0; i < 256; i++) ! 671: ave += histog[i]; ! 672: ave /= 256 ! 673: ! 674: .P3 ! 675: for (i = R = Hint = 0; i < 256; i++) ! 676: { L = R ! 677: Hint += histog[i] ! 678: while (Hint > ave) ! 679: { Hint -= ave ! 680: R++ ! 681: } ! 682: j = (L+R)/2 ! 683: eqlz[i] = (j>255)?255:j ! 684: } ! 685: } ! 686: 41: x new=eqlz[old] ! 687: .P2 ! 688: When \fIpico\fP starts up it reads a small set of library procedures ! 689: by simulating an ! 690: .CW r ! 691: command (see Table 1). ! 692: These definitions are stored in the file ! 693: .CW /usr/lib/pico/defines . ! 694: The builtins listed in Table 2 can be used in \fIpico\fP programs and ! 695: \fIpico\fP procedures. ! 696: .NH ! 697: Non-Interactive Use of \fIPico\fP ! 698: .PP ! 699: When \fIpico\fP is used without having access to a frame buffer ! 700: all commands will still work. ! 701: To check the result of executing commands ! 702: it can be convenient to write what would have been the current screen image ! 703: into a file with the ! 704: .CW w ! 705: command ! 706: and view it in another \fImux\fP-window on the 5620 (or 630) terminal with ! 707: a command like ! 708: .I flicks . ! 709: For instance, in one window the session can be: ! 710: .P1 0 ! 711: $ pico rob pjw ! 712: 1: nocolor ! 713: 2: x new=($rob*$pjw)/255 ! 714: 3: w - junk ! 715: 4: ! 716: .P2 ! 717: While in another window the file is displayed ! 718: with ! 719: .I flicks , ! 720: as follows: ! 721: .P1 0 ! 722: $ flicks -em junk ! 723: .P2 ! 724: .NH ! 725: See Also ! 726: .PP ! 727: More examples on how to use \fIpico\fP, and on its internal structure, ! 728: can be found in: ! 729: |reference(pico %no_cite)|reference(digital darkroom %no_cite) ! 730: .PP ! 731: |reference_placement ! 732: .FC ! 733: .1C ! 734: .TS ! 735: center; ! 736: c c ! 737: lFCW lw(4i). ! 738: _ ! 739: COMMAND DESCRIPTION ! 740: = ! 741: a [x y w d] file T{ ! 742: append file with optional offset/dimensions ! 743: T} ! 744: d basename/$n delete file ! 745: h file T{ ! 746: read header information from file(s) ! 747: T} ! 748: r file read (library) command file ! 749: w [-] file T{ ! 750: write file or window with or without a header ! 751: format: default = \fIpico\fP header, \- means no header ! 752: T} ! 753: _ ! 754: nocolor T{ ! 755: update & display only 1 channel ! 756: T} ! 757: color T{ ! 758: update & display all 3 channels ! 759: T} ! 760: _ ! 761: window x y w d T{ ! 762: restrict workarea to this window ! 763: T} ! 764: _ ! 765: get [x y w d] file T{ ! 766: read file contents into ! 767: .CW old ! 768: T} ! 769: get $n T{ ! 770: refresh ! 771: .CW old ! 772: with an already opened file ! 773: T} ! 774: _ ! 775: f show mounted files ! 776: show [name] T{ ! 777: show symbol information (values) ! 778: T} ! 779: functions show functions ! 780: _ ! 781: def name { pprog } define a function ! 782: x expr execute expr in default loop ! 783: x { pprog } execute \fIpico\fP program ! 784: _ ! 785: q quit ! 786: _ ! 787: .TE ! 788: .ce ! 789: File names containing nonalphanumeric characters (period, slash) must be enclosed in double quotes. ! 790: .sp .5 ! 791: .ce ! 792: \fBTable 1.\fR Command Summary ! 793: .SP 3 ! 794: .TS ! 795: center; ! 796: lFCW lw(4i). ! 797: _ ! 798: printf(string, args) recognizes only: \f(CW%d\fP, \f(CW%s\fP, \f(CW\en\fP, \f(CW\et\fP ! 799: x_cart(radius, angle) T{ ! 800: convert radius and angle (degrees: 0..360) into x_coordinate ! 801: T} ! 802: y_cart(radius, angle) T{ ! 803: convert radius and angle (degrees: 0..360) into y_coordinate ! 804: T} ! 805: X_cart(r,a),Y_cart(r,a) T{ ! 806: same as [\fIxy\fP]_\fIcart\fP, but expects \fIangle\fP in centidegrees ! 807: T} ! 808: r_polar(x,y) convert \fIx,y\fP coordinate into radius ! 809: a_polar(x,y) T{ ! 810: angle returned is in degrees: 0..360, acuuracy=\(+- 2 degrees ! 811: T} ! 812: A_polar(x,y) angle returned is in centidegrees: 0..36000 ! 813: putframe(nr) dump window into the file \f(CW"frame.%6d"\fP, \fInr\fP ! 814: getframe(nr) T{ ! 815: read from the file \f(CW"frame.%6d"\fP, \fInr\fP ! 816: T} ! 817: setcmap(i, r,g,b) write \fIi\fPth value in colormap ! 818: getcmap(i, r,g,b) read \fIi\fPth value in colormap ! 819: redcmap(i, z) ! 820: grncmap(), blucmap() ! 821: _ ! 822: sin(angle), cos(angle) T{ ! 823: returns 0..10,000, \fIangle\fP in degrees : 0..360 ! 824: T} ! 825: Sin(angle), Cos(angle) T{ ! 826: same but expects \fIangle\fP in centidegrees: 0..36000 ! 827: T} ! 828: atan(x, y) T{ ! 829: arc-tangent of \fIy/x\fP, returns angle in degrees: 0..360 ! 830: T} ! 831: exp(a) as advertised ! 832: log(a),log10(a) returns 1024*result ! 833: sqrt(a) integer square root of \fIa\fP ! 834: pow(a,b) \fIa\fP to the power \fIb\fP ! 835: rand() returns a random integer \fIr\fP: 0\(<=\fIr\fP<32768. ! 836: _ ! 837: .TE ! 838: .ce ! 839: \fBTable 2.\fR Builtin Procedures
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.