Rotate a BMP image in java without libraries java - java

This code works, it reads a file in byte type and after assigning the image it creates a copy in the directory where the other part is located with a different name, I must do the same, create a new file, I just have to make it rotate on the X and Y axes as the final 180 degree image without creating a library to do the job.
Can you help me with the code or madnar information
Thank you!
public class BMPRotations {
public static void main(String[] args) throws IOException {
int contador=0;
int datos_entrada[] = new int[921655];
try {
FileInputStream archivo_lectura = new FileInputStream("Ruta__picture.bmp");
boolean final_ar = false;
while(!final_ar) {
int byte_entrada = archivo_lectura.read();
if(byte_entrada!=-1)
datos_entrada[contador]=byte_entrada;
else
final_ar=true;
//Muestra todos los bytes
//System.out.println(datos_entrada[contador]);
contador++;
}
archivo_lectura.close();
}catch(IOException e) {
System.out.print("Error");
}
System.out.print("Bystes de la imagen: " + contador);
crea_fichero(datos_entrada);
}
static void crea_fichero(int datos_nuevo_fichero[]) {
try {
FileOutputStream fichero_nuevo = new FileOutputStream("Ruta_picture.bmp");
for(int i=0; i<datos_nuevo_fichero.length;i++) {
fichero_nuevo.write(datos_nuevo_fichero[i]);
}
fichero_nuevo.close();
}catch(IOException e) {
System.out.println("Error ");
}
}
Here is a reference image.
640X480 in 24-bit format
https://i.stack.imgur.com/pz4A4.png

This isn't a full answer but I hope it points you in right direction for what looks like homework.
What you have implemented so far is simply copying a file with hard-coded size 921655, and does not deal with an image - just any file. You could replace the entire program with:
File input = new File("Ruta__picture.bmp");
File output = new File("Ruta_picture.bmp");
Files.copy(input.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING);
To deal with images, look at javax.imageio.ImageIO class. This shows how to load any supported JDK image type and write it back:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
BufferedImage image = ImageIO.read(input);
// TODO: TRANSFORM "image" here
BufferedImage modified = image;
ImageIO.write(modified , "bmp", output);
Note that ImageIO.write supports other types such as "jpg".

Related

How to convert one pdf to multiple png images with multithreading

I used the following method to convert a pdf into multiple png images:
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.imgscalr.Scalr;
public class ImgUtil {
public static List<String> convertPDFPagesToImages(String sourceFilePath, String desFilePath){
List<String> urlList = new ArrayList<>();
try {
File sourceFile = new File(sourceFilePath);
File destinationFile = new File(desFilePath);
if (!destinationFile.exists()) {
destinationFile.mkdir();
log.info("Folder Created ->:{} ", destinationFile.getAbsolutePath());
}
if (sourceFile.exists()) {
log.info("Images copied to Folder Location: ", destinationFile.getAbsolutePath());
PDDocument document = PDDocument.load(sourceFile);
PDFRenderer pdfRenderer = new PDFRenderer(document);
int numberOfPages = document.getNumberOfPages();
log.info("Total files to be converting ->{} ", numberOfPages);
String fileName = sourceFile.getName().replace(".pdf", "");
String fileExtension = "png";
/*
* 600 dpi give good image clarity but size of each image is 2x times of 300 dpi.
* Ex: 1. For 300dpi 04-Request-Headers_2.png expected size is 797 KB
* 2. For 600dpi 04-Request-Headers_2.png expected size is 2.42 MB
*/
int dpi = 300;// use less dpi for to save more space in harddisk. For professional usage you can use more than 300dpi
for (int i = 0; i < numberOfPages; ++i) {
File outPutFile = new File(desFilePath + fileName +"_"+ (i+1) +"."+ fileExtension);
BufferedImage bImage = pdfRenderer.renderImageWithDPI(i, dpi, ImageType.RGB);
ImageIO.write(bImage, fileExtension, outPutFile);
urlList.add(outPutFile.getPath().replaceAll("\\\\", "/"));
}
document.close();
log.info("Converted Images are saved at ->{} ", destinationFile.getAbsolutePath());
} else {
log.error(sourceFile.getName() +" File not exists");
}
} catch (Exception e) {
e.printStackTrace();
}
return urlList;
}
public static void main(String[] args) {
convertPDFPagesToImages("D:\\tmp\\report\\pdfPath\\61199020100754118.pdf", "D:\\tmp\\report\\pdfPath\\");
}
}
But I found that when the number of pdf pages is relatively large, the image conversion is slower. I consider using multithreading to parse the images. Is it possible to convert a pdf into a picture through multiple threads or is there a similar method?
A simple way to speed up this conversion would be to split image writing to a background thread. Set up an executorService before opening the PDF:
ExecutorService exec = Executors.newFixedThreadPool(1);
List<Future<?>> pending = new ArrayList<>();
Instead of writing the image in same calling thread, just submit a new task to the service:
// ImageIO.write(bImage, fileExtension, outPutFile);
pending.add(exec.submit(() -> write(bImage, fileExtension, outImage.toFile())));
And function to perform the task:
private static void write(BufferedImage image, String fileExtension, File file) {
try {
ImageIO.write(image, fileExtension, file);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
After closing the PDF document make sure the executor is finished:
for (Future<?> fut : pending) {
fut.get();
}
exec.shutdown();
exec.awaitTermination(365, TimeUnit.DAYS);
Using more than one thread for ImageIO.write may not benefit you as it is heavy IO operation but as I said in the comment, experiment with writing to a large ByteArrayOutputStream and then the file may also help on your specific hardware.

Java Image Processing: Why is the output image smaller in storage than the input image?

I'm learning Java Image Processing. Here is my code:
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class LoadImage {
public static void main(String[] args) {
int width = 1280;
int height = 720;
BufferedImage image = null;
// READ IMAGE
try {
File input_image = new File("E:\\SELF-TAUGHT LEARNING\\39. Image Processing with Java\\test-image.jpg");
image = new BufferedImage (width,height,BufferedImage.TYPE_INT_ARGB);
image = ImageIO.read(input_image);
System.out.println("Read successfully");
}
catch (IOException e) {
System.out.println("Error: " + e);
}
// WRITE IMAGE
try {
File output_image = new File("E:\\SELF-TAUGHT LEARNING\\39. Image Processing with Java\\test-image-output.jpg");
ImageIO.write(image, "jpg", output_image);
System.out.println("Writing successfully");
}
catch (IOException e) {
System.out.println("Error: "+ e);
}
}
}
So the input image is around 300kb. But the output image is only 48kb. Why? Thank you
If the image is the same resolution and quality after saving the new version, it's likely just a difference of metadata and formatting. It's also possible, however, that you are getting a lower quality image - if the original image had a high enough quality setting, it may not be noticeable when Java saves it at a lower quality.
Some things to check:
do the before and after images look different?
is the after image smaller in size?
I'm not very knowledgeable about Java, and don't know a lot about their image processing, but I would imagine there are methods for setting image size, resolution, and quality. I do, however, work with images a lot, and I know there are a lot of optimizations (especially in JPEG images) that you can do to reduce file size without affecting visual quality noticeably.

How to get the color of a pixel in a Java applet to produce a map?

I am working with a Java to create a small applet. I am interested if there is a way I can "scan" an image to get the color values of a certain pixel. I would prefer to not have to display the image on the screen, but if you find that is the only way, please tell me. I would ideally like to be able to have my applet scan an image file and create an image on the screen according to the image. Please try to keep the answers a little bit simple, as I am still getting used to all of the technical terms.
Thanks,
~Rane
What I have so far:
import java.applet.Applet;
public class LoadGuideImage {
Applet applet;
public LoadGuideImage(Applet applet){
this.applet = applet;
}
public String getPixelColor(String pathToImage, int Xpix, int Ypix){
int redC = 0;
int greenC = 0;
int blueC = 0;
//Get Pixel colors here and save to ints
return redC + " " + greenC + " " + blueC;
}
}
Are you suggesting something like this 'the other guy'?:
BufferedImage img = (BufferedImage) getImage(pathToImage);
System.out.println("Color: " + img.getRGB(3, 3));
getImage method:
public Image getImage(String path) {
Image img;
URL url = null;
try {
url = applet.getDocumentBase();
} catch (Exception e){
// TODO: handle exception
}
img = applet.getImage(url, path);
return img;
}
nice name by the way. So I was in the same position a while ago.
use this for your get image method, just tweak it and use it to benefit you:
public class ImageLoader {
public BufferedImage load(String path){
try {
return ImageIO.read(getClass().getResource(path));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I have a been making a game that uses individual pixels to load those pixels and then put tiles where certain pixels are located in the map. If you would like to take my code snippet from there let me know and ill hook you up :P

Can I tell what the file type of a BufferedImage originally was?

In my code, I have a BufferedImage that was loaded with the ImageIO class like so:
BufferedImage image = ImageIO.read(new File (filePath);
Later on, I want to save it to a byte array, but the ImageIO.write method requires me to pick either a GIF, PNG, or JPG format to write my image as (as described in the tutorial here).
I want to pick the same file type as the original image. If the image was originally a GIF, I don't want the extra overhead of saving it as a PNG. But if the image was originally a PNG, I don't want to lose translucency and such by saving it as a JPG or GIF. Is there a way that I can determine from the BufferedImage what the original file format was?
I'm aware that I could simply parse the file path when I load the image to find the extension and just save it for later, but I'd ideally like a way to do it straight from the BufferedImage.
As #JarrodRoberson says, the BufferedImage has no "format" (i.e. no file format, it does have one of several pixel formats, or pixel "layouts"). I don't know Apache Tika, but I guess his solution would also work.
However, if you prefer using only ImageIO and not adding new dependencies to your project, you could write something like:
ImageInputStream input = ImageIO.createImageInputStream(new File(filePath));
try {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(input);
BufferedImage image = reader.read(0); // Read the same image as ImageIO.read
// Do stuff with image...
// When done, either (1):
String format = reader.getFormatName(); // Get the format name for use later
if (!ImageIO.write(image, format, outputFileOrStream)) {
// ...handle not written
}
// (case 1 done)
// ...or (2):
ImageWriter writer = ImageIO.getImageWriter(reader); // Get best suitable writer
try {
ImageOutputStream output = ImageIO.createImageOutputStream(outputFileOrStream);
try {
writer.setOutput(output);
writer.write(image);
}
finally {
output.close();
}
}
finally {
writer.dispose();
}
// (case 2 done)
}
finally {
reader.dispose();
}
}
}
finally {
input.close();
}
BufferedImage does not have a "format"
Once the bytes have been translated into a BufferedImage the format of the source file is completely lost, the contents represent a raw byte array of the pixel information nothing more.
Solution
You should use the Tika library to determine the format from the original byte stream before the BufferedImage is created and not rely on file extensions which can be inaccurate.
One could encapsulate the BufferedImage and related data in class instance(s) like so:
final public class TGImage
{
public String naam;
public String filename;
public String extension;
public int layerIndex;
public Double scaleX;
public Double scaleY;
public Double rotation;
public String status;
public boolean excluded;
public BufferedImage image;
public ArrayList<String> history = new ArrayList<>(5);
public TGImage()
{
naam = "noname";
filename = "";
extension ="";
image = null;
scaleX = 0.0;
scaleY = 0.0;
rotation = 0.0;
status = "OK";
excluded = false;
layerIndex = 0;
addHistory("Created");
}
final public void addHistory(String str)
{
history.add(TGUtil.getCurrentTimeStampAsString() + " " + str);
}
}
and then use it like this:
public TGImage loadImage()
{
TGImage imgdat = new TGImage();
final JFileChooser fc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image Files", "jpg", "png", "gif", "tif");
fc.setFileFilter(filter);
fc.setCurrentDirectory(new File(System.getProperty("user.home")));
int result = fc.showOpenDialog(this); // show file chooser
if (result == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
System.out.println("Selected file extension is " + TGUtil.getFileExtension(file));
if (TGUtil.isAnImageFile(file))
{
//System.out.println("This is an Image File.");
try
{
imgdat.image = ImageIO.read(file);
imgdat.filename = file.getName();
imgdat.extension = TGUtil.getFileExtension(file);
info("image has been loaded from file:" + imgdat.filename);
} catch (IOException ex)
{
Logger.getLogger(TGImgPanel.class.getName()).log(Level.SEVERE, null, ex);
imgdat.image = null;
info("File not loaded IOexception: img is null");
}
} else
{
imgdat = null;
info("File not loaded: The requested file is not an image File.");
}
}
return imgdat;
}
Then you have everything relevant together in TGImage instance(s).
and perhaps use it in an imagelist like so:
ArrayList<TGImage> images = new ArrayList<>(5);

How do I convert images between CMYK and RGB in ColdFusion (Java)?

I have a need to convert images from CMYK to RGB - not necessarily back again, but hey, if it can be done...
With the release of ColdFusion 8, we got the CFImage tag, but it doesn't support this conversion; and nor does Image.cfc, or Alagad's Image Component.
However, it should be possible in Java; which we can leverage through CF. For example, here's how you might create a Java thread to sleep a process:
<cfset jthread = createObject("java", "java.lang.Thread")/>
<cfset jthread.sleep(5000)/>
I would guess a similar method could be used to leverage java to do this image conversion, but not being a Java developer, I don't have a clue where to start. Can anyone lend a hand here?
A very simple formula for converting from CMYK to RGB ignoring all color profiles is:
R = ( (255-C)*(255-K) ) / 255;
G = ( (255-M)*(255-K) ) / 255;
B = ( (255-Y)*(255-K) ) / 255;
This code requires CMYK values to be in rage of 0-255. If you have 0 to 100 or 0.0 to 1.0 you'll have to convert the values.
Hope this will get you started.
As for the java and ColdFusion interfacing, I'm sorry, but I have no idea how to do that.
I use the Java ImageIO libraries (https://jai-imageio.dev.java.net). They aren't perfect, but can be simple and get the job done. As far as converting from CMYK to RGB, here is the best I have been able to come up with.
Download and install the ImageIO JARs and native libraries for your platform. The native libraries are essential. Without them the ImageIO JAR files will not be able to detect the CMYK images. Originally, I was under the impression that the native libraries would improve performance but was not required for any functionality. I was wrong.
The only other thing that I noticed is that the converted RGB images are sometimes much lighter than the CMYK images. If anyone knows how to solve that problem, I would be appreciative.
Below is some code to convert a CMYK image into an RGB image of any supported format.
Thank you,
Randy Stegbauer
package cmyk;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
public class Main
{
/**
* Creates new RGB images from all the CMYK images passed
* in on the command line.
* The new filename generated is, for example "GIF_original_filename.gif".
*
*/
public static void main(String[] args)
{
for (int ii = 0; ii < args.length; ii++)
{
String filename = args[ii];
boolean cmyk = isCMYK(filename);
System.out.println(cmyk + ": " + filename);
if (cmyk)
{
try
{
String rgbFile = cmyk2rgb(filename);
System.out.println(isCMYK(rgbFile) + ": " + rgbFile);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
}
/**
* If 'filename' is a CMYK file, then convert the image into RGB,
* store it into a JPEG file, and return the new filename.
*
* #param filename
*/
private static String cmyk2rgb(String filename) throws IOException
{
// Change this format into any ImageIO supported format.
String format = "gif";
File imageFile = new File(filename);
String rgbFilename = filename;
BufferedImage image = ImageIO.read(imageFile);
if (image != null)
{
int colorSpaceType = image.getColorModel().getColorSpace().getType();
if (colorSpaceType == ColorSpace.TYPE_CMYK)
{
BufferedImage rgbImage =
new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
ColorConvertOp op = new ColorConvertOp(null);
op.filter(image, rgbImage);
rgbFilename = changeExtension(imageFile.getName(), format);
rgbFilename = new File(imageFile.getParent(), format + "_" + rgbFilename).getPath();
ImageIO.write(rgbImage, format, new File(rgbFilename));
}
}
return rgbFilename;
}
/**
* Change the extension of 'filename' to 'newExtension'.
*
* #param filename
* #param newExtension
* #return filename with new extension
*/
private static String changeExtension(String filename, String newExtension)
{
String result = filename;
if (filename != null && newExtension != null && newExtension.length() != 0);
{
int dot = filename.lastIndexOf('.');
if (dot != -1)
{
result = filename.substring(0, dot) + '.' + newExtension;
}
}
return result;
}
private static boolean isCMYK(String filename)
{
boolean result = false;
BufferedImage img = null;
try
{
img = ImageIO.read(new File(filename));
}
catch (IOException e)
{
System.out.println(e.getMessage() + ": " + filename);
}
if (img != null)
{
int colorSpaceType = img.getColorModel().getColorSpace().getType();
result = colorSpaceType == ColorSpace.TYPE_CMYK;
}
return result;
}
}
The tag cfx_image may be of use to you. I haven't used it in a while but I remember it had a ton of features.
Alternatively, you might be able to script a windows app such as Irfanview (via commandline using cfexecute) to process images.
Hope that helps
I know that this question is old, but I still encounter problems with CMYK images & ColdFusion. However, I just read a CMYK JPEG image using ColdFusion 10 and resaved it. The saved image was able to to be read using ColdFusion 9 (which is only capable of reading RGB JPEGs.) I'm not sure if this conversion is intentional or not and I don't currently have any way of identifying whether the source image's color profile is CMYK or not as the saved color profile still appears to be the same.
<cfset imgData = ImageRead(expandPath("./CMYK_image.jpg"))>
<cfset ImageWrite(imgData, expandPath("./Saved_image.jpg"))>

Categories