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

152
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 (6291L/39K).

final sclass BWIntegralImage implements MakesBufferedImage, IBWIntegralImage {
  int w, h;
  int[] data; // 1 entry per pixel
  ifdef BWIntegralImage_CountAccesses
    long accesses;
  endifdef
  
  *() {}
  *(File f) { this(loadImage2(f)); }
  
  *(MakesBufferedImage img) { this(toBufferedImage(img)); }
  
  //*(BufferedImage img) { this(BWImage(img)); }
  
  *(BufferedImage image) ctex {
    alloc(image.getWidth(), image.getHeight());
    
    pcall {
      GrabbableIntPixels gp = grabbableIntPixels(image);
      if (gp != null) ret with grab(gp);
    }
    
    // Use pixelGrabber if quick method fails
    PixelGrabber pixelGrabber = new(image, 0, 0, w, h, data, 0, w);
    if (!pixelGrabber.grabPixels())
      fail("Could not grab pixels");
      
    grab(GrabbableIntPixels(data, w, h, 0, w));
  }
  
  *(GrabbableIntPixels gp) {
    alloc(gp.w, gp.h);
    grab(gp);
  }
  
  void grab(GrabbableIntPixels gp) {
    ifdef BWIntegralImage_debug
      print("BWIntegralImage grabbing: " + gp);
    endifdef
    int offset = gp.offset;
    int[] image = gp.data;
    int sum = 0;
    for x to w: {
      int packed = image[offset+x];
      int brightness = packedToBrightness(packed);
      data[x] = (sum += brightness);
    }
    
    ifdef BWIntegralImage_useVectorAPI
      import jdk.incubator.vector.*;
      VectorSpecies<Int> species = IntVector.SPECIES_PREFERRED;
      int upperBound = species.loopBound(w);
    endifdef

    int scanlineExtra = gp.scanlineStride-w;
    int iImage = offset+gp.scanlineStride, i = w;
    for (int y = 1; y < h; y++) {
      sum = 0;
      ifdef BWIntegralImage_useVectorAPI
        int x = 0;
        for (; x < upperBound; x += species.length(), iImage += species.length(), i += species.length()) {
          for (int sub = 0; sub < species.length(); sub++) {
            sum += packedToBrightness(image[iImage+sub]);
            data[i+sub] = sum;
          }
          
          IntVector v = IntVector.fromArray(species, data, i);
          IntVector v_last = IntVector.fromArray(species, data, i-w);
          v = v.add(v_last);
          v.intoArray(data, i);
        }

        for (; x < w; x++, iImage++, i++) {
          int packed = image[iImage];
          int brightness = packedToBrightness(packed);
          sum += brightness;
          data[i] = sum + data[i-w];
        }
      endifdef
      
      ifndef BWIntegralImage_useVectorAPI
        for x to w: {
          int packed = image[iImage];
          int brightness = packedToBrightness(packed);
          sum += brightness;
          data[i] = sum + data[i-w];
          iImage++; i++;
        }
      endifndef
      
      iImage += scanlineExtra;
    } // for y
  }
    
  *(BWImage img) {
    alloc(img.w(), img.h());
    data = new int[w*h];
    int i = 0;
    for y to h: {
      int sum = 0;
      for x to w: {
        sum += img.getByte(x, y) & 0xFF;
        data[i] = y > 0 ? sum + data[i-w] : sum;
        i++;
      }
    }
  }
  
  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 || x >= w || y >= h ? 0
      : data[min(y, h-1)*w+min(x, w-1)];
  }
  
  public int getIIValue(int x, int y) { 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; }
  
  // unoptimized
  public BufferedImage getBufferedImage() {
    ret scaleDownUsingIntegralImageBW(this, w).getBufferedImage();
  }
  
  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
  }
}

Author comment

Began life as a copy of #1019588

download  show line numbers  debug dex   

Travelled to 12 computer(s): bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, 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/41
Text MD5: 63d7674af93850d35b1cd0ea23596016
Transpilation MD5: 985c0d96091cad3eece15db7eea06a5b
Author: stefan
Category: javax / imaging
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-01-07 19:15:13
Source code size: 4303 bytes / 152 lines
Pitched / IR pitched: No / No
Views / Downloads: 263 / 761
Version history: 40 change(s)
Referenced in: [show references]

Formerly at http://tinybrain.de/1019595 & http://1019595.tinybrain.de