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 |