Class PixelMapGen

java.lang.Object
net.paulhertz.pixelaudio.PixelMapGen
Direct Known Subclasses:
BoustropheGen, BuildFromPathGen, DiagonalZigzagGen, HilbertGen, MooreGen, MultiGen, RandomContinousGen

public abstract class PixelMapGen extends Object

Abstract class for handling coordinates and LUT generation for PixelAudioMapper. PixelAudioMapper is designed to be independent of any specific mapping between its audio and pixel arrays. It uses PixelMapGen classes as plug-ins to obtain values for its LUTs. Keeping the LUT generation class outside PixelAudioMapper removes dependencies on the particular mapping.

The PixelAudioMapper class handles the combinatorial math for mapping between two arrays whose elements are in one-to-one correspondence but in different orders. PixelMapGen generates the mapping between the two arrays. PixelAudioMapper, as its name suggests, considers one array to be floating point audio samples and other to be RGBA integer pixel data, but of course the relationship is completely arbitrary as far as the mapping goes. The mapping was given its own class precisely because it is generalizable, though PixelMapGen does assume that the cardinality of its arrays can be factored by width and height.

The following short program shows the typical initialization of PixelAudio classes in Processing:

   import net.paulhertz.pixelaudio.*;
   
   PixelAudio pixelaudio;
   HilbertGen hGen;
   PixelAudioMapper mapper;
   PImage mapImage;
   int[] colors;
   
   public void setup() {
     size(512, 512);
     pixelaudio = new PixelAudio(this);
     hGen = new HilbertGen(width, height);
     mapper = new PixelAudioMapper(hGen);
     mapImage = createImage(width, height, RGB);
     mapImage.loadPixels();
     mapper.plantPixels(getColors(), mapImage.pixels, 0, 0, mapper.getSize());
     mapImage.updatePixels();
   }
   
   public int[] getColors() {
     int[] colorWheel = new int[mapper.getSize()];
     pushStyle();
     colorMode(HSB, colorWheel.length, 100, 100);
     int h = 0;
     for (int i = 0; i < colorWheel.length; i++) {
       colorWheel[i] = color(h, 66, 66);
       h++;
     }
     popStyle();
     return colorWheel;
   }
   
   public void draw() {
     image(mapImage, 0, 0);
   } 
   
Creating your own PixelMapGen subclass

To create your own PixelMapGen subclass, all you need to do is supply a list of non-repeating coordinate pairs that cover a grid where width >= 2; height >= 2;. Of course, your subclass may impose other restrictions on width and height, or include constructors that require additional arguments. Your describe() and validate() methods can provide users with information on the requirements of your subclass. PixelMapGen will generate the LUTs for signal and image path from the coordinates. When you initialize a PixelAudioMapper with a PixelMapGen, pixelMap is copied to the PixelAudioMapper.signalToImageLUT field and sampleMap is copied to the PixelAudioMapper.imageToSignalLUT field. pixelMap and signalToImageLUT are the "signal map", the pixel indices of the path the mapping of signal to image follows as it traverses the pixel grid. Whenever possible, please follow the convention of generating the first coordinate at (0,0). This allows for consistent behavior when coordinates and LUTs apply the transforms implemented in the BitmapTransform class. Within the body of the subclass, I suggest the following naming convention for the coordinate generating methods:

  @Override
  public int[] generate() {...}
  
  private ArrayList<int[]> generateCoordinates() {...}
  
  private ArrayList<int[]> generateYourSubclassNameCoordinates(int width, int height) {...}
 

