Annotation of researchv10dc/vol2/pico/pico.ms, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.