docs: public final WritableRaster filter(final Raster pSource, WritableRaster pDest, IndexColorModel pColorModel) {
          int width = pSource.getWidth();
          int height = pSource.getHeight();
  
          // Create destination raster if needed
          if (pDest == null) {
              pDest = createCompatibleDestRaster(pSource, pColorModel);
          }
  
          // Initialize Floyd-Steinberg error vectors.
          // +2 to handle the previous pixel and next pixel case minimally
          // When reference for column, add 1 to reference as this buffer is
          // offset from actual column position by one to allow FS to not check
          // left/right edge conditions
          int[][] currErr = new int[width + 2][3];
          int[][] nextErr = new int[width + 2][3];
  
          // Random errors in [-1 .. 1] - for first row
          for (int i = 0; i < width + 2; i++) {
              // Note: This is broken for the strange cases where nextInt returns Integer.MIN_VALUE
              currErr[i][0] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
              currErr[i][1] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
              currErr[i][2] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
          }
  
          // Temp buffers
          final int[] diff = new int[3]; // No alpha
          final int[] inRGB = new int[4];
          final int[] outRGB = new int[4];
          Object pixel = null;
          boolean forward = true;
  
          // Loop through image data
          for (int y = 0; y < height; y++) {
              // Clear out next error rows for colour errors
              for (int i = nextErr.length; --i >= 0;) {
                  nextErr[i][0] = 0;
                  nextErr[i][1] = 0;
                  nextErr[i][2] = 0;
              }
  
              // Set up start column and limit
              int x;
              int limit;
              if (forward) {
                  x = 0;
                  limit = width;
              }
              else {
                  x = width - 1;
                  limit = -1;
              }
  
              // TODO: Use getPixels instead of getPixel for better performance?            
  
              // Loop over row
              while (true) {
                  // Get RGB from original raster
                  // DON'T KNOW IF THIS WILL WORK FOR ALL TYPES.
                  pSource.getPixel(x, y, inRGB);
  
                  // Get error for this pixel & add error to rgb
                  for (int i = 0; i < 3; i++) {
                      // Make a 28.4 FP number, add Error (with fraction),
                      // rounding and truncate to int
                      inRGB[i] = ((inRGB[i] << 4) + currErr[x + 1][i] + 0x08) >> 4;
  
                      // Clamp
                      if (inRGB[i] > 255) {
                          inRGB[i] = 255;
                      }
                      else if (inRGB[i] < 0) {
                          inRGB[i] = 0;
                      }
                  }
  
                  // Get pixel value...
                  // It is VERY important that we are using a IndexColorModel that
                  // support reverse color lookup for speed.
                  pixel = pColorModel.getDataElements(toIntARGB(inRGB), pixel);
  
                  // ...set it...
                  pDest.setDataElements(x, y, pixel);
  
                  // ..and get back the closet match
                  pDest.getPixel(x, y, outRGB);
  
                  // Convert the value to default sRGB
                  // Should work for all transfertypes supported by IndexColorModel
                  toRGBArray(pColorModel.getRGB(outRGB[0]), outRGB);
  
                  // Find diff
                  diff[0] = inRGB[0] - outRGB[0];
                  diff[1] = inRGB[1] - outRGB[1];
                  diff[2] = inRGB[2] - outRGB[2];
  
                  // Apply F-S error diffusion
                  // Serpentine scan: left-right
                  if (forward) {
                      // Row 1 (y)
                      // Update error in this pixel (x + 1)
                      currErr[x + 2][0] += diff[0] * 7;
                      currErr[x + 2][1] += diff[1] * 7;
                      currErr[x + 2][2] += diff[2] * 7;
  
                      // Row 2 (y + 1)
                      // Update error in this pixel (x - 1)
                      nextErr[x][0] += diff[0] * 3;
                      nextErr[x][1] += diff[1] * 3;
                      nextErr[x][2] += diff[2] * 3;
                      // Update error in this pixel (x)
                      nextErr[x + 1][0] += diff[0] * 5;
                      nextErr[x + 1][1] += diff[1] * 5;
                      nextErr[x + 1][2] += diff[2] * 5;
                      // Update error in this pixel (x + 1)
                      // TODO: Consider calculating this using
                      // error term = error - sum(error terms 1, 2 and 3)
                      // See Computer Graphics (Foley et al.), p. 573
                      nextErr[x + 2][0] += diff[0]; // * 1;
                      nextErr[x + 2][1] += diff[1]; // * 1;
                      nextErr[x + 2][2] += diff[2]; // * 1;
  
                      // Next
                      x++;
  
                      // Done?
                      if (x >= limit) {
                          break;
                      }
  
                  }
                  else {
                      // Row 1 (y)
                      // Update error in this pixel (x - 1)
                      currErr[x][0] += diff[0] * 7;
                      currErr[x][1] += diff[1] * 7;
                      currErr[x][2] += diff[2] * 7;
  
                      // Row 2 (y + 1)
                      // Update error in this pixel (x + 1)
                      nextErr[x + 2][0] += diff[0] * 3;
                      nextErr[x + 2][1] += diff[1] * 3;
                      nextErr[x + 2][2] += diff[2] * 3;
                      // Update error in this pixel (x)
                      nextErr[x + 1][0] += diff[0] * 5;
                      nextErr[x + 1][1] += diff[1] * 5;
                      nextErr[x + 1][2] += diff[2] * 5;
                      // Update error in this pixel (x - 1)
                      // TODO: Consider calculating this using
                      // error term = error - sum(error terms 1, 2 and 3)
                      // See Computer Graphics (Foley et al.), p. 573
                      nextErr[x][0] += diff[0]; // * 1;
                      nextErr[x][1] += diff[1]; // * 1;
                      nextErr[x][2] += diff[2]; // * 1;
  
                      // Previous
                      x--;
  
                      // Done?
                      if (x <= limit) {
                          break;
                      }
                  }
              }
  
              // Make next error info current for next iteration
              int[][] temperr;
              temperr = currErr;
              currErr = nextErr;
              nextErr = temperr;
  
              // Toggle direction
              if (alternateScans) {
                  forward = !forward;
              }
          }
  
          return pDest;
      }