See PixelAudioMapper for a detailed explanation of how LUTs are used in PixelAudio.
See DiagonalZigzagGen for an example of how each method functions in context.
See the LookupTables and MultiGenLookupTables example sketches (in Processing or Eclipse) for a visualization of Lookup Tables in PixelAudio.

  • Field Details

  • Constructor Details

    • PixelMapGen

      public PixelMapGen(int width, int height, AffineTransformType type)
      Constructor for classes that extend PixelMapGen. You will need to create you own constructor for your class, but it can just call super(width, height) if everything it does can be handled in your generate() method. Note that generate() should be called on the last line of your constructor, after any additional initializations or calculations required for your class. See DiagonalZigzagGen and HilbertGen for examples of how to organize and initialize your own PixelMapGen class.
      Parameters:
      width - width of the PixelMapGen in pixels
      height - height of the PixelMapGen in pixels
      type - an AffineTransformType to apply to the coordinates of the PixelMapGen prior to creating the index maps pixelMap and sampleMap
    • PixelMapGen

      public PixelMapGen(int width, int height)
      Constructor for classes that extend PixelMapGen. You will need to create you own constructor for your class, but it can just call super(width, height) if everything it does can be handled in your generate() method. Note that generate() should be called on the last line of your constructor, after any additional initializations or calculations required for your class. See DiagonalZigzagGen and HilbertGen for examples of how to organize and initialize your own PixelMapGen class.
      Parameters:
      width -
      height -
  • Method Details

    • describe

      public abstract String describe()
      Returns a description of the mapping and initialization requirements of a PixelMapGen class.
      Returns:
      A String describing this class's mapping and initialization requirements
    • validate

      public abstract boolean validate(int width, int height)
      Validates parameters to a constructor.
      Parameters:
      width -
      height -
      Returns:
      true if the width and height parameters are valid for creating a mapping with this generator, otherwise, false.
    • generate

      public abstract int[] generate()

      Initialization method that sets this.coords, and then this.pixelMap and this.sampleMap: this.coords is a list of coordinate pairs representing the signal path, the (x,y) pixel locations along a path that visits every pixel in a bitmap exactly once. Once you have created it, you can call setMapsFromCoords() to set this.pixelMap and this.sampleMap automatically.

      generate() must be called from your class, so that you can initialize any local variables before generating coordinates and LUTs. The best place to call it is typically on the last line of the constructor for your class, after calling super() on the first line and after initializing any local variables needed to generate your coordinates and LUTs. You must initialize this.coords, this.pixelMap, and this.sampleMap within generate(). See DiagonalZigzagGen or HilbertGen for sample code.

      Returns:
      this.pixelMap, the value for PixelAudioMapper.signalToImageLUT.
    • setMapsFromCoords

      public int[] setMapsFromCoords(ArrayList<int[]> coordinates)
      Sets this.coords, this.pixelMap and this.sampleMap instance variables from coordinates ArrayList argument. This method is provided as a convenience: all you have to do in a child class is set the coordinates of the signal path as it steps through a bitmap of dimensions this.w * this.h.
      Parameters:
      coordinates - a list of coordinate pairs representing the signal path, the (x,y) pixel locations along a path that visits every pixel in a bitmap exactly once. This should be created within your generate() method in your child class that extends PixelMapGen.
      Returns:
      the pixelMap value, which has already been set in this method and may be ignored
    • transformCoords

      public void transformCoords(ArrayList<int[]> coordinates, AffineTransformType type)
      Applies an AffineTransformType to a list of 2D coordinates.
      Parameters:
      coordinates - an array of coordinate pairs
      type - the AffineTransformType to apply
    • loadIndexMaps

      public void loadIndexMaps()
      Creates pixelMap and sampleMap from coords, which must already be initialized.
    • getWidth

      public int getWidth()
      Returns:
      Width of the bitmap associated with this PixelMapGen.
    • getHeight

      public int getHeight()
      Returns:
      Height of the bitmap associated with this PixelMapGen.
    • getSize

      public int getSize()
      Returns:
      Size (width * height) of the bitmap associated with this PixelMapGen.
    • getPixelMap

      public int[] getPixelMap()
      Returns pixelMap, the pixel array indices used to initialize PixelAudioMapper.signalToImageLUT.
      Returns:
      pixelMap array, which steps through the signal and returns indices to each pixel in the corresponding bitmap
    • getPixelMapCopy

      public int[] getPixelMapCopy()
      Returns a copy of pixelMap.
      Returns:
      a copy of the pixelMap array
    • getSampleMap

      public int[] getSampleMap()
      Returns sampleMap, the audio signal indices used to initialize PixelAudioMapper.imageToSignalLUT.
      Returns:
      the sampleMap array, which steps through the bitmap \ and returns indexes to each sample in the corresponding signal
    • getSampleMapCopy

      public int[] getSampleMapCopy()
      Returns a copy of sampleMap.
      Returns:
      a copy of sampleMap
    • getCoordinates

      public ArrayList<int[]> getCoordinates()
      Returns the coordinates of the signal path.
      Returns:
      this.coords, the array of coordinate pairs that mark a path (the "signal path") through every pixel in a bitmap. getCoordinatesCopy() is the preferred method for obtaining the coordinates.
    • getCoordinatesCopy

      public ArrayList<int[]> getCoordinatesCopy()
      Returns a copy of the coordinates of the signal path.
      Returns:
      a copy of this.coords
    • getTransformType

      public AffineTransformType getTransformType()
      Returns the AffineTransformType associated with this PixelMapGen.
      Returns:
      an AffineTransformType
    • setTransformType

      public void setTransformType(AffineTransformType transformType)
      Sets the AffineTransformType associated with this PixelMapGen and transforms its coordinates and associated sampleMap and pixelMap fields.
      Parameters:
      transformType - an AffineTransformType
    • isPowerOfTwo

      public static boolean isPowerOfTwo(int n)
    • findPowerOfTwo

      public static int findPowerOfTwo(int n)
    • findNearestPowerOfTwoLessThan

      public static int findNearestPowerOfTwoLessThan(int n)
    • getPixelMapFromCoordinates

      public static int[] getPixelMapFromCoordinates(ArrayList<int[]> coordsList, int w)
      Given a list of coordinate pairs over an image, returns the corresponding bitmap index numbers.
      Parameters:
      coordsList - a list of coordinate pairs representing the (x,y) pixel locations along a path that visits every pixel in a bitmap
      w - the width of the bitmap
      Returns:
      the bitmap index numbers of the coordinates
    • getInversMapFromPixelArray

      public static int[] getInversMapFromPixelArray(int[] pixelArr)
      Builds the inverse LUT corresponding to the supplied lookup table.
      Parameters:
      pixelArr - a one-to-one index mapping
      Returns:
      an array such that inverseArr[pixelArr[i]] == i for all valid indices
    • randomTransform

      public static AffineTransformType randomTransform(Random rand)
      Returns a random transform from PixelMapGen.transArray.
      Parameters:
      rand - a Random instance.
      Returns:
      a randomly selected transform from PixelMapGen.transArray
    • randomUniformTransform

      public static AffineTransformType randomUniformTransform(Random rand)
      Returns a random transform from PixelMapGen.transArray.
      Parameters:
      rand - a Random instance.
      Returns:
      a randomly selected transform from PixelMapGen.transArray