Как клонировать BufferedImage
У меня есть объект, в котором есть много bufferedimages, я хочу создать новый объект, копирующий все bufferedimages в новый объект, но эти новые изображения могут быть изменены, и я не хочу, чтобы исходные изображения объектов изменялись путем изменения изображений новых объектов.
- это ясно?
Можно ли это сделать, и может ли кто-нибудь предложить хороший способ сделать это, пожалуйста?
Я думал о getSubImage, но где-то читал, что любые изменения в этом изображении возвращаются обратно к родительскому изображению.
Я просто хочу получить новую совершенно отдельную копию или клон BufferedImage
Ответы
Ответ 1
Что-то вроде этого?
static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
Ответ 2
Я делаю это:
public static BufferedImage copyImage(BufferedImage source){
BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
Graphics g = b.getGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
return b;
}
Он работает достаточно хорошо и прост в использовании.
Ответ 3
Ранее упомянутая процедура терпит неудачу при применении к дополнительным изображениям. Вот более полное решение:
public static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
Ответ 4
Класс BufferedImage не реализует интерфейс Cloneable. Таким образом, метод клона не переоценивается. Здесь альтернатива для метода глубокой копии:
Совет по языку 76: альтернатива методу глубокой копии
Ответ 5
Это было безумно полезно для программы, которую я использую, чтобы рисовать вещи, и не смог реализовать Undo/Redo из-за того, что BufferedImages на стеках был практически одним и тем же.
Кстати, я предлагаю все, используя пару стеков для этих операций!
Каждый раз, когда вы что-то делаете, сразу создайте новое изображение, используйте метод deepCopy, упомянутый выше.
image = deepCopy((BufferedImage) stackUndo.peek());
измените изображение по своему усмотрению, затем, когда вы прекратите редактирование (например, когда вы отпустите кнопку мыши) сделайте
stackUndo.push(image);
и всегда красьте элемент в верхней части левого стека
g.drawImage(stackUndo.peek(),x,y,null);
а затем, если вы выполните операцию отмены/повтора, выполните следующие действия:
public void undoOrRedo(String op) {
if(op.equals("undo") && stackUndo.size()>1){
stackRedo.push(stackUndo.pop());
repaint();
}
if(op.equals("redo") && stackRedo.size()>0){
stackUndo.push(stackRedo.pop());
repaint();
}
}
обязательно оставите что-то в левом стеке, потому что для рисования всегда будет использоваться элемент вверху (peek)!
Ответ 6
Другой способ - использовать класс Graphics2D
для рисования изображения на новом пустом изображении. Это на самом деле не клонирует изображение, но оно приводит к копированию создаваемого изображения.
public static final BufferedImage clone(BufferedImage image) {
BufferedImage clone = new BufferedImage(image.getWidth(),
image.getHeight(), image.getType());
Graphics2D g2d = clone.createGraphics();
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return clone;
}
Ответ 7
Я знаю, что этот вопрос довольно старый, но для будущих посетителей, здесь решение, которое я бы использовал:
Image oldImage = getImage();
Image newImage = oldImage.getScaledInstance(oldImage.getWidth(null), oldImage.getHeight(null), Image.SCALE_DEFAULT);
Пожалуйста, исправьте меня, если изменение только что полученного newImage
также влияет на исходное изображение любым способом.
- > Javadoc для getScaledInstance
- > Javadoc для SCALE_DEFAULT (остальные константы перечислены чуть ниже этого)