我的 AffineTransformation 在像素之间有间隙
My AffineTransformation has gaps between pixels
首先我想说的是,我没有使用Oracle制作的AffineTransform class。我正在做我“自己的”仿射变换。为什么?我正在制作像素引擎,但找不到任何其他解决方案。所以我开始浏览 Wikipedia 以及矩阵的工作原理。然后我观看了 javidx9 的 video 如何实现它。我让它工作了。旋转、反射、剪切等效果很好,但我有一个像素间隙。 Javidx9 在他的视频中提到了这个问题,他解决了这个问题。我尝试了他的解决方案,但在进行反射、旋转和剪切时出现 "ArrayOutOfIndex 错误"。我一直在努力解决这个问题,但由于代码复杂,我无法理解我在做什么。这就是为什么我在这里!我需要你的帮助!
我是这样工作的(有间隙):
我用于间隙转换的代码如下:
用矩阵渲染图像
for (int x = 0; x < image2.getWidth(); x++)
{
for (int y = 0; y < image2.getHeight(); y++)
{
matrixLast.forward(x,y);
renderer.setPixel((int)matrixLast.getNx(),(int) matrixLast.getNy(), image2.getPixels()[x+y*image2.getWidth()], null, 255);
}
}
然而,如您所见,您需要的信息远不止于此。 我也做了一个“Matrix3x3”class,这里是重要的methods/functions:
public static void Identity(Matrix3x3 mat)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Translate(Matrix3x3 mat, float ox, float oy)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = ox;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = oy;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Rotate(Matrix3x3 mat, float degrees)
{
double fTheta = Math.toRadians(degrees);
mat.matrix[0][0] = (float)Math.cos(fTheta); mat.matrix[1][0] = (float)-Math.sin(fTheta); mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = (float)Math.sin(fTheta); mat.matrix[1][1] = (float)Math.cos(fTheta); mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Scale(Matrix3x3 mat, float sx, float sy)
{
mat.matrix[0][0] = sx; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = sy; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Shear(Matrix3x3 mat, float sx, float sy)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = sx; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = sy; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Reflection(Matrix3x3 mat) {
mat.matrix[0][0] = -1.0f; mat.matrix[1][0] = 0; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public void forward(float inX, float inY) { //Ingen aning vad denna gör
float outX,outY;
outX = (inX * this.matrix[0][0]) + (inY * this.matrix[1][0]) + this.matrix[2][0];
outY = (inX * this.matrix[0][1]) + (inY * this.matrix[1][1]) + this.matrix[2][1];
this.ny = outY;
this.nx = outX;
}
在上面看到的“渲染”代码中,您会看到其中有一个“matrixLast”。 这是我得到那个的方法(它们在别处定义为例如:“Matrix3x3 名称;”):
Matrix3x3.Translate(matrixFinal3, -image2.getWidth() / 2, -image2.getHeight() / 2);
Matrix3x3.Rotate(matrixFinal2,rotation); //Rotation och shear är det något fel på.
matrixSum = Matrix3x3.multiplyMatrix(matrixFinal2, matrixFinal3);
Matrix3x3.Translate(matrixFinal, 700, 600);
matrixLast = Matrix3x3.multiplyMatrix(matrixFinal, matrixSum);
matrixInv = Matrix3x3.invert(matrixLast);
我遇到的问题基本上是我正在尝试修复“差距”。我尝试了 Javidx9 的解决方案,它将渲染代码更改为以下内容(Utils.getMaximum() returns 最大的数字,而 Utils.getMinimum() 的相反) :
float ex,ey,sx,sy;
matrixLast.forward(0f, 0f);
sx = matrixLast.getNx();
ex = matrixLast.getNx();
sy = matrixLast.getNy();
ey = matrixLast.getNy();
matrixLast.forward((float) image2.getWidth(), (float) image2.getHeight());
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
matrixLast.forward(0f, (float) image2.getHeight());
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
matrixLast.forward((float) image2.getWidth(), 0f);
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
for(int x = (int)sx; x < (int)ex; x++) {
for(int y = (int)sy; y < (int)ey; y++) {
matrixInv.forward(x,y);
renderer.setPixel(x, y, image2.getPixels()[(int)(matrixInv.getNx() + 0.5) + (int)(matrixInv.getNy() + 0.5) * image2.getWidth()], null, 255);
}
}
他还添加了一个invert方法:
public static Matrix3x3 invert(Matrix3x3 matIn) {
float det = matIn.matrix[0][0] * (matIn.matrix[1][1] * matIn.matrix[2][2] - matIn.matrix[1][2] * matIn.matrix[2][1]) -
matIn.matrix[1][0] * (matIn.matrix[0][1] * matIn.matrix[2][2] - matIn.matrix[2][1] * matIn.matrix[0][2]) +
matIn.matrix[2][0] * (matIn.matrix[0][1] * matIn.matrix[1][2] - matIn.matrix[1][1] * matIn.matrix[0][2]);
float idet = 1.0f / det;
Matrix3x3 matOut = new Matrix3x3();
matOut.matrix[0][0] = (matIn.matrix[1][1] * matIn.matrix[2][2] - matIn.matrix[1][2] * matIn.matrix[2][1]) * idet;
matOut.matrix[1][0] = (matIn.matrix[2][0] * matIn.matrix[1][2] - matIn.matrix[1][0] * matIn.matrix[2][2]) * idet;
matOut.matrix[2][0] = (matIn.matrix[1][0] * matIn.matrix[2][1] - matIn.matrix[2][0] * matIn.matrix[1][1]) * idet;
matOut.matrix[0][1] = (matIn.matrix[2][1] * matIn.matrix[0][2] - matIn.matrix[0][1] * matIn.matrix[2][2]) * idet;
matOut.matrix[1][1] = (matIn.matrix[0][0] * matIn.matrix[2][2] - matIn.matrix[2][0] * matIn.matrix[0][2]) * idet;
matOut.matrix[2][1] = (matIn.matrix[0][1] * matIn.matrix[2][0] - matIn.matrix[0][0] * matIn.matrix[2][1]) * idet;
matOut.matrix[0][2] = (matIn.matrix[0][1] * matIn.matrix[1][2] - matIn.matrix[0][2] * matIn.matrix[1][1]) * idet;
matOut.matrix[1][2] = (matIn.matrix[0][2] * matIn.matrix[1][0] - matIn.matrix[0][0] * matIn.matrix[1][2]) * idet;
matOut.matrix[2][2] = (matIn.matrix[0][0] * matIn.matrix[1][1] - matIn.matrix[0][1] * matIn.matrix[1][0]) * idet;
return matOut;
}
这是他完全迷失了我的时候,它变得太复杂了,由于我不知道代码的确切作用,我不知道如何解决它。他的解决方案给了我一个 ArrayOutOfIndex 错误,但仅在进行反射、旋转和剪切时出现:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -9 out of bounds for length 589824
at com.dubstepzedd.gameengine.gamemanager.GameManager.render(GameManager.java:112)
at com.dubstepzedd.gameengine.GameContainer.loop(GameContainer.java:94)
at com.dubstepzedd.gameengine.GameContainer.run(GameContainer.java:48)
at java.base/java.lang.Thread.run(Thread.java:832)
at com.dubstepzedd.gameengine.GameContainer.start(GameContainer.java:40)
at com.dubstepzedd.gameengine.gamemanager.GameManager.main(GameManager.java:178)
我不知道为什么会这样。如果有人对如何以不同的方式处理“差距”情况或代码有什么问题有任何建议,请发表评论或post提问
更新
这是我添加 getPixel() 时的行为:
添加到图片的代码class:
public int getPixel(int x, int y) {
if(0 <= x && x < this.width && 0 <= y && y < this.height) {
return pixels[x+y*this.width];
}
else {
return Color.black.getRGB();
}
}
您正在尝试访问原始图像之外的像素:
image2.getPixels()[(int)(matrixInv.getNx() + 0.5) + (int)(matrixInv.getNy() + 0.5) * image2.getWidth()]
我建议为您的图像添加一种方法 class 如果 x 和 y 在范围内,returns 像素位于 x/y 位置,如果不在范围内,则使用默认颜色:
// add to image class:
int getPixel(int x, int y) {
if (0 <= x && x < width && 0 <= y && y < height) {
return pixelData[x + width*y];
} else {
return backgroundColor;
}
}
使用此方法代替数组查找 - 例如
for(int x = (int)sx; x < (int)ex; x++) {
for(int y = (int)sy; y < (int)ey; y++) {
matrixInv.forward(x,y);
int pixel = image2.getPixel((int)(matrixInv.getNx() + 0.5, (int)(matrixInv.getNy() + 0.5))
renderer.setPixel(x, y, pixel);
}
}
首先我想说的是,我没有使用Oracle制作的AffineTransform class。我正在做我“自己的”仿射变换。为什么?我正在制作像素引擎,但找不到任何其他解决方案。所以我开始浏览 Wikipedia 以及矩阵的工作原理。然后我观看了 javidx9 的 video 如何实现它。我让它工作了。旋转、反射、剪切等效果很好,但我有一个像素间隙。 Javidx9 在他的视频中提到了这个问题,他解决了这个问题。我尝试了他的解决方案,但在进行反射、旋转和剪切时出现 "ArrayOutOfIndex 错误"。我一直在努力解决这个问题,但由于代码复杂,我无法理解我在做什么。这就是为什么我在这里!我需要你的帮助!
我是这样工作的(有间隙):
我用于间隙转换的代码如下:
用矩阵渲染图像
for (int x = 0; x < image2.getWidth(); x++)
{
for (int y = 0; y < image2.getHeight(); y++)
{
matrixLast.forward(x,y);
renderer.setPixel((int)matrixLast.getNx(),(int) matrixLast.getNy(), image2.getPixels()[x+y*image2.getWidth()], null, 255);
}
}
然而,如您所见,您需要的信息远不止于此。 我也做了一个“Matrix3x3”class,这里是重要的methods/functions:
public static void Identity(Matrix3x3 mat)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Translate(Matrix3x3 mat, float ox, float oy)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = ox;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = oy;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Rotate(Matrix3x3 mat, float degrees)
{
double fTheta = Math.toRadians(degrees);
mat.matrix[0][0] = (float)Math.cos(fTheta); mat.matrix[1][0] = (float)-Math.sin(fTheta); mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = (float)Math.sin(fTheta); mat.matrix[1][1] = (float)Math.cos(fTheta); mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Scale(Matrix3x3 mat, float sx, float sy)
{
mat.matrix[0][0] = sx; mat.matrix[1][0] = 0.0f; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0.0f; mat.matrix[1][1] = sy; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Shear(Matrix3x3 mat, float sx, float sy)
{
mat.matrix[0][0] = 1.0f; mat.matrix[1][0] = sx; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = sy; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public static void Reflection(Matrix3x3 mat) {
mat.matrix[0][0] = -1.0f; mat.matrix[1][0] = 0; mat.matrix[2][0] = 0.0f;
mat.matrix[0][1] = 0; mat.matrix[1][1] = 1.0f; mat.matrix[2][1] = 0.0f;
mat.matrix[0][2] = 0.0f; mat.matrix[1][2] = 0.0f; mat.matrix[2][2] = 1.0f;
}
public void forward(float inX, float inY) { //Ingen aning vad denna gör
float outX,outY;
outX = (inX * this.matrix[0][0]) + (inY * this.matrix[1][0]) + this.matrix[2][0];
outY = (inX * this.matrix[0][1]) + (inY * this.matrix[1][1]) + this.matrix[2][1];
this.ny = outY;
this.nx = outX;
}
在上面看到的“渲染”代码中,您会看到其中有一个“matrixLast”。 这是我得到那个的方法(它们在别处定义为例如:“Matrix3x3 名称;”):
Matrix3x3.Translate(matrixFinal3, -image2.getWidth() / 2, -image2.getHeight() / 2);
Matrix3x3.Rotate(matrixFinal2,rotation); //Rotation och shear är det något fel på.
matrixSum = Matrix3x3.multiplyMatrix(matrixFinal2, matrixFinal3);
Matrix3x3.Translate(matrixFinal, 700, 600);
matrixLast = Matrix3x3.multiplyMatrix(matrixFinal, matrixSum);
matrixInv = Matrix3x3.invert(matrixLast);
我遇到的问题基本上是我正在尝试修复“差距”。我尝试了 Javidx9 的解决方案,它将渲染代码更改为以下内容(Utils.getMaximum() returns 最大的数字,而 Utils.getMinimum() 的相反) :
float ex,ey,sx,sy;
matrixLast.forward(0f, 0f);
sx = matrixLast.getNx();
ex = matrixLast.getNx();
sy = matrixLast.getNy();
ey = matrixLast.getNy();
matrixLast.forward((float) image2.getWidth(), (float) image2.getHeight());
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
matrixLast.forward(0f, (float) image2.getHeight());
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
matrixLast.forward((float) image2.getWidth(), 0f);
sx = Utils.getMinimum(sx, matrixLast.getNx()); sy = Utils.getMinimum(sy, matrixLast.getNy());
ex = Utils.getMaximum(ex, matrixLast.getNx()); ey = Utils.getMaximum(ey, matrixLast.getNy());
for(int x = (int)sx; x < (int)ex; x++) {
for(int y = (int)sy; y < (int)ey; y++) {
matrixInv.forward(x,y);
renderer.setPixel(x, y, image2.getPixels()[(int)(matrixInv.getNx() + 0.5) + (int)(matrixInv.getNy() + 0.5) * image2.getWidth()], null, 255);
}
}
他还添加了一个invert方法:
public static Matrix3x3 invert(Matrix3x3 matIn) {
float det = matIn.matrix[0][0] * (matIn.matrix[1][1] * matIn.matrix[2][2] - matIn.matrix[1][2] * matIn.matrix[2][1]) -
matIn.matrix[1][0] * (matIn.matrix[0][1] * matIn.matrix[2][2] - matIn.matrix[2][1] * matIn.matrix[0][2]) +
matIn.matrix[2][0] * (matIn.matrix[0][1] * matIn.matrix[1][2] - matIn.matrix[1][1] * matIn.matrix[0][2]);
float idet = 1.0f / det;
Matrix3x3 matOut = new Matrix3x3();
matOut.matrix[0][0] = (matIn.matrix[1][1] * matIn.matrix[2][2] - matIn.matrix[1][2] * matIn.matrix[2][1]) * idet;
matOut.matrix[1][0] = (matIn.matrix[2][0] * matIn.matrix[1][2] - matIn.matrix[1][0] * matIn.matrix[2][2]) * idet;
matOut.matrix[2][0] = (matIn.matrix[1][0] * matIn.matrix[2][1] - matIn.matrix[2][0] * matIn.matrix[1][1]) * idet;
matOut.matrix[0][1] = (matIn.matrix[2][1] * matIn.matrix[0][2] - matIn.matrix[0][1] * matIn.matrix[2][2]) * idet;
matOut.matrix[1][1] = (matIn.matrix[0][0] * matIn.matrix[2][2] - matIn.matrix[2][0] * matIn.matrix[0][2]) * idet;
matOut.matrix[2][1] = (matIn.matrix[0][1] * matIn.matrix[2][0] - matIn.matrix[0][0] * matIn.matrix[2][1]) * idet;
matOut.matrix[0][2] = (matIn.matrix[0][1] * matIn.matrix[1][2] - matIn.matrix[0][2] * matIn.matrix[1][1]) * idet;
matOut.matrix[1][2] = (matIn.matrix[0][2] * matIn.matrix[1][0] - matIn.matrix[0][0] * matIn.matrix[1][2]) * idet;
matOut.matrix[2][2] = (matIn.matrix[0][0] * matIn.matrix[1][1] - matIn.matrix[0][1] * matIn.matrix[1][0]) * idet;
return matOut;
}
这是他完全迷失了我的时候,它变得太复杂了,由于我不知道代码的确切作用,我不知道如何解决它。他的解决方案给了我一个 ArrayOutOfIndex 错误,但仅在进行反射、旋转和剪切时出现:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -9 out of bounds for length 589824
at com.dubstepzedd.gameengine.gamemanager.GameManager.render(GameManager.java:112)
at com.dubstepzedd.gameengine.GameContainer.loop(GameContainer.java:94)
at com.dubstepzedd.gameengine.GameContainer.run(GameContainer.java:48)
at java.base/java.lang.Thread.run(Thread.java:832)
at com.dubstepzedd.gameengine.GameContainer.start(GameContainer.java:40)
at com.dubstepzedd.gameengine.gamemanager.GameManager.main(GameManager.java:178)
我不知道为什么会这样。如果有人对如何以不同的方式处理“差距”情况或代码有什么问题有任何建议,请发表评论或post提问
更新
这是我添加 getPixel() 时的行为:
添加到图片的代码class:
public int getPixel(int x, int y) {
if(0 <= x && x < this.width && 0 <= y && y < this.height) {
return pixels[x+y*this.width];
}
else {
return Color.black.getRGB();
}
}
您正在尝试访问原始图像之外的像素:
image2.getPixels()[(int)(matrixInv.getNx() + 0.5) + (int)(matrixInv.getNy() + 0.5) * image2.getWidth()]
我建议为您的图像添加一种方法 class 如果 x 和 y 在范围内,returns 像素位于 x/y 位置,如果不在范围内,则使用默认颜色:
// add to image class:
int getPixel(int x, int y) {
if (0 <= x && x < width && 0 <= y && y < height) {
return pixelData[x + width*y];
} else {
return backgroundColor;
}
}
使用此方法代替数组查找 - 例如
for(int x = (int)sx; x < (int)ex; x++) {
for(int y = (int)sy; y < (int)ey; y++) {
matrixInv.forward(x,y);
int pixel = image2.getPixel((int)(matrixInv.getNx() + 0.5, (int)(matrixInv.getNy() + 0.5))
renderer.setPixel(x, y, pixel);
}
}