Carregada para um BufferedImage e acessada através de getRGB(), com ajuda de getWidth() e getHeight(), uma imagem é basicamente uma matriz de cores. Você deve estar tendo problemas para visualizar isso, mas você já tem o que precisa para criar seu algoritmo que aplica uma transformação nesses pixels.
Com os pixels de cor da imagem, você pode fazer o que quiser: multiplicar cores, duplicá-los em outra matriz, subtrair cores, tirar a média das cores, aumentar a quantidade de pixels, etc. O algoritmo que fará isso depende de você (que são esses que você quer implementar), mas você já tem a base para o que quer.
Exemplo de carregamento de imagem e pegar cor do pixel:
BufferedImage img = ImageIO.read(new File("C:\\teste\\image.png")); // o path da imagem pode variar, obviamente
int w = img.getWidth();
int h = img.getHeight();
for(int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
Color original = new Color(img.getRGB(i, j)); // agora "original" contém a cor do pixel
// aplique o algoritmo que quiser sobre esse pixel
}
}
Você també pode criar um BufferedImage vazio. Para criar uma imagem 2 vezes maior que a original, você só precisa multiplicar:
BufferedImage newImage = new BufferedImage(w * 2, h * 2, BufferedImage.TYPE_INT_ARGB); // o type, último parâmetro pode variar
e fazer o que quiser com newImage.
Para salvar:
ImageIO.write(newImage, "png", new File("C:\\teste\\newimage.png")); // o tipo e o path de destino podem variar
Abraço.