Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

253
LINES

< > BotCompany Repo | #1019595 // BWIntegralImage (size limit 8 megapixels, uses 4 byte per pixel)

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (13025L/76K).

// grayscale, actually
sclass BWIntegralImage > Meta implements IBWIntegralImage, IIntegralImage {
  int w, h;
  int[] data; // 1 entry per pixel
  ifdef BWIntegralImage_CountAccesses
    long accesses;
  endifdef
  
  // constructors
  
  *() {}
  *(File f) { this(loadImage2(f)); }
  *(MakesBufferedImage img) { this(toBufferedImage(img)); }
  *(BufferedImage image) { grab(image); }
  *(BufferedImage image, Decolorizer decolorizer) { grab(image, decolorizer); }
  *(GrabbableIntPixels gp) { grab(gp); }
  *(GrabbableRGBBytePixels gp) { grab(gp, new Decolorizer.Simple); }
  *(GrabbableGrayPixels gp) { grab(gp); }
  
  *(BWImage img) {
    grab(new GrabbableGrayPixels(img.pixels, img.width, img.height,
      0, img.width);
  }
  
  // grab functions
  
  void grab(BufferedImage image, Decolorizer decolorizer default null) {
    if (image.getType() == BufferedImage.TYPE_BYTE_GRAY)
      grab(grabbableGrayPixels(image));
    else { // rgb image
      var gp = grabbableRGBBytePixels(image);
      if (gp != null)
        grab(gp, decolorizer);
      else
        grab(grabbableIntPixels_fastOrSlow(image), decolorizer);
    }
  }

  void grab(GrabbableRGBBytePixels gp, Decolorizer decolorizer) {
    if (decolorizer == null) decolorizer = new Decolorizer.Simple;
    
    alloc(gp.w, gp.h);
    int w = this.w, h = this.h;
    ifdef BWIntegralImage_debug
      print("BWIntegralImage grabbing: " + gp);
    endifdef
    
    // first row
    
    int iImage = gp.offset, sum = 0, pixelStride = gp.pixelStride;
    byte[] image = gp.data;
    for x to w: {
      int packed = rgbInt(image[iImage], image[iImage+1], image[iImage+2]);
      iImage += pixelStride;
      int brightness = decolorizer.toGrayScale(packed);
      data[x] = (sum += brightness);
    }
    
    // subsequent rows
    
    var ping = pingSource();
    int scanlineExtra = gp.scanlineStride-w*pixelStride;
    iImage = gp.offset+gp.scanlineStride;
    int i = w;
    for (int y = 1; y < h; y++) {
      sum = 0;
      for x to w: {
        int packed = rgbInt(image[iImage], image[iImage+1], image[iImage+2]);
        iImage += pixelStride;
        int brightness = decolorizer.toGrayScale(packed);
        sum += brightness;
        data[i] = sum + data[i-w];
        i++;
      }

      iImage += scanlineExtra;
      ping?!;
    } // for y
  }
    
  void grab(GrabbableIntPixels gp, Decolorizer decolorizer) {
    if (isDefaultDecolorizer(decolorizer))
      ret with grab(gp);
    
    alloc(gp.w, gp.h);
    int w = this.w, h = this.h;
    ifdef BWIntegralImage_debug
      print("BWIntegralImage grabbing: " + gp);
    endifdef
    int offset = gp.offset, sum = 0;
    int[] image = gp.data;
    for x to w: {
      int packed = image[offset+x];
      int brightness = decolorizer.toGrayScale(packed);
      data[x] = (sum += brightness);
    }
    
    var ping = pingSource();
    int scanlineExtra = gp.scanlineStride-w;
    int iImage = offset+gp.scanlineStride, i = w;
    for (int y = 1; y < h; y++) {
      sum = 0;
      for x to w: {
        int packed = image[iImage];
        int brightness = decolorizer.toGrayScale(packed);
        sum += brightness;
        data[i] = sum + data[i-w];
        iImage++; i++;
      }

      iImage += scanlineExtra;
      ping?!;
    } // for y
  }
    
  void grab(GrabbableIntPixels gp) {
    alloc(gp.w, gp.h);
    int w = this.w, h = this.h;
    ifdef BWIntegralImage_debug
      print("BWIntegralImage grabbing: " + gp);
    endifdef
    int offset = gp.offset, sum = 0;
    int[] image = gp.data;
    for x to w: {
      int packed = image[offset+x];
      int brightness = packedToBrightness(packed);
      data[x] = (sum += brightness);
    }
    
    var ping = pingSource();
    int scanlineExtra = gp.scanlineStride-w;
    int iImage = offset+gp.scanlineStride, i = w;
    for (int y = 1; y < h; y++) {
      sum = 0;
      for x to w: {
        int packed = image[iImage];
        int brightness = packedToBrightness(packed);
        sum += brightness;
        data[i] = sum + data[i-w];
        iImage++; i++;
      }

      iImage += scanlineExtra;
      ping?!;
    } // for y
  }
  
  void grab(GrabbableGrayPixels gp) {
    alloc(gp.w, gp.h);
    ifdef BWIntegralImage_debug
      print("BWIntegralImage grabbing: " + gp);
    endifdef
    int offset = gp.offset, sum = 0;
    byte[] image = gp.data;
    for x to w: {
      int brightness = image[offset+x];
      data[x] = (sum += brightness);
    }
    
    var ping = pingSource();
    int scanlineExtra = gp.scanlineStride-w;
    int iImage = offset+gp.scanlineStride, i = w;
    for (int y = 1; y < h; y++) {
      sum = 0;
      for x to w: {
        int brightness = image[iImage];
        sum += brightness;
        data[i] = sum + data[i-w];
        iImage++; i++;
      }

      iImage += scanlineExtra;
      ping?!;
    } // for y
  }
    
  private void alloc(int w, int h) {
    this.w = w;
    this.h = h;
    if (w*h > 8*1024*1024)
      fail("Image too large (more than 8 MP): " + w + "*" + h);
    data = new int[w*h];
  }
  
  // pixels outside of image are considered black
  int get(int x, int y) {
    ifdef BWIntegralImage_CountAccesses
      ++accesses;
    endifdef
    ret x < 0 || y < 0 ? 0
      : data[min(y, h-1)*w+min(x, w-1)];
  }

  // precise version [TO TEST!]
  public double getIIValue(double x, double y) {
    int xFloor = ifloor(x), yFloor = ifloor(y);
    double val = getIIValue(xFloor, yFloor);
    
    // at integer coordinate?
    if (xFloor == x && yFloor == y)
      ret val;
      
    // at non-integer coordinate, perform subpixel calculation
    double val2 = getIIValue(xFloor+1, yFloor);
    double val3 = getIIValue(xFloor  , yFloor+1);
    double val4 = getIIValue(xFloor+1, yFloor+1);
    
    ret blend2D(val, val2, val3, val4, x-xFloor, y-yFloor);
  }
  
  public int getIIValue(int x, int y) { ret get(x, y); }
  public double getIntegralValue(int x, int y, int channel) {
    ret get(x, y);
  }
  
  public double getPixelAverage(int x1, int y1, int x2, int y2) {
    int area = (x2-x1)*(y2-y1);
    ret doubleRatio(bwIntegralImage_sumRect(this, x1, y1, x2, y2), area);
  }
  
  public int getWidth() { ret w; }
  public int getHeight() { ret h; }
  
  int packedToBrightness(int packed) {
    int b = (packed & 0xFF);
    ifdef BWIntegralImage_brightnessCheat
      ret b;
    endifdef
    ifndef BWIntegralImage_brightnessCheat
      int r = ((packed >> 16) & 0xFF);
      int g = ((packed >> 8) & 0xFF);
      ret (r+g+b+1)/3;
    endifndef
  }
  
  // get brightness of pixel
  public int getInt(int x, int y) {
    ret iround(rectSum(x, y, x+1, y+1, 0));
  }
  
  // returns RGB pixel without alpha
  public int getPixel(int x, int y) {
    ret rgbIntFromGrayscale(getInt(x, y));
  }
  
  public BufferedImage getBufferedImage() {
    //ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage();
    O src = metaGet src(this);
    if (src cast BufferedImage) ret src;
    
    ret grayImageFromIBWIntegralImage(this);
  }
}

Author comment

Began life as a copy of #1019588

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mowyntqkapby, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1019595
Snippet name: BWIntegralImage (size limit 8 megapixels, uses 4 byte per pixel)
Eternal ID of this version: #1019595/83
Text MD5: 1b7a72aaea4b10244a4587f77165c1d0
Transpilation MD5: 9720c55ad15b8e7c25bbe6b2ec3d2bd3
Author: stefan
Category: javax / imaging
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-03-26 03:47:14
Source code size: 7248 bytes / 253 lines
Pitched / IR pitched: No / No
Views / Downloads: 697 / 1602
Version history: 82 change(s)
Referenced in: [show references]