Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
Summary Activity SCM

SCM Repository

[sml3d] View of /trunk/sml3d/src/raw-data/image-util.sml
ViewVC logotype

View of /trunk/sml3d/src/raw-data/image-util.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 659 - (download) (annotate)
Sat Jan 2 04:50:37 2010 UTC (9 years, 9 months ago) by jhr
File size: 5304 byte(s)
  Factor out support for low-level C data into separate library.  This library
  is used by both the OpenCL and OpenGL libraries.
(* image-util.sml
 *
 * COPYRIGHT (c) 2010 John Reppy (http://cs.uchicago.edu/~jhr)
 * All rights reserved.
 *
 * Some utility functions for image generation and manipulation.
 *)

structure ImageUtil :> sig

    type 'a ty = 'a DataBuffer.ty
    type float = Real32.real

  (* procedural generation of images using integer indices.  The coordinates are given
   * in depth, row, column order.
   *)
    val tabulate1D : 'a ty -> {wid : int, f : int -> 'a} -> 'a Image.image1D
    val tabulate2D : 'a ty -> {wid : int, ht : int, f : int * int -> 'a} -> 'a Image.image2D
    val tabulate3D : 'a ty -> {wid : int, ht : int, depth : int, f : int * int * int -> 'a} -> 'a Image.image3D

  (* procedural generation of textures using floating-point coordinates.  The coordinates
   * correspond to the center of the given texel and are given in s, t, r order (note
   * that this order is the opposite of that used by the tabulate functions).
   *)
    val gen1D : 'a ty -> {wid : int, f : float -> 'a} -> 'a Image.image1D
    val gen2D : 'a ty -> {wid : int, ht : int, f : float * float -> 'a} -> 'a Image.image2D
    val gen3D : 'a ty -> {wid : int, ht : int, depth : int, f : float * float * float -> 'a} -> 'a Image.image3D

  (* generate by overwriting an existing image *)
    val update1D : 'a Image.image1D * (int -> 'a) -> unit
    val update2D : 'a Image.image2D * (int * int -> 'a) -> unit
    val update3D : 'a Image.image3D * (int * int * int -> 'a) -> unit

  end = struct

    structure I = Image
    structure DB = DataBuffer

    type 'a ty = 'a DB.ty
    type float = Real32.real


  (** fill in an existing data buffer **)

    fun fill1D {wid, buf, f} = let
	  fun lp i = if (i < wid)
		then (
		  DB.set(buf, i, f i); lp(i+1))
		else ()
	  in
	    lp 0
	  end

    fun fill2D {wid, ht, buf, f} = let
	  fun lp1 (r, i) = if (r < ht)
		then let
		  fun lp2 (c, i) = if (c < wid)
			then (DB.set(buf, i, f(r, c)); lp2(c+1, i+1))
			else lp1 (r+1, i)
		  in
		    lp2 (0, i)
		  end
		else ()
	  in
	    lp1 (0, 0)
	  end

    fun fill3D {wid, ht, depth, buf, f} = let
	  fun lp1 (d, i) = if (d < depth)
		then let
		  fun lp2 (r, i) = if (r < ht)
			then let
			  fun lp3 (c, i) = if (c < wid)
				then (DB.set(buf, i, f(d, r, c)); lp3(c+1, i+1))
				else lp2 (r+1, i)
			  in
			    lp3 (0, i)
			  end
			else lp1 (d+1, i)
		  in
		    lp2 (0, i)
		  end
		else ()
	  in
	    lp1 (0, 0)
	  end


  (** generate by overwriting an existing image **)
    fun update1D (img, f) = fill1D {wid = I.width1D img, buf = I.data1D img, f = f}

    fun update2D (img, f) = fill2D {
	    wid = I.width2D img, ht = I.height2D img, buf = I.data2D img, f = f
	  }

    fun update3D (img, f) = fill3D {
	    wid = I.width3D img, ht = I.height3D img, depth = I.depth3D img,
	    buf = I.data3D img, f = f
	  }


  (** procedural generation of images using integer indices **)

    fun checkDim i = if (i < 1) then raise Size else ()

    fun tabulate1D elemSz {wid, f} = let
	  val _ = checkDim wid
	  val buf = DB.new (elemSz, wid)
	  in
	    fill1D {wid = wid, buf = buf, f = f};
	    I.image1D {wid=wid, data=buf}
	  end

    fun tabulate2D elemSz {wid, ht, f} = let
	  val _ = checkDim wid
	  val _ = checkDim ht
	  val buf = DB.new (elemSz, wid*ht)
	  in
	    fill2D {wid = wid, ht = ht, buf = buf, f = f};
	    I.image2D {wid=wid, ht=ht, data=buf}
	  end

    fun tabulate3D elemSz {wid, ht, depth, f} = let
	  val _ = checkDim wid
	  val _ = checkDim ht
	  val _ = checkDim depth
	  val buf = DB.new (elemSz, wid*ht*depth)
	  in
	    fill3D {wid = wid, ht = ht, depth = depth, buf = buf, f = f};
	    I.image3D {wid=wid, ht=ht, depth=depth, data=buf}
	  end


  (** procedural generation of images using real indices.  The coordinate of the image
   ** will be a unit interva/square/cube.  The real indices are calculated to be the
   ** center of the texels (i.e., offset by 0.5 * texel width).
   **)

    fun offsetAndSpan sz = let
	  val span = 1.0 / Real32.fromInt sz
	  val offset = 0.5 * span
	  in
	    (offset, span)
	  end

    fun gen1D elemSz {wid, f} = let
	  val _ = checkDim wid
	  val buf = DB.new (elemSz, wid)
	  val (offset, span) = offsetAndSpan wid
	  fun g i = f (offset + Real32.fromInt i * span)
	  in
	    fill1D {wid = wid, buf = buf, f = g};
	    I.image1D {wid=wid, data=buf}
	  end

    fun gen2D elemSz {wid, ht, f} = let
	  val _ = checkDim wid
	  val _ = checkDim ht
	  val buf = DB.new (elemSz, wid*ht)
	  val (cOffset, cSpan) = offsetAndSpan wid
	  val (rOffset, rSpan) = offsetAndSpan ht
	  fun g (r, c) = f (cOffset + Real32.fromInt c * cSpan, rOffset + Real32.fromInt r * rSpan)
	  in
	    fill2D {wid = wid, ht = ht, buf = buf, f = g};
	    I.image2D {wid=wid, ht=ht, data=buf}
	  end

    fun gen3D elemSz {wid, ht, depth, f} = let
	  val _ = checkDim wid
	  val _ = checkDim ht
	  val _ = checkDim depth
	  val buf = DB.new (elemSz, wid*ht*depth)
	  val (cOffset, cSpan) = offsetAndSpan wid
	  val (rOffset, rSpan) = offsetAndSpan ht
	  val (dOffset, dSpan) = offsetAndSpan depth
	  fun g (d, r, c) = f (
		cOffset + Real32.fromInt c * cSpan,
		rOffset + Real32.fromInt r * rSpan,
		dOffset + Real32.fromInt d * dSpan)
	  in
	    fill3D {wid = wid, ht = ht, depth = depth, buf = buf, f = g};
	    I.image3D {wid=wid, ht=ht, depth=depth, data=buf}
	  end

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0