Для нужд моей программы я создал средство искажения изображения и размещения его на карте (моя программа - это программа на основе карты).
Я написал свой собственный механизм для размещения и искажения изображения, используя три точки, которые помещаются на изображение, три точки, которые помещаются на карту, а затем, что я просто делаю, создаю AffineTransform, который преобразует первый треугольник.во-вторых, фактически размещая изображение именно там, где я хочу, и преобразовывая его в соответствии с желаниями пользователя.
Проблема в том, что с AffineTransforms вы можете выполнять только самые базовые преобразования.Вы можете переводить, вращать, масштабировать и искажать изображение.Этого достаточно для большинства случаев, но недавно я хотел реализовать 4-точечное преобразование, аналогичное бесплатному преобразованию в Photoshop.
Я провел некоторое исследование и обнаружил преобразование перспективы JAI, которое с помощью WarpPerspective позволяет достичь того, чего я хочу,У меня изначально была одна проблема с прозрачностью результирующего фона преобразованного изображения, но я также нашел решение этой проблемы.Вот код, который у меня есть:
package com.hampton.utils;
import java.awt.Dimension;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.ImageLayout;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.PerspectiveTransform;
import javax.media.jai.PlanarImage;
import javax.media.jai.RasterFactory;
import javax.media.jai.RenderedOp;
import javax.media.jai.WarpPerspective;
import javax.media.jai.operator.CompositeDescriptor;
/**
* @author Savvas Dalkitsis
*/
public class PerspectiveTransformation {
public static PlanarImage getPrespective(PlanarImage img) {
int numBands = img.getSampleModel().getNumBands();
ParameterBlock pb = new ParameterBlock();
pb.add(new Float(img.getWidth())).add(new Float(img.getHeight()));
pb.add(new Byte[]{new Byte((byte)0xFF)});
RenderedOp alpha = JAI.create("constant", pb);
pb = new ParameterBlock();
pb.addSource(img).addSource(img);
pb.add(alpha).add(alpha).add(Boolean.FALSE);
pb.add(CompositeDescriptor.DESTINATION_ALPHA_LAST);
SampleModel sm =
RasterFactory.createComponentSampleModel(img.getSampleModel(),
DataBuffer.TYPE_BYTE,
img.getTileWidth(),
img.getTileHeight(),
numBands + 1);
ColorSpace cs =
ColorSpace.getInstance(numBands == 1 ?
ColorSpace.CS_GRAY : ColorSpace.CS_sRGB);
ColorModel cm =
RasterFactory.createComponentColorModel(DataBuffer.TYPE_BYTE,
cs, true, false,
Transparency.BITMASK);
ImageLayout il = new ImageLayout();
il.setSampleModel(sm).setColorModel(cm);
RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, il);
RenderedOp srca = JAI.create("composite", pb, rh);
Dimension d = new Dimension(img.getWidth(),img.getHeight());
PerspectiveTransform p = PerspectiveTransform.getQuadToQuad(0, 0, d.width, 0, d.width, d.height, 0, d.height, 100, 0, 300, 0, d.width, d.height, 0, d.height);
WarpPerspective wp = new WarpPerspective(p);
pb = (new ParameterBlock()).addSource(srca);
pb.add(wp);
pb.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC));
PlanarImage i = (PlanarImage)JAI.create("warp",pb);
return i;
}
}
Это работает (я для простоты жестко закодировал преобразование, позже я включу его в свою систему преобразования только на этот раз, вместо этого я буду использовать 4 очка)из 3).
Проблема, с которой я столкнулся, заключается в том, что до сих пор с моим старым методом все, что мне нужно было сделать, это сохранить AffineTransform (который отображает изображение на карту) и просто выполнить g2.drawImage (imgтрансформируй) и все было хорошо.Это было действительно быстро, и это работало как очарование.Моя проблема сейчас заключается в том, что создание преобразованного PlanarImage занимает много времени (2-3 секунды) и, следовательно, бесполезно для использования в реальном времени.Я знаю, что могу просто сохранить преобразованное изображение, а затем нарисовать то, что будет действительно быстрым, но причина, по которой я этого хочу, заключается в том, что в моем механизме преобразования из 3 точек я предоставляю представление о результирующем преобразовании в реальном времени.Когда пользователь перетаскивает каждую из точек, он сразу видит полученное изображение.
Мой вопрос: есть ли быстрый способ использовать WarpPerspectives в Graphics2D?Я ищу что-то похожее на метод Graphics2D draw (Image, AffineTransform).Или, если у вас есть сторонняя библиотека преобразования изображений, которая работает очень быстро, это также приветствуется.