bicubic interpolation

This commit is contained in:
laurenspriem 2024-03-12 17:06:42 +05:30
parent 5b3519ea38
commit 3b2fa3ba10

View file

@ -35,6 +35,7 @@ Color readPixelColor(
) {
if (x < 0 || x >= image.width || y < 0 || y >= image.height) {
// throw ArgumentError('Invalid pixel coordinates.');
log('[WARNING] `readPixelColor`: Invalid pixel coordinates, out of bounds');
return const Color(0x00000000);
}
assert(byteData.lengthInBytes == 4 * image.width * image.height);
@ -1078,7 +1079,7 @@ void warpAffineFloat32List(
final num yOrigin = (xTrans - b00) * a10Prime + (yTrans - b10) * a11Prime;
final Color pixel =
getPixelBilinear(xOrigin, yOrigin, inputImage, imgByteDataRgba);
getPixelBicubic(xOrigin, yOrigin, inputImage, imgByteDataRgba);
// Set the new pixel
outputList[startIndex + 3 * (yTrans * width + xTrans)] =
@ -1221,6 +1222,98 @@ Color getPixelBilinear(num fx, num fy, Image image, ByteData byteDataRgba) {
return Color.fromRGBO(r, g, b, 1.0);
}
/// Get the pixel value using Bicubic Interpolation. Code taken mainly from https://github.com/brendan-duncan/image/blob/6e407612752ffdb90b28cd5863c7f65856349348/lib/src/image/image.dart#L697
Color getPixelBicubic(num fx, num fy, Image image, ByteData byteDataRgba) {
fx = fx.clamp(0, image.width - 1);
fy = fy.clamp(0, image.height - 1);
final x = fx.toInt() - (fx >= 0.0 ? 0 : 1);
final px = x - 1;
final nx = x + 1;
final ax = x + 2;
final y = fy.toInt() - (fy >= 0.0 ? 0 : 1);
final py = y - 1;
final ny = y + 1;
final ay = y + 2;
final dx = fx - x;
final dy = fy - y;
num cubic(num dx, num ipp, num icp, num inp, num iap) =>
icp +
0.5 *
(dx * (-ipp + inp) +
dx * dx * (2 * ipp - 5 * icp + 4 * inp - iap) +
dx * dx * dx * (-ipp + 3 * icp - 3 * inp + iap));
final icc = readPixelColor(image, byteDataRgba, x, y);
final ipp =
px < 0 || py < 0 ? icc : readPixelColor(image, byteDataRgba, px, py);
final icp = px < 0 ? icc : readPixelColor(image, byteDataRgba, x, py);
final inp = py < 0 || nx >= image.width
? icc
: readPixelColor(image, byteDataRgba, nx, py);
final iap = ax >= image.width || py < 0
? icc
: readPixelColor(image, byteDataRgba, ax, py);
final ip0 = cubic(dx, ipp.red, icp.red, inp.red, iap.red);
final ip1 = cubic(dx, ipp.green, icp.green, inp.green, iap.green);
final ip2 = cubic(dx, ipp.blue, icp.blue, inp.blue, iap.blue);
// final ip3 = cubic(dx, ipp.a, icp.a, inp.a, iap.a);
final ipc = px < 0 ? icc : readPixelColor(image, byteDataRgba, px, y);
final inc =
nx >= image.width ? icc : readPixelColor(image, byteDataRgba, nx, y);
final iac =
ax >= image.width ? icc : readPixelColor(image, byteDataRgba, ax, y);
final ic0 = cubic(dx, ipc.red, icc.red, inc.red, iac.red);
final ic1 = cubic(dx, ipc.green, icc.green, inc.green, iac.green);
final ic2 = cubic(dx, ipc.blue, icc.blue, inc.blue, iac.blue);
// final ic3 = cubic(dx, ipc.a, icc.a, inc.a, iac.a);
final ipn = px < 0 || ny >= image.height
? icc
: readPixelColor(image, byteDataRgba, px, ny);
final icn =
ny >= image.height ? icc : readPixelColor(image, byteDataRgba, x, ny);
final inn = nx >= image.width || ny >= image.height
? icc
: readPixelColor(image, byteDataRgba, nx, ny);
final ian = ax >= image.width || ny >= image.height
? icc
: readPixelColor(image, byteDataRgba, ax, ny);
final in0 = cubic(dx, ipn.red, icn.red, inn.red, ian.red);
final in1 = cubic(dx, ipn.green, icn.green, inn.green, ian.green);
final in2 = cubic(dx, ipn.blue, icn.blue, inn.blue, ian.blue);
// final in3 = cubic(dx, ipn.a, icn.a, inn.a, ian.a);
final ipa = px < 0 || ay >= image.height
? icc
: readPixelColor(image, byteDataRgba, px, ay);
final ica =
ay >= image.height ? icc : readPixelColor(image, byteDataRgba, x, ay);
final ina = nx >= image.width || ay >= image.height
? icc
: readPixelColor(image, byteDataRgba, nx, ay);
final iaa = ax >= image.width || ay >= image.height
? icc
: readPixelColor(image, byteDataRgba, ax, ay);
final ia0 = cubic(dx, ipa.red, ica.red, ina.red, iaa.red);
final ia1 = cubic(dx, ipa.green, ica.green, ina.green, iaa.green);
final ia2 = cubic(dx, ipa.blue, ica.blue, ina.blue, iaa.blue);
// final ia3 = cubic(dx, ipa.a, ica.a, ina.a, iaa.a);
final c0 = cubic(dy, ip0, ic0, in0, ia0).clamp(0, 255).toInt();
final c1 = cubic(dy, ip1, ic1, in1, ia1).clamp(0, 255).toInt();
final c2 = cubic(dy, ip2, ic2, in2, ia2).clamp(0, 255).toInt();
// final c3 = cubic(dy, ip3, ic3, in3, ia3);
return Color.fromRGBO(c0, c1, c2, 1.0);
}
List<double> getAlignedFaceBox(AlignmentResult alignment) {
final List<double> box = [
// [xMinBox, yMinBox, xMaxBox, yMaxBox]