JavaCL - flip input image - java

I am using JavaCL and I want to rotate the image and save image back to "out.png".
Unfortunately the line of code:
write_imagef(output, (int2){coords.y, coords.x}, pixel );
(x and y coordinates are switched) seems to have no any effect. I can do whatever I want but the result is still the original image! Why the output is not affected?
CopyImagesExample.java
import static java.lang.Math.cos;
import static java.lang.Math.sin;
import static org.bridj.Pointer.allocateFloats;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteOrder;
import javax.imageio.ImageIO;
import org.bridj.Pointer;
import com.nativelibs4java.opencl.CLBuffer;
import com.nativelibs4java.opencl.CLContext;
import com.nativelibs4java.opencl.CLDevice;
import com.nativelibs4java.opencl.CLEvent;
import com.nativelibs4java.opencl.CLImage2D;
import com.nativelibs4java.opencl.CLKernel;
import com.nativelibs4java.opencl.CLMem.Usage;
import com.nativelibs4java.opencl.CLSampler;
import com.nativelibs4java.opencl.CLSampler.AddressingMode;
import com.nativelibs4java.opencl.CLSampler.FilterMode;
import com.nativelibs4java.opencl.CLProgram;
import com.nativelibs4java.opencl.CLQueue;
import com.nativelibs4java.opencl.JavaCL;
import com.nativelibs4java.util.IOUtils;
public class CopyImagesExample {
public static void main(String[] args) throws IOException {
CLContext context = JavaCL.createBestContext();
CLQueue queue = context.createDefaultQueue();
ByteOrder byteOrder = context.getByteOrder();
CLDevice[] devices = context.getDevices();
System.out.println("Devices count " + context.getDeviceCount());
System.out.println(devices[0].getMaxComputeUnits());
System.out.println(devices[0].getOpenCLVersion());
int n = 1024;
Pointer<Float> aPtr = allocateFloats(n).order(byteOrder);
Pointer<Float> bPtr = allocateFloats(n).order(byteOrder);
Pointer<Float> oPtr = allocateFloats(n).order(byteOrder);
for (int i = 0; i < n; i++) {
aPtr.set(i, (float) cos(i));
bPtr.set(i, (float) sin(i));
}
// Create OpenCL input buffers (using the native memory pointers aPtr
// and bPtr) :
BufferedImage img = ImageIO.read(new FileInputStream("images/lena256.png"));
CLImage2D inputImage = context.createImage2D(Usage.Input, img, false);
// Create an OpenCL output buffer :
CLImage2D outImage = context.createImage2D(Usage.Output, img, false);
CLSampler sampler = context.createSampler(false, AddressingMode.ClampToEdge, FilterMode.Nearest);
// Read the program sources and compile them :
String src = IOUtils.readText(CopyImagesExample.class
.getResource("CopyImage.cl"));
CLProgram program = context.createProgram(devices, src);
// Get and call the kernel :
CLKernel nnKernel = program.createKernel("rotate_image");
nnKernel.setArgs(inputImage, outImage, sampler);
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth()*img.getHeight() });
BufferedImage outPtr = outImage.read(queue, addEvt); // blocks until
// add_floats
// finished
ImageIO.write(outPtr, "png", new File("out.png"));
}
}
CopyImage.cl
__kernel void rotate_image(
__read_only image2d_t input,
__write_only image2d_t output,
sampler_t sampler)
{
// Store each work-items unique row and column
int2 coords = (int2){get_global_id(0), get_global_id(1)};
float4 pixel = read_imagef(input, sampler, coords);
write_imagef(output, (int2){coords.y, coords.x}, pixel );
}
Input:
Output:
But desired output is that the image is rotated (x and y coordinates of each pixel is switched).

Quick fix: replace code :
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth()*img.getHeight() });
with:
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth(), img.getHeight() });
The reason is, that in OpenCL code I am using
get_global_id(0)
and
get_global_id(1)
So I need enqueue 2D range.

Related

Problem saving an int array as an image in Java

I am trying to manipulate an image by first manipulating its data elements as bytes, and the saving it back as a RGB. The image size is 320x320x3 (rgb).
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.IntBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
class sobel_java {
public static void main(String args[]){
BufferedImage image = null;
try{
image = ImageIO.read(new File("butterfinger.jpg"));
final byte[] image_pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int image_height = image.getHeight();
final int image_width = image.getWidth();
System.out.println(image_height);
System.out.println(image_width);
BufferedImage out_image = new BufferedImage(image_width, image_height, BufferedImage.TYPE_INT_RGB);
/* Create an int array that contains image_pixels. */
IntBuffer intBuf = ByteBuffer.wrap(image_pixels).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
int[] array = new int[intBuf.remaining()];
intBuf.get(array);
/* Write the int array to BufferedImage. */
out_image.getRaster().setDataElements(0, 0, image_width, image_height, array);
/* Save the image. */
ImageIO.write(out_image, "jpg", new File("out.jpg"));
}catch(IOException e){
System.out.println(e);
}
}
}
In runtime, I get the following error,
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: arraycopy: last source index 77120 out of bounds for int[76800]
at java.base/java.lang.System.arraycopy(Native Method)
at java.desktop/sun.awt.image.IntegerInterleavedRaster.setDataElements(IntegerInterleavedRaster.java:425)
at sobel_java.main(sobel_java.java:30)
You're using an int array. Each pixel takes up 4 bytes then; RGB covers 3 of em, and the 4th is discarded. That way, it's 1 int = 1 pixel, vs. some bizarro packing algorithm.
Fix it by not using int arrays, or by manually injecting a 4th ignored byte.

OpenCV library in Tomcat(8.5.32) Server unable to execute

Facing issue while image processing code setup. In spite of doing all code changes and different approaches facing the issue.
Libraries used – OpenCV – 3.4.2
Jars Used – opencv-3.4.2-0
tess4j-3.4.8
Lines added in pom.xml
<!-- https://mvnrepository.com/artifact/org.openpnp/opencv -->
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>3.4.2-0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sourceforge.tess4j/tess4j -->
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>3.4.8</version>
</dependency>
Steps for OpenCV installation :
Download opencv.exe from the official site’
Run opencv.exe, it will create an opencv folder
We have now the opencv library available which we can use for eclipse.
Steps for Tesseract installation :
Download tess4j.zip file from the official link
Extract the zip folder after download
Provide the path of the tess4j folder
Following are the steps which we have performed for the setup in eclipse :
We have added native library by providing path to openCV library from build path settings
We downloaded tesseract for image reading.
We provided the path to the Tesseraact in the code
We have used System.loadlibrary(Core.NATIVE_LIBRARY_NAME) and openCv.loadLocally() for loading the library.
Then we have made the WAR export for deployment
There has been no changes or setup in apache tomcat
For loading the libraries in Tomcat we have to provide some setup here :-
Now for the new code we have used, Load Library static class in the code (as solutions stated on stack overflow)
In here System.loadLibrary is not working
We had to use System.load along with hardcoded path which is resulting in internal error
We have used System.load – 2 time in the static class out of which the when the 1st one is giving -std error -bad allocation
As there are 2 paths in opencv-
This is the 1st one
System.load("C:\Users\Downloads\opencv\build\bin\opencv_java342.dll");
and the 2nd one is giving the assertion error based on which one is kept above
This is the 2nd one
System.load("C:\User\Downloads\opencv\build\java\x64\opencv_java3412.dll");
The code is executing till mid-way and then getting out and till now not yet code has reached till tesseract.
Here is the code for the same :
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.opencv.core.Core;
import org.opencv.core.CvException;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import net.sourceforge.tess4j.Tesseract;
import nu.pattern.OpenCV;
public class ReadImageBox {
public String readDataFromImage(String imageToReadPath,String tesseractPath)
{
String result = "";
try {
String i = Core.NATIVE_LIBRARY_NAME;
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
logger.info("Img to read "+imageToReadPath);
String imagePath =imageToReadPath; // bufferNameOfImagePath = "";
logger.info(imagePath);
/*
* The class Mat represents an n-dimensional dense numerical single-channel or
* multi-channel array. It can be used to store real or complex-valued vectors
* and matrices, grayscale or color images, voxel volumes, vector fields, point
* clouds, tensors, histograms (though, very high-dimensional histograms may be
* better stored in a SparseMat ).
*/
logger.info("imagepath::"+imagePath);
OpenCV.loadLocally();
logger.info("imagepath::"+imagePath);
//logger.info("Library Information"+Core.getBuildInformation());
logger.info("imagepath::"+imagePath);
Mat source = Imgcodecs.imread(imagePath);
logger.info("Source image "+source);
String directoryPath = imagePath.substring(0,imagePath.lastIndexOf('/'));
logger.info("Going for Image Processing :" + directoryPath);
// calling image processing here to process the data from it
result = updateImage(100,20,10,3,3,2,source, directoryPath,tesseractPath);
logger.info("Data read "+result);
return result;
}
catch (UnsatisfiedLinkError error) {
// Output expected UnsatisfiedLinkErrors.
logger.error(error);
}
catch (Exception exception)
{
logger.error(exception);
}
return result;
}
public static String updateImage(int boxSize, int horizontalRemoval, int verticalRemoval, int gaussianBlur,
int denoisingClosing, int denoisingOpening, Mat source, String tempDirectoryPath,String tesseractPath) throws Exception{
// Tesseract Object
logger.info("Tesseract Path :"+tesseractPath);
Tesseract tesseract = new Tesseract();
tesseract.setDatapath(tesseractPath);
// Creating the empty destination matrix for further processing
Mat grayScaleImage = new Mat();``
Mat gaussianBlurImage = new Mat();
Mat thresholdImage = new Mat();
Mat morph = new Mat();
Mat morphAfterOpreation = new Mat();
Mat dilate = new Mat();
Mat hierarchy = new Mat();
logger.info("Image type"+source.type());
// Converting the image to gray scale and saving it in the grayScaleImage matrix
Imgproc.cvtColor(source, grayScaleImage, Imgproc.COLOR_RGB2GRAY);
//Imgproc.cvtColor(source, grayScaleImage, 0);
// Applying Gaussain Blur
logger.info("source image "+source);
Imgproc.GaussianBlur(grayScaleImage, gaussianBlurImage, new org.opencv.core.Size(gaussianBlur, gaussianBlur),
0);
// OTSU threshold
Imgproc.threshold(gaussianBlurImage, thresholdImage, 0, 255, Imgproc.THRESH_OTSU | Imgproc.THRESH_BINARY_INV);
logger.info("Threshold image "+gaussianBlur);
// remove the lines of any table inside the invoice
Mat horizontal = thresholdImage.clone();
Mat vertical = thresholdImage.clone();
int horizontal_size = horizontal.cols() / 30;
if(horizontal_size%2==0)
horizontal_size+=1;
// showWaitDestroy("Horizontal Lines Detected", horizontal);
Mat horizontalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,
new org.opencv.core.Size(horizontal_size, 1));
Imgproc.erode(horizontal, horizontal, horizontalStructure);
Imgproc.dilate(horizontal, horizontal, horizontalStructure);
int vertical_size = vertical.rows() / 30;
if(vertical_size%2==0)
vertical_size+=1;
// Create structure element for extracting vertical lines through morphology
// operations
Mat verticalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,
new org.opencv.core.Size(1, vertical_size));
// Apply morphology operations
Imgproc.erode(vertical, vertical, verticalStructure);
Imgproc.dilate(vertical, vertical, verticalStructure);
Core.absdiff(thresholdImage, horizontal, thresholdImage);
Core.absdiff(thresholdImage, vertical, thresholdImage);
logger.info("Vertical Structure "+verticalStructure);
Mat newImageFortest = thresholdImage;
logger.info("Threshold image "+thresholdImage);
// applying Closing operation
Imgproc.morphologyEx(thresholdImage, morph, Imgproc.MORPH_CLOSE, Imgproc.getStructuringElement(
Imgproc.MORPH_RECT, new Size(denoisingClosing, denoisingClosing)));
logger.info("Morph image "+morph);
// applying Opening operation
Imgproc.morphologyEx(morph, morphAfterOpreation, Imgproc.MORPH_OPEN, Imgproc.getStructuringElement(
Imgproc.MORPH_RECT, new Size(denoisingOpening, denoisingOpening)));
logger.info("Morph After operation image "+morphAfterOpreation);
// Applying dilation on the threshold image to create bounding box edges
Imgproc.dilate(morphAfterOpreation, dilate,
Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(boxSize, boxSize)));
logger.info("Dilate image "+dilate);
// creating string buffer object
String text = "";
try
{
// finding contours
List<MatOfPoint> contourList = new ArrayList<MatOfPoint>(); // A list to store all the contours
// finding contours
Imgproc.findContours(dilate, contourList, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);
logger.info("Contour List "+contourList);
// Creating a copy of the image
//Mat copyOfImage = source;
Mat copyOfImage = newImageFortest;
logger.info("Copy of Image "+copyOfImage);
// Rectangle for cropping
Rect rectCrop = new Rect();
logger.info("Rectangle Crop New Object "+rectCrop);
// loop through the identified contours and crop them from the image to feed
// into Tesseract-OCR
for (int i = 0; i < contourList.size(); i++) {
// getting bound rectangle
rectCrop = Imgproc.boundingRect(contourList.get(i));
logger.info("Rectangle cropped"+rectCrop);
// cropping Image
Mat croppedImage = copyOfImage.submat(rectCrop.y, rectCrop.y + rectCrop.height, rectCrop.x,
rectCrop.x + rectCrop.width);
// writing cropped image to disk
logger.info("Path to write cropped image "+ tempDirectoryPath);
String writePath = tempDirectoryPath + "/croppedImg.png";
logger.info("writepath"+writePath);
// imagepath = imagepath.
Imgcodecs.imwrite(writePath, croppedImage);
try {
// extracting text from cropped image, goes to the image, extracts text and adds
// them to stringBuffer
logger.info("Exact Path where Image was written with Name "+ writePath);
String textExtracted = (tesseract
.doOCR(new File(writePath)));
//Adding Seperator
textExtracted = textExtracted + "_SEPERATOR_";
logger.info("Text Extracted "+textExtracted);
textExtracted = textExtracted + "\n";
text = textExtracted + text;
logger.info("Text Extracted Completely"+text);
// System.out.println("Andar Ka Text => " + text.toString());
} catch (Exception exception) {
logger.error(exception);
}
writePath = "";
logger.info("Making write Path empty for next Image "+ writePath);
}
}
catch(CvException ae)
{
logger.error("cv",ae);
}
catch(UnsatisfiedLinkError ae)
{
logger.error("unsatdif",ae);
}
catch(Exception ae)
{
logger.error("general",ae);
}
// converting into string
return text.toUpperCase();
}
// convert Mat to Image for GUI output
public static Image toBufferedImage(Mat m) {
// getting BYTE_GRAY formed image
int type = BufferedImage.TYPE_BYTE_GRAY;
if (m.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = m.channels() * m.cols() * m.rows();
byte[] b = new byte[bufferSize];
m.get(0, 0, b); // get all the pixels
// creating buffered Image
BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(b, 0, targetPixels, 0, b.length);
// returning Image
return image;
}
// method to display Mat format images using the GUI
private static void showWaitDestroy(String winname, Mat img) {
HighGui.imshow(winname, img);
HighGui.moveWindow(winname, 500, 0);
HighGui.waitKey(0);
HighGui.destroyWindow(winname);
}
}

How to disable compression when writing JPEG in java?

I want to compress JPEG to fixed file size (20480 bytes). Here is my code:
package io.github.baijifeilong.jpeg;
import lombok.SneakyThrows;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
/**
* Created by BaiJiFeiLong#gmail.com at 2019/10/9 上午11:26
*/
public class JpegApp {
#SneakyThrows
public static void main(String[] args) {
BufferedImage inImage = ImageIO.read(new File("demo.jpg"));
BufferedImage outImage = new BufferedImage(143, 143, BufferedImage.TYPE_INT_RGB);
outImage.getGraphics().drawImage(inImage.getScaledInstance(143, 143, Image.SCALE_SMOOTH), 0, 0, null);
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_DISABLED);
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("jpg").next();
imageWriter.setOutput(new FileImageOutputStream(new File("demo-xxx.jpg")));
imageWriter.write(null, new IIOImage(outImage, null, null), jpegParams);
}
}
And the error occured:
Exception in thread "main" javax.imageio.IIOException: JPEG compression cannot be disabled
at com.sun.imageio.plugins.jpeg.JPEGImageWriter.writeOnThread(JPEGImageWriter.java:580)
at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:363)
at io.github.baijifeilong.jpeg.JpegApp.main(JpegApp.java:30)
Process finished with exit code 1
So how to disable JPEG compression? Or there be any method that can compress any image to a fixed file size with any compression?
As for the initial question, how to create non-compressed jpegs: one can't, for fundamental reasons. While I initially assumed that it is possible to write a non-compressing jpg encoder producing output that can be decoded with any existing decoder by manipulating the Huffman tree involved, I had to dismiss it. The Huffman encoding is just the last step of quite a pipeline of transformations, that can not be skipped. Custom Huffman trees may also break less sophisticated decoders.
For an answer that takes into consideration the requirement change made in comments (resize and compress any way you like, just give me the desired file size) one could reason this way:
The jpeg file specification defines an End of Image marker. So chances are, that patching zeros (or just anything perhaps) afterwards make no difference. An experiment patching some images up to a specific size showed that gimp, chrome, firefox and your JpegApp swallowed such an inflated file without complaint.
It would be rather complicated to create a compression that for any image compresses precisely to your size requirement (kind of: for image A you need a compression ratio of 0.7143, for Image B 0.9356633, for C 12.445 ...). There are attempts to predict image compression ratios based on raw image data, though.
So I'd propose just to resize/compress to any size < 20480 and then patch it:
calculate the scaling ratio based on the original jpg size and the
desired size, including a safety margin to account for the
inherently vague nature of the issue
resize the image with that ratio
patch missing bytes to match exactly the desired size
As outlined here
private static void scaleAndcompress(String fileNameIn, String fileNameOut, Long desiredSize) {
try {
long size = getSize(fileNameIn);
// calculate desired ratio for conversion to stay within size limit, including a safte maring (of 10%)
// to account for the vague nature of the procedure. note, that this will also scale up if needed
double desiredRatio = (desiredSize.floatValue() / size) * (1 - SAFETY_MARGIN);
BufferedImage inImg = ImageIO.read(new File(fileNameIn));
int widthOut = round(inImg.getWidth() * desiredRatio);
int heigthOut = round(inImg.getHeight() * desiredRatio);
BufferedImage outImg = new BufferedImage(widthOut, heigthOut, BufferedImage.TYPE_INT_RGB);
outImg.getGraphics().drawImage(inImg.getScaledInstance(widthOut, heigthOut, Image.SCALE_SMOOTH), 0, 0, null);
JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersByFormatName("jpg").next();
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
imageWriter.setOutput(new MemoryCacheImageOutputStream(outBytes));
imageWriter.write(null, new IIOImage(outImg, null, null), new JPEGImageWriteParam(null));
if (outBytes.size() > desiredSize) {
throw new IllegalStateException(String.format("Excess output data size %d for image %s", outBytes.size(), fileNameIn));
}
System.out.println(String.format("patching %d bytes to %s", desiredSize - outBytes.size(), fileNameOut));
patch(desiredSize, outBytes);
try (FileOutputStream outFileStream = new FileOutputStream(new File(fileNameOut))) {
outBytes.writeTo(outFileStream);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void patch(Long desiredSize, ByteArrayOutputStream bytesOut) {
long patchSize = desiredSize - bytesOut.size();
for (long i = 0; i < patchSize; i++) {
bytesOut.write(0);
}
}
private static long getSize(String fileName) {
return (new File(fileName)).length();
}
private static int round(double f) {
return Math.toIntExact(Math.round(f));
}
A solution using Magick (sudo apt install imagemagick on Debian), maybe not work for some images. Thanks to #curiosa-g.
package io.github.baijifeilong.jpeg;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
/**
* Created by BaiJiFeiLong#gmail.com at 2019/10/9 上午11:26
*/
public class JpegApp {
#SneakyThrows
private static InputStream compressJpeg(InputStream inputStream, int fileSize) {
File tmpFile = new File(String.format("tmp-%d.jpg", Thread.currentThread().getId()));
FileUtils.copyInputStreamToFile(inputStream, tmpFile);
Process process = Runtime.getRuntime().exec(String.format("mogrify -strip -resize 512 -define jpeg:extent=%d %s", fileSize, tmpFile.getName()));
try (Scanner scanner = new Scanner(process.getErrorStream()).useDelimiter("\\A")) {
if (process.waitFor() > 0) throw new RuntimeException(String.format("Mogrify Error \n### %s###", scanner.hasNext() ? scanner.next() : "Unknown"));
}
try (FileInputStream fileInputStream = new FileInputStream(tmpFile)) {
byte[] bytes = IOUtils.toByteArray(fileInputStream);
assert bytes.length <= fileSize;
byte[] newBytes = new byte[fileSize];
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
Files.delete(Paths.get(tmpFile.getPath()));
return new ByteArrayInputStream(newBytes);
}
}
#SneakyThrows
public static void main(String[] args) {
InputStream inputStream = compressJpeg(new FileInputStream("big.jpg"), 40 * 1024);
IOUtils.copy(inputStream, new FileOutputStream("40KB.jpg"));
System.out.println(40 * 1024);
System.out.println(new File("40KB.jpg").length());
}
}
And the output:
40960
40960

OpenCV 3 (Java Binding) : Apply CLAHE to image

I try to use the java bindings of open cv to apply an non-global contrast (histogram) optimization for a (color) png image, but I fail to get it to work.
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import javax.imageio.ImageIO;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.CLAHE;
import org.opencv.imgproc.Imgproc;
public class Main {
public static void main( String[] args ) {
try {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
// fetch the png
File input = new File("test.png");
BufferedImage buffImage = ImageIO.read(input);
byte[] data = ((DataBufferByte) buffImage.getRaster().getDataBuffer()).getData();
// build MAT for original image
Mat orgImage = new Mat(buffImage.getHeight(),buffImage.getWidth(), CvType.CV_8UC3);
orgImage.put(0, 0, data);
// transform from to LAB
Mat labImage = new Mat(buffImage.getHeight(), buffImage.getWidth(), CvType.CV_8UC4);
Imgproc.cvtColor(orgImage, labImage, Imgproc.COLOR_BGR2Lab);
// apply CLAHE
CLAHE clahe = Imgproc.createCLAHE()
Mat destImage = new Mat(buffImage.getHeight(),buffImage.getWidth(), CvType.CV_8UC4);
clahe.apply(labImage, destImage);
Imgcodecs.imwrite("test_clahe.png", destImage);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
I get the exception:
Error: cv::Exception: C:\builds\master_PackSlaveAddon-win64-vc12-static\opencv\modules\imgproc\src\clahe.cpp:354: error: (-215) _src.type() == CV_8UC1 || _src.type() == CV_16UC1 in function `anonymous
-namespace'::CLAHE_Impl::apply
I guess I need to work with the individual channels, but I cannot figure out how. The code is inspired from this c++ example, but somehow I fail to extract the corresponding layers (I guess I need only L chanel for clahe.apply())
This Example just splits the Lab image and applies Clahe on the L channel which is the intensity channel. So just use this code for java.
List<Mat> channels = new LinkedList();
Core.split(labImage, channels);
CLAHE clahe = Imgproc.createCLAHE()
Mat destImage = new Mat(buffImage.getHeight(),buffImage.getWidth(), CvType.CV_8UC4);
clahe.apply(channels.get(0), destImage);
Core.merge(channels, labImage);
and finally merge the intensity channel to the other channels. I haven't changed any parameters as I don't know how your image looks but I guess that isn't the problem. Hope it helps!

Determine whether an image is grayscale in Java

I'm using something along the lines of this to do a (naive, apparently) check for the color space of JPEG images:
import java.io.*;
import java.awt.color.*;
import java.awt.image.*;
import javax.imageio.*;
class Test
{
public static void main(String[] args) throws java.lang.Exception
{
File f = new File(args[0]);
if (f.exists())
{
BufferedImage bi = ImageIO.read(f);
ColorSpace cs = bi.getColorModel().getColorSpace();
boolean isGrayscale = cs.getType() == ColorSpace.TYPE_GRAY;
System.out.println(isGrayscale);
}
}
}
Unfortunately this reports false for images that (visually) appear gray-only.
What check would do the right thing?
You can use this code:
File input = new File("inputImage.jpg");
BufferedImage image = ImageIO.read(input);
Raster ras = image.getRaster();
int elem = ras.getNumDataElements();
System.out.println("Number of Elems: " + elem);
If the number of elems returns 1, then its a greyscale image. If it returns 3, then its a color image.
the image looks like gray beacuse the r=g=b but actually it is a full color image, it has three channel r g b and the real gray image only have one channel

Categories

Resources