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

248
LINES

< > BotCompany Repo | #1035748 // G22DataWrangler

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

Libraryless. Click here for Pure Java version (32059L/200K).

// TODO: different sorting methods, e.g. "widest SSIs"
// Note: Blur is slow. e.g. 48ms for 2 screens
// Posterization is fast, e.g. 8ms for 2 screens
// Region making speed depends on how many regions there are.
// TODO: Make regions incrementally by starting at random pixels
sclass G22DataWrangler > Stages2 is IHasChangeListeners {
  replace Stage with Runnable.
  
  event change;
  
  settable BufferedImage inputImage;
  
  // try to re-use anything that is identical
  settable G22DataWrangler stealingFrom;
  
  settable bool withDiagonals = true;
  settableWithVar int blur = 0; // in pixels
  
  settableWithVar int colorsPerChannel = 2;
  
  settableWithVar float drift; // brightness drift for gradients (-1 to 1)
  settableWithVar float antiDrift; // brightness drift after rposterization gradients (-1 to 1)
  
  // kilobytes per compressed image (pessimistic estimate
  // counting 2 bytes for each int)
  settable TargetAndActual<Double> kilobytes = new(250.0);
  settable new TargetAndActual<Double> coveredPixelsPercentage;
  settable new TargetAndActual<Double> detailLevel;
  
  settable bool vectorize = true;
  settable bool allowPartialSSIs = true;
  
  gettable bool blackAndWhiteMode;
  
  settable SortMode sortMode = SortMode.compressibility;
  
  enum SortMode { compressibility, pixels }
  
  BufferedImage blurredImage;
  int maxLines, maxInts;
  L<? extends AbstractSSI> currentSSIs; // ssis at current stage
  L<SSI> initialSSIs;
  AbstractSSIList sortedSSIs, cutSSIs,
    vectorizedSSIs, cutVectorizedSSIs;
  CutListToBudget<AbstractSSI> cutter;
  
  // We store the posterized image as Hi15
  Hi15Image posterizedImage;
  
  // Region maker + regions
  
  FastRegions_Hi15Image regionMaker;
  L<IImageRegion<Hi15Image>> regions, regionsBySize;
  
  // Constructors
  
  *() {}
  *(BufferedImage *inputImage) {}
  *(MakesBufferedImage inputImage) { this.inputImage = inputImage.getBufferedImage(); }
  
  // Methods
  
  SinglePixelPosterizer posterizer() {
    ret new SinglePixelPosterizer(colorsPerChannel()).drift(drift).antiDrift(antiDrift);
  }
  
  selfType kb(TargetAndActual<Double> kb) { ret kilobytes(kb); }
  TargetAndActual<Double> kb() { ret kilobytes; }
  
  WidthAndHeight resolution() {
    ret imageSize(inputImage);
  }

  double detailDivisor() {
    ret areaRoot(inputImage);
  }
  
  int colors() {
    ret blackAndWhiteMode ? 2 : cubed(colorsPerChannel());
  }
  
  transient simplyCached FieldVar<Int> varColors() {
    ret new FieldVar<Int>(this, "colors", l0 colors, l1 colors);
  }
  
  // choose number of colors for posterized image
  selfType colors(int colors) {
    int perChannel = iceil(cbrt(colors));
    blackAndWhiteMode = colors == 2;
    ret colorsPerChannel(perChannel);
  }
  
  stage "Steal" {
    if (stealingFrom != null) {
      if (stealingFrom.inputImage != inputImage)
        ret with stealingFrom = null;
        
      // Avoid keeping old data wranglers around through a stealingFrom chain
      stealingFrom.stealingFrom = null;
    }
  }

  stage "Blur" {
    if (stealingFrom != null)
      if (stealingFrom.blur == blur)
        ret with blurredImage = stealingFrom.blurredImage;
      else
        stealingFrom = null;
    blurredImage = blurBufferedImage(blur, inputImage);
  }
  
  stage posterizeStage "Posterize" {
    if (stealingFrom != null)
      if (eq(stealingFrom.posterizer(), posterizer()))
        ret with posterizedImage = stealingFrom.posterizedImage;
      else
        stealingFrom = null;
        
    var image = blurredImage;
    if (blackAndWhiteMode)
      image = BWImage(image).getBufferedImage();
      //image = transformBufferedImageWithSimplePixelOp(image, rgb -> 0xFFFFFF, ...);
    posterizedImage = posterizeBufferedImageToHi15(image, posterizer());
  }
  
  stage prepareRegionsStage "Prepare regions" {
    if (stealingFrom != null)
      if (stealingFrom.withDiagonals == withDiagonals) {
        regionMaker = stealingFrom.regionMaker;
        regions = stealingFrom.regions;
        ret;
      } else
        stealingFrom = null;
        
    regionMaker = new FastRegions_Hi15Image(posterizedImage);
    regionMaker.withDiagonals(withDiagonals);
  }
  
  stage regionsStage "Regions" {
    regions = regionMaker!;
  }
  
  stage biggestRegionsStage "Sort regions" {
    regions = regionsBySize = biggestRegionsFirst(regions);
  }
  
  stage "SSIs" {
    initialSSIs = new L;
    for (region : regions)
      initialSSIs.addAll(new G22_RegionToSSIs_v2(region).withDiagonals (withDiagonals)!);
    currentSSIs = initialSSIs;
  }
  
  int initialSSILines() {
    ret totalSSILines(initialSSIs);
  }
  
  stage "Vector-Optimize" {
    currentSSIs = vectorizedSSIs = vectorize
      ? new VectorOptimizedSSIList(currentSSIs)
      : new GeneralSSIList(currentSSIs);
  }
  
  stage "Sort SSIs" {
    if (sortMode == SortMode.compressibility)
      sortedSSIs = new GeneralSSIList(sortedDesc(currentSSIs, (a, b) -> {
        int x = cmp(a.compressibility(), b.compressibility());
        if (x != 0) ret x;
        ret cmp(a.numberOfPixels(), b.numberOfPixels());
      }));
    else if (sortMode == SortMode.pixels)
      sortedSSIs = new GeneralSSIList(biggestSSIsFirst(currentSSIs));
    else
      fail("Unknown sort mode");
    currentSSIs = sortedSSIs;
  }
  
  stage "Cut SSI List by detail level" {
    maxLines = !detailLevel.hasTarget() ? Int.MAX_VALUE
      : iround(detailDivisor()*detailLevel.target());
    currentSSIs = cutSSIs = new GeneralSSIList(takeFirstNSSILines(maxLines, currentSSIs));
    detailLevel.set(l(cutSSIs)/detailDivisor());
  }
  
  stage "Cut Vector-Optimized SSIs by file size" {
    maxInts = !kilobytes.hasTarget() ? Int.MAX_VALUE
      : iround(kilobytes.target()*512); // assuming 16 bit ints
    cutter = new CutListToBudget<AbstractSSI>(ssi -> (double) ssi.sizeInInts(), maxInts, (L) currentSSIs);
    
    if (allowPartialSSIs)
      cutter.allowPartial((ssi, budget) -> ssi.reduceToInts(iround(budget)));
      
    currentSSIs = cutVectorizedSSIs = new GeneralSSIList(cutter!);
    kilobytes.set(totalSizeInInts(cutVectorizedSSIs)/512.0);
  }
  
  L<IImageRegion<Hi15Image>> regions() {
    stepUntilStage(regionsStage);
    ret regions;
  }
  
  L<IImageRegion<Hi15Image>> regionsBySize() {
    stepUntilStage(biggestRegionsStage);
    ret regions;
  }
  
  L<IBinaryImage> regionsAsIBinaryImages() {
    ret map regionToIBinaryImage(regions());
  }
  
  BlurAndPosterizeSettings bnpSettings() {
    ret new BlurAndPosterizeSettings()
      .blur(blur)
      .colors(colors())
      .colorDrift(new RGB(drift()))
      .antiDrift(new RGB(antiDrift));
  }
  
  void importSettings(BlurAndPosterizeSettings bnp) {
    blur(bnp.blur);
    colors(bnp.colors);
    drift(bnp.colorDrift.brightness());
    antiDrift(bnp.antiDrift.brightness());
  }
  
  FastRegions_Hi15Image preparedRegionMaker() {
    stepUntilStage(prepareRegionsStage);
    ret regionMaker;
  }
  
  FastRegions_Hi15Image regionMaker() {
    stepUntilStage(regionsStage);
    ret regionMaker;
  }
  
  toString {
    ret commaCombine(
      shortClassName(this),
      imageSize(inputImage),
      "completed stages: " + or2(joinWithComma(completedStages()), "-")
    );
  }
  
  Hi15Image posterizedImage() {
    stepUntilStage(posterizeStage);
    ret posterizedImage;
  }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): elmgxqgtpvxh, mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1035748
Snippet name: G22DataWrangler
Eternal ID of this version: #1035748/89
Text MD5: 61be3468a1aef32a57c634f5fc256d74
Transpilation MD5: 7ebeeb6c5b2c186a0425205b7812994c
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-02-13 18:29:23
Source code size: 7556 bytes / 248 lines
Pitched / IR pitched: No / No
Views / Downloads: 341 / 828
Version history: 88 change(s)
Referenced in: #1003674 - Standard Classes + Interfaces (LIVE continued in #1034167)
#1035995 - G22DataWrangler backup before color drift