############################################################################
#
#	File:     picktile.icn
#
#	Subject:  Program to pick a tile out of an image
#
#	Author:   Ralph E. Griswold
#
#	Date:     May 2, 2001
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#  This program provides an optionally magnified view of an image file.
#  Clicking on a pixel produces a pattern specification for the tile
#  with the selected upper-left corner.
#
#  Options are:
#
#	-z i	zoom factor, default 1 (no magnification)
#	-f	use fixed size tiles rather than selection; default selection
#	-w i	width of tile, default 32
#	-h i	height of tile, default width
#	-I	pick tiles to make icons; implies -z2, -f, -w38, -w38 (the
#		  larger size leaves room for error and trimming)
#	-R i	specs for ResEdit files; i = 32 or 16
# 	-t	trim whitepace around tile
#
#  Typical usage is
#
#	picktile image.xbm >image.tle
#
#  The program terminates if "q" is pressed when in the image window.
#
############################################################################
#
#  Requires:  Version 9 graphics
#
############################################################################
#
#  Links:  options, patxform, win, xcompat
#
############################################################################

link options
link patxform
link win
link xcompat

procedure main(args)
   local pixmap, wix, hix, c, x, y, event, opts, base, magnif, cols, rows
   local arglist, state, x0, x1, y0, y1, pattern

   opts := options(args, "tz+w+h+If")
   magnif := \opts["z"] | 1
   cols := \opts["w"] | 32
   rows := \opts["h"] | cols

   if \opts["I"] then {
      magnif := 2
      cols := rows := 38
      opts["f"] := 1
      }

   pixmap := XBind(, , ,"image=" || args[1]) |
      stop("*** cannot open image file")

   wix := WAttrib(pixmap, "width")
   hix := WAttrib(pixmap, "height")

   win(magnif * wix, magnif * hix)

#  Build the magnified image.

#  But if the magnification happens to be 1, don't do it the dumb way.

   if magnif = 1 then
      CopyArea(pixmap, &window)

   else {
      every y := 0 to hix - 1 do {
         arglist := []

         every x := 0 to wix - 1 do {
            c := Pixel(pixmap, x, y, 1, 1)
            if c == "0,0,0" then {
               every put(arglist, (magnif * x) | (magnif * y) | magnif | magnif)
               }
            x +:= 1
            }

         if *arglist > 0 then FillRectangle ! arglist
         }
      }

   if \opts["f"] then {				# let user pick corners
      while event := Event() do {
         case event of {
            "q":   exit()
            &lpress | &mpress | &rpress: {
               pattern := pix2pat(pixmap, &x / magnif, &y / magnif, cols, rows)
               if \opts["t"] then pattern := rows2pat(ptrim(pat2rows(pattern)))
               write(pattern)
               }
            }
         }
      }


   else {					# let user drag to select area
      state := "pick"				# waiting for user to pick
   
      WAttrib("drawop=reverse")
      WAttrib("linestyle=dashed")
   
      while event := Event() do {
         if event === "q" then exit()
         case state of {
            "pick": {				# pick the upper-left corner
               if event === &lpress then {
                  x1 := x0 := &x		# initial coordinates
                  y1 := y0 := &y
                  DrawRectangle(x0, y0, 0, 0)	# start the selection rectangle
                  state := "select"		# now select the rectangle
                  }
               }
            "select": {				# select the rectangle
               case event of {
                  &ldrag: {			# searching ...
                     DrawRectangle(x0, y0, x1 - x0, y1 - y0) # erase rectangle
                     x1 := &x			# new lower-right
                     y1 := &y
                     DrawRectangle(x0, y0, x1 - x0, y1 - y0) # new rectangle
                     }
                  &lrelease: {			# got it!
                     DrawRectangle(x0, y0, x1 - x0, y1 - y0) # erase rectangle
                     x1 := &x			# new lower-right
                     y1 := &y
                     DrawRectangle(x0, y0, x1 - x0, y1 - y0) # new rectangle
                     state := "decide"			# now decide
                     }
                  }
               }
            "decide": {				# is it wanted or not?
               DrawRectangle(x0, y0, x1 - x0, y1 - y0) # erase rectangle
               if event === &lpress then {
                  if (x0 <= &x <= x1) & (y0 <= &y <= y1) then {
                     pattern := pix2pat(pixmap, x0 / magnif, y0 / magnif,
                        (x1 - x0) / magnif, (y1 - y0) / magnif)
                     if \opts["t"] then
                        pattern := rows2pat(ptrim(pat2rows(pattern)))
                     write(pattern)
                     }
                  }
               state := "pick"			# go for another
               }
            }
         }
      }

end
