我需要创建分辨率极高的屏幕截图。由于分辨率大于渲染器支持的分辨率,因此需要将它们拆分为较小的分辨率并在以后拼接在一起。
我已经找到了矩形的拼接/渲染部分,但我正在努力寻找最适合每个拼贴的矩形分辨率。
我的渲染器限制为4096x4096。
对于像16384x16384这样的分辨率,这很容易弄明白:4 * 4矩形的4096x4096。
我的输入分辨率并不总是2的幂,但是一个这样的例子可能是5005x5000,最佳矩形大小为5 * 2矩形1001x2500。
我正在寻找的功能是,当给定所需的分辨率和最大分辨率时,输出最大分辨率内的分辨率,可以乘以达到所需的分辨率。
这样的事情:
public IntRect FindOptimalTileSize(IntRect desiredResolution, IntRect maximumTileSize)
{
//some magic
return new IntRect(magic.X, magic.Y);
}
连续的输出要求:
我曾尝试在互联网上搜索解决方案,但这些似乎都是针对不同的,更常见的用例。
可能无法始终找到满足我所有规则的矩形,在这种情况下,我希望函数返回可区分的内容,例如-1x-1
答案 0 :(得分:0)
我不是数学专家,但这可能会让你成为一个起点。这段代码是草图。它不是生产准备好的。它不具备测试质量。它只是一个草图,你将不得不做很多工作来清理它并使其可用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
int resultX = -1;
int resultY = -1;
int sourceX = 5005;
int sourceY = 5000;
int targetX = 4096;
int targetY = 4096;
if (sourceX <= targetX) { resultX = sourceX; }
if (sourceY <= targetY) { resultY = sourceY; }
if (IsValid(resultX, resultY)) {
// return the results
Console.WriteLine($"x={resultX}, y={resultY}");
return;
}
for (int index=targetX; 0 < index; index--) {
double result = (double)sourceX / index;
if (0 == result - (int)result) {
resultX = index;
break;
}
}
for (int index = targetY; 0 < index; index--) {
double result = (double)sourceY / index;
if (0 == result - (int)result) {
resultY = index;
break;
}
}
Console.WriteLine($"x={resultX}, y={resultY}");
Console.ReadKey(true);
}
static bool IsValid(int x, int y) {
return (-1 != x) && (-1 != y);
}
}
}
答案 1 :(得分:0)
您的问题可以分解为两个相同的问题:找到整数n的相等整数分区p,其中p <米。
使用扩展方法和一些助手,您可以生成n:
的素数因子分解static IEnumerable<int> PotentialPrimes() { // fails once int.MaxValue exceeded
yield return 2;
yield return 3;
var pp = 5;
for (; ; ) {
yield return pp;
yield return pp + 2;
pp += 6;
}
}
public static IEnumerable<int> Primes() {
return PotentialPrimes().Where(p => {
var sqrt = (int)Math.Floor(Math.Sqrt(p));
return !PotentialPrimes().TakeWhile(f => f <= sqrt)
.Any(f => p % f == 0);
});
}
public static IEnumerable<int> PrimeFactors(this int n) {
var maxDivisor = (int)Math.Floor(Math.Sqrt(n));
var testDivisors = Primes().TakeWhile(pp => pp < maxDivisor);
foreach (var f in testDivisors)
for (; n % f == 0; n /= f)
yield return f;
if (n != 1)
yield return n;
}
现在,使用素数分解,你可以找到小于m的最大p(根据注释,如果n> m,则返回n):
public static int LargestPartition(this int n, int maxPartitionSize) {
var factors = n.PrimeFactors().Where(f => f <= maxPartitionSize);
if (factors.Any()) {
var flist = factors.OrderByDescending(f => f).ToList();
var partition = flist.First();
foreach (var f in flist.Skip(1)) {
var tp = partition * f;
if (tp <= maxPartitionSize)
partition = tp;
}
return partition;
}
else
return n;
}
最后,只需将LargestPartition
应用于矩形的每一边:
public IntRect FindOptimalTileSize(IntRect desiredResolution, IntRect maximumTileSize) {
return new IntRect(desiredResolution.X.LargestPartition(maximumTileSize.X),
desiredResolution.Y.LargestPartition(maximumTileSize.Y));
}
注意:我更新了我的PrimeFactors
功能,以便更快地处理更多通用案例,以防有人遇到此问题。之前我无法在一小时内从2计算到int.MaxValue
,现在需要36秒。如果性能仍然是一个问题,Math.Sqrt
可以被替换,但我认为到那时其他开销将占主导地位。