/**
  * Adds (partial) transparency to a sampleable. This decorator multiplies the alpha channel of the
  * base sampleable by an opacity factor, {@code alpha}. If the base sampleable is opaque, then
  * {@code alpha} gives the opacity of the result, but to the extent that the base sampleable is
  * semi-transparent, {@code alpha} applies additional transparency on top of that by multiplying
  * the alpha at each point.
  *
  * @param alpha the opacity of the resulting sampleable
  * @param base the sampleable to make partially transparent
  * @return the partially transparent sampleable
  */
 public static Sampleable addTransparency(double alpha, Sampleable base) {
   return new AbstractSampleable(base.getBoundingBox()) {
     @Override
     public Color getColorAt(Point<Double> point) {
       Color c = base.getColorAt(point);
       return Colors.rgba(c.red(), c.green(), c.blue(), alpha * c.alpha());
     }
   };
 }
 /**
  * Scales a sampleable by the given factor. The position of the origin is fixed.
  *
  * @param factor the factor to scale by
  * @param base the sampleable to scale
  * @return the scaled sampleable
  */
 public static Sampleable scale(double factor, Sampleable base) {
   BoundingBox bb = base.getBoundingBox();
   return new AbstractSampleable(
       factor * bb.top(), factor * bb.bottom(),
       factor * bb.left(), factor * bb.right()) {
     @Override
     public Color getColorAt(Point<Double> point) {
       return base.getColorAt(point.scaleBy(1 / factor));
     }
   };
 }