我是Java的初学者,只编写了一年。我的任务是对任何给定的图像造成扭曲。我最近在膨胀效应方面遇到了很多麻烦。我一直在谷歌周围进行研究,我发现这些链接非常有用:
https://math.stackexchange.com/questions/266250/explanation-of-this-image-warping-bulge-filter-algorithm Image Warping - Bulge Effect Algorithm
我尝试了这两个链接给我的算法,但我最终没有任何结果。
我们说我已经导入了一个100像素×100像素的图像,从下面的代码开始,我正确地使用了算法:
//modifiedImage is a global variable and contains the image that is 100x100
public BufferedImage buldge(){
double X = 0;
double Y = 0;
BufferedImage anImage = new BufferedImage (1000, 1000, BufferedImage.TYPE_INT_ARGB);
for(int x = 0; x < modifiedImage.getWidth(); x++){
for(int y = 0; y < modifiedImage.getHeight(); y++){
int rgb = modifiedImage.getRGB(x, y);
double newRadius = 0;
X = x - x/2;
Y = y - y/2;
double radius = Math.sqrt(X*X + Y*Y);
double angle = Math.atan2(X, Y);
newRadius = Math.pow(radius,1.5);
X = (int)(newRadius*Math.sin(angle));
Y = (int)(newRadius*Math.cos(angle));
anImage.setRGB((int)X, (int)Y,rgb);
}
}
return anImage;
}
问题是这段代码并没有真正凸显中间的图像。我制作了一个尺寸为1000x1000的新BufferedImage,因为原始像素的像素扩展得非常远,有些像素扩展到1000x1000以上。如果有人帮我展示这个代码中有关凸起效应的问题,我将不胜感激。
答案 0 :(得分:4)
我认为问题的一个(主要)部分是你在像素中计算凸起效果的半径。虽然我没有阅读您链接的主题中的所有答案,但似乎它们指的是纹理坐标 - 即0到1之间的值。
除此之外:使用当前的方法,您将遇到抽样问题。想象一下,输入图像中心的一个像素将被拉伸&#34;这样它就可以覆盖输出图像中的10x10像素区域。但是,您仍然只计算此像素的一个新位置。
想象一下,就像你从输入图像中获取像素,并将它们移动到输出图像中的新位置 - 但你必须反过来做:你必须检查输出图像中的每个像素,并且计算输入图像的哪个像素在那里移动。
我创造了一个小例子:它允许移动放大镜&#34;用鼠标在图像上。使用鼠标滚轮,您可以改变失真的强度。使用SHIFT + MouseWheel,您可以更改放大镜的大小。
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageBulgeTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridLayout(1, 1));
frame.getContentPane().add(new ImageBulgePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class ImageBulgePanel extends JPanel
{
private BufferedImage input;
private BufferedImage output;
private double bulgeStrength = 0.3;
private double bulgeRadius = 100;
ImageBulgePanel()
{
try
{
input = ImageIO.read(new File("lena512color.png"));
}
catch (IOException e1)
{
e1.printStackTrace();
}
addMouseMotionListener(new MouseAdapter()
{
@Override
public void mouseMoved(MouseEvent e)
{
updateImage(e.getX(), e.getY());
}
});
addMouseWheelListener(new MouseWheelListener()
{
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) ==
InputEvent.SHIFT_DOWN_MASK)
{
bulgeRadius += 10 * e.getWheelRotation();
System.out.println("bulgeRadius "+bulgeRadius);
}
else
{
bulgeStrength += 0.1 * e.getWheelRotation();
bulgeStrength = Math.max(0, bulgeStrength);
System.out.println("bulgeStrength "+bulgeStrength);
}
updateImage(e.getX(), e.getY());
}
});
}
@Override
@Transient
public Dimension getPreferredSize()
{
if (isPreferredSizeSet())
{
return super.getPreferredSize();
}
return new Dimension(input.getWidth(), input.getHeight());
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (output != null)
{
g.drawImage(output, 0, 0, null);
}
}
private void updateImage(int x, int y)
{
if (output == null)
{
output = new BufferedImage(
input.getWidth(), input.getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
computeBulgeImage(input, x, y,
bulgeStrength, bulgeRadius,
output);
repaint();
}
private static void computeBulgeImage(
BufferedImage input, int cx, int cy,
double bulgeStrength, double bulgeRadius,
BufferedImage output)
{
int w = input.getWidth();
int h = input.getHeight();
for(int x = 0; x < w; x++)
{
for(int y = 0; y < h; y++)
{
int dx = x-cx;
int dy = y-cy;
double distanceSquared = dx * dx + dy * dy;;
int sx = x;
int sy = y;
if (distanceSquared < bulgeRadius * bulgeRadius)
{
double distance = Math.sqrt(distanceSquared);
boolean otherMethod = false;
otherMethod = true;
if (otherMethod)
{
double r = distance / bulgeRadius;
double a = Math.atan2(dy, dx);
double rn = Math.pow(r, bulgeStrength)*distance;
double newX = rn*Math.cos(a) + cx;
double newY = rn*Math.sin(a) + cy;
sx += (newX - x);
sy += (newY - y);
}
else
{
double dirX = dx / distance;
double dirY = dy / distance;
double alpha = distance / bulgeRadius;
double distortionFactor =
distance * Math.pow(1-alpha, 1.0 / bulgeStrength);
sx -= distortionFactor * dirX;
sy -= distortionFactor * dirY;
}
}
if (sx >= 0 && sx < w && sy >= 0 && sy < h)
{
int rgb = input.getRGB(sx, sy);
output.setRGB(x, y, rgb);
}
}
}
}
}