I tried searching for this quite a lot and cant seem to figure it out. All of the threads I read shows that everyone is doing the same thing. But it doesn't seem to work for me.
I want to create a new image and add two images to this created image.
For this I'm generating a Mat.zeros onto which I will be adding my two images(lets say A and B. I'll call the zeros Mat G).
I scale down the images A and B.
I create an ROI on G with the size of A and then copy A to G.submat.
I create an ROT on G with size B and then copy B to G.submat.
When I finally save G, all I get is a black image( because I generated G as Mat.zeros )
. I'm guessing copyTo is not really copying the content from A to G on the ROI of G.
I'm not sure what I'm doing wrong.
I'm using Kotlin which compiles down to Java.
#PostConstruct
fun init() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
#Test
fun `merge image`() {
val frameLeft = Imgcodecs.imread("/home/nischit/Downloads/potato1.jpg")
val frameRight = Imgcodecs.imread("/home/nischit/Downloads/potato2.jpg")
val frameOutput = Mat.zeros(1920, 1080, frameLeft.depth())
println(frameLeft.depth())
println(frameRight.depth())
println(frameOutput.depth())
val tempLeft = Mat()
val tempRight = Mat()
scaleFrame(frameLeft, tempLeft)
scaleFrame(frameRight, tempRight)
println("tempLeft: ${tempLeft.cols()},${tempLeft.rows()}")
println("tempRight: ${tempRight.cols()},${tempRight.rows()}")
tempLeft.copyTo(frameOutput.submat(Rect(10, 10, tempLeft.cols(), tempLeft.rows())))
tempRight.copyTo(frameOutput.submat(Rect(10, 500, tempRight.cols(), tempRight.rows())))
saveImage(frameOutput, 2)
}
fun scaleFrame(frame: Mat, out: Mat, maxWidth: Int = MAX_WIDTH, maxHeight: Int = MAX_HEIGHT) {
val isFrameInPortraitMode = frame.height() > frame.width()
val scale = if (isFrameInPortraitMode) {
(maxHeight * 1.0 / frame.height())
} else {
(maxWidth * 1.0 / frame.width())
}
Imgproc.resize(frame, out, Size(frame.width() * scale, frame.height() * scale))
}
fun saveImage(frame: Mat, i: Int = 0) {
Imgcodecs.imwrite("/home/nischit/Downloads/potatoGenerated$i.jpg", frame)
}
Okay, the problem was with channels in the blank image I had created i.e frameOutput. All of the inputs have 3 channels while this matrix had 1 channel as I was not initializing it correctly.
Replacing
val frameOutput = Mat.zeros(1920, 1080, frameLeft.depth()) with val frameOutput = Mat.zeros(Size(1920.0, 1080.0), CvType.CV_8UC3) worked.
Related
When overriding onDraw in an edittext, I can make the text in any location I see fit. What I'm having trouble with is aligning their respective "boxes" ie the area where the actual char is clicked to edit said char. The text I can move, or rather draw wherever, but how do I align the actual physical position of the char to it's painted char? I'm at a bit of a loss I couldn't figure out what to override to change these positions. Any help would be awesome! I don't have any code to post, as it's literally just an extended edittext and override onDraw with a for loop.
I attempted to move the position of text digits individually inside an edit text using onDraw, but found it doesn't seem to move the actual location just the paint representation of it.
EDIT ----------------------------------
Ive found what I believe to be what needs overriden, the onSelection start and end. But, it seems to cause an infinite recursion loop? Anyone got any ideas as to how this is done? Indentation is hard to do on a phone but here's a sample of the rough idea:
class HexEditorEditText(context: Context, attrs: AttributeSet?) : EditText(context, attrs) {
private val characterWidth: Float
private val characterHeight: Float
init {
val textPaint = paint
characterWidth = textPaint.measureText("00")
characterHeight = textPaint.fontSpacing
}
override fun onDraw(canvas: Canvas?) {
val text = text.toString()
var x = 0f
var y = 0f
for (i in 0 until text.length step 2) {
val pair = text.substring(i, i + 2)
canvas?.drawText(pair, x, y, paint)
x += characterWidth + characterWidth / 2
}
}
override fun getSelectionStart(): Int {
val layout = layout
val line = layout.getLineForOffset(selectionStart)
val x = layout.getPrimaryHorizontal(selectionStart)
return (x / (characterWidth + characterWidth / 2)).toInt() * 2
}
override fun getSelectionEnd(): Int {
val layout = layout
val line = layout.getLineForOffset(selectionEnd)
val x = layout.getPrimaryHorizontal(selectionEnd)
return (x / (characterWidth + characterWidth / 2)).toInt() * 2
}
override fun setSelection(start: Int, stop: Int) {
super.setSelection((start / 2) * 2, (stop / 2) * 2)
}
}
I'm been writing maze algorithms, and want to draw the mazes generated using JavaFX.
To begin with, I'm attempting to draw a simple grid - but made up of smaller shapes so that I'll later be able to change the shape of the grid into that of a maze.
I'm using little upper left corner shapes (like ┏) and a GridPane, but this is leading to small discontinuities between the cells. (screenshot and code below). How can I wedge these shapes together seamlessly? Am I barking up the wrong tree with the Gridpane idea?
attempted grid drawing so far
My code, below, is actually written in Scala; I'm using ScalaFX, but finding help for ScalaFX online is a nightmare so I've been going solely off JavaFX docs - they are pretty much the same thing as far as I've gathered.
val lineLength: Int = 30
def makeClosedCell(length: Int = lineLength): Shape = {
val wallN = Line(0,0,length,0)
val wallW = Line(0,0,0,length)
val closedCell: Shape = Shape.union(wallN, wallW)
return closedCell
}
def makeOpenW(length: Int = lineLength): Shape = Line(0,0,length,0)
def makeOpenN(length: Int = lineLength): Shape = Line(0,0,0,length)
def initialiseGrid(r: GridPane, sizex: Int, sizey: Int): Unit = {
for (i <- 0 until sizex) {
val colConst = new ColumnConstraints()
colConst.setPercentWidth(100.0 / sizex)
r.getColumnConstraints().add(colConst)
}
for (i <- 0 until sizey) {
val rowConst = new RowConstraints()
rowConst.setPercentHeight(100.0 / sizey)
r.getRowConstraints().add(rowConst)
}
for(j <- sizey-1 to 0 by -1){
for(i <- 0 until sizex){
r.add(makeClosedCell(),i,j)
}
r.add(makeOpenN(),sizex,j)
}
for(i <- 0 until sizex){
r.add(makeOpenW(),i,sizey)
}
}
Just found a solution. I've found this can be solved by fixing the exact column and row widths and heights to the same value as the line lengths, like so:
val rowConst = new RowConstraints()
// remove: rowConst.setPercentHeight(100.0 / sizey)
rowConst.setMinHeight(length)
rowConst.setMaxHeight(length)
r.getRowConstraints().add(rowConst)
With length passed into the initialisation function, of course.
Context:
I'm trying to create an animation in java.
The animation is simply take an image and make it appear from the darkest pixels to the lightest.
The Problem:
The internal algorithm defining the pixels transformations is not my issue.
I'm new to Java and Computing in general. I've done a bit of research, and know that there are plenty of APIs that helps with image filters/transformations.
My problem is performance, understanding it.
To the implementation i've created a method that do the following:
Receives an BufferedImage.
Get the WritableRaster of the BufferedImage.
Using setSample and getSample, process and change pixel by pixel.
Return the BufferedImage.
After that, i use a Timer to call the method.
The returned BufferedImage is attached to a JButton via setIcon after each call.
With a 500x500 image my machine takes around 3ms to process each call.
For standard 1080p images it takes around 30ms, wich is about 33 frames per second.
My goal is to process/animate FullHD images at 30fps... And i will not be able to with the path I'm following. Not in most computers.
What i'm getting wrong? How i can make it faster? Using getDataBuffer or getPixels instead of getSample can improve it?
Thanks in advance! And sorry my english.
Partial Conclusions:
Thanks to some help here. I've changed concept. Instead of using getSample and setSample I've stored the pixels ARGB informations of the BufferedImage into an array. So i process the array and copy it all at once into a Raster of another BufferedImage.
The process time reduced from 30ms ( get/set sample ) to 1ms. ( measured poorly, but in the same machine, enviroment and code ).
Below is a little class i coded to implement it. The class can filter pixels only below a Brightness level, the other pixels become transparent ( alpha = 0 ).
Hope it help's who search for the same solution in the future. Be wary that I'm below rookie level in Java, so the code might be poorly organized/optimized.
import java.awt.Graphics2D;
import java.awt.image.*;
/**
* #author Psyny
*/
public class ImageAppearFX {
//Essencial Data
BufferedImage imgProcessed;
int[] RAWoriginal;
int[] RAWprocessed;
WritableRaster rbgRasterProcessedW;
//Information about the image
int x,y;
int[] mapBrightness;
public ImageAppearFX(BufferedImage inputIMG) {
//Store Dimensions
x = inputIMG.getWidth();
y = inputIMG.getHeight();
//Convert the input image to INT_ARGB and store it.
this.imgProcessed = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB);
Graphics2D canvas = this.imgProcessed.createGraphics();
canvas.drawImage(inputIMG, 0, 0, x, y, null);
canvas.dispose();
//Create an int Array of the pixels informations.
//p.s.: Notice that the image was converted to INT_ARGB
this.RAWoriginal = ((DataBufferInt) this.imgProcessed.getRaster().getDataBuffer()).getData();
//Dupplication of original pixel array. So we can make changes based on original image
this.RAWprocessed = this.RAWoriginal.clone();
//Get Raster. We will need the raster to write pixels on
rbgRasterProcessedW = imgProcessed.getRaster();
//Effect Information: Store brightness information
mapBrightness = new int[x*y];
int r,g,b,a,greaterColor;
// PRocess all pixels
for(int i=0 ; i < this.RAWoriginal.length ; i++) {
a = (this.RAWoriginal[i] >> 24) & 0xFF;
r = (this.RAWoriginal[i] >> 16) & 0xFF;
g = (this.RAWoriginal[i] >> 8) & 0xFF;
b = (this.RAWoriginal[i] ) & 0xFF;
//Search for Stronger Color
greaterColor = r;
if( b > r ) {
if( g > b ) greaterColor = g;
else greaterColor = b;
} else if ( g > r ) {
greaterColor = g;
}
this.mapBrightness[i] = greaterColor;
}
}
//Effect: Show only in a certain percent of brightness
public BufferedImage BrightnessLimit(float percent) {
// Adjust input values
percent = percent / 100;
// Pixel Variables
int hardCap = (int)(255 * percent);
int r,g,b,a,bright;
// Process all pixels
for(int i=0 ; i < this.RAWoriginal.length ; i++) {
//Get information of a pixel of the ORIGINAL image
a = (this.RAWoriginal[i] >> 24) & 0xFF;
r = (this.RAWoriginal[i] >> 16) & 0xFF;
g = (this.RAWoriginal[i] >> 8) & 0xFF;
b = (this.RAWoriginal[i] ) & 0xFF;
//Brightness information of that same pixel
bright = this.mapBrightness[i];
//
if( bright > hardCap ) {
a = 0;
}
this.RAWprocessed[i] = ((a << 24) + (r << 16) + (g << 8) + ( b )); //Write ARGB in byte format
}
//Copy the processed array into the raster of processed image
rbgRasterProcessedW.setDataElements(0, 0, x, y, RAWprocessed);
return imgProcessed;
}
//Return reference to the processed image
public BufferedImage getImage() {
return imgProcessed;
}
}
While the time difference resulting from the change doesn't prove that the repeated searching is the bottleneck, it does strongly implicate it.
If you are willing/able to trade memory for time, I would first sort a list of all the pixel locations by brightness. Next, I would use the sorted list during the animation to look up the next pixel to copy.
An extra piece of advice: use one of Java's built in sorting methods. It's educational to make your own, but learning how to sort doesn't seem to be your goal here. Also, if my guess about the bottleneck is wrong, you'll want to minimize your time pursuing this answer.
Currently I am saving a jtable as jpeg using the below method, when the dimension of the jtable became 2590, 126181, java.lang.OutOfMemoryError: Java heap space exception occurs at "BufferedImage constructor", when the size of the table is small the image gets saved successfully.
public BufferedImage saveComponentAsJPEG(JTable table, String filename) {
Dimension size = table.getSize();
BufferedImage myImage =
new BufferedImage(size.width, size.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = myImage.createGraphics();
table.paint(g2);
return myImage;
}
How to save a jtable with bigger size in pdf or jpeg image?
Updated Info:
You asked how to "split the JTable into different small images":
As you go through my code below please read my comments, they help explain what is happening and will help you grasp a better understanding of how a JTable/JComponent can be painted to lots of small images. At the heart my code is similar to yours, but there are two key points:
1) Rather than create a single large BufferedImage, I create a single small image that is then used multiple times, therefore leaving a very small memory footprint.
2) With the single image, I use Graphics.translate() to paint a small part of the JTable each time.
The following code was tested with a large JComponents (2590 x 126181) and a tile size of 200x200, and the whole process did not exceed 60mb of memory:
//width = width of tile in pixels, for minimal memory usage try 200
//height = height of tile in pixels, for minimal memory usage try 200
//saveFileLocation = folder to save image tiles
//component = The JComponent to save as tiles
public static boolean saveComponentTiles(int width, int height, String saveFileLocation, JComponent component)
{
try
{
//Calculate tile sizes
int componentWidth = component.getWidth();
int componentHeight = component.getHeight();
int horizontalTiles = (int) Math.ceil((double)componentWidth / width); //use (double) so Math.ceil works correctly.
int verticalTiles = (int) Math.ceil((double)componentHeight / height); //use (double) so Math.ceil works correctly.
System.out.println("Tiles Required (H, W): "+horizontalTiles+", verticalTiles: "+verticalTiles);
//preset arguments
BufferedImage image;
//Loop through vertical and horizontal tiles
//Draw part of the component to the image
//Save image to file
for (int h = 0; h < verticalTiles; h++)
{
for (int w = 0; w < horizontalTiles; w++)
{
//check tile size, if area to paint is smaller than image then shrink image
int imageHeight = height;
int imageWidth = width;
if (h + 1 == verticalTiles)
{
imageHeight = componentHeight - (h * height);
}
if (w + 1 == horizontalTiles)
{
imageWidth = componentWidth - (w * width);
}
image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
//translate image graphics so that only the correct part of the component is panted to the image
g.translate(-(w * width), -(h * height));
component.paint(g);
//In my example I am saving the image to file, however you could throw your PDF processing code here
//Files are named as "Image.[h].[w]"
//Example: Image 8 down and 2 accross would save as "Image.8.2.png"
ImageIO.write(image, "png", new File(saveFileLocation + "Image." + h +"."+ w + ".png"));
//tidy up
g.dispose();
}
}
return true;
}
catch (IOException ex)
{
return false;
}
}
Just call it like so:
boolean result = saveComponentTiles(200, 200, saveFileLocation, jTable1);
Also if you haven't done it already, you should only call the method from a different thread because it will hang your application when dealing with large components.
If you have not picked a PDF library yet, then I highly recommend looking at iText.
Original Post:
The process you are looking for is quite simple, however it may take some work.
You were on the right track thinking about parts, but as David
mentioned you shouldn't mess with the jTable, instead you will need a
to make use of the TiledImage class, or do something yourself with
RenderedImage and Rasters.
This sort of method basically uses HDD space instead of memory and
lets you create a large image in lots of smaller parts/tiles, then
when its done you can save it all to a single image file.
This answer may also help: https://stackoverflow.com/a/14069551/1270000
Good evening, need some help with getting a square area of rgb pixels with openCV
Im trying to get the pixels from a 50x50 area on the center of the screen, but i didnt get any success.
if i use the output i dont get any pixel else if using original mat(image) its getting the top corner
Please someone help
#Override
public void onPreviewFrame(Mat image) {
int w = image.cols();
int h = image.rows();
Mat roi=new Mat(image, new Rect(h/2 , w/2 , 50, 50));
Mat output = roi.clone();
int rw=output.cols();
int rh=output.rows();
//double [] arrp = output.get(rh, rw);//if i use the output i dont get any pixel
double [] arrp = image.get(rh, rw);//if use original mat its getting the top corner
Log.i("",+(int)arrp[2]+" "+ (int)arrp[1]+" "+(int)arrp[0]);
}
I assume you can use copyTo :
Mat output(50, 50, image.type());
image(Rect(h/2 , w/2 , output.size())).copyTo(output);
The matrix class has an operator (const Rect &roi), that returns a submatrix (without deep data copy). : http://docs.opencv.org/modules/core/doc/basic_structures.html#id6
EDIT:
Didn't see it was for android. I think there is no operator, so you have to use the submat function :
image.submat(Rect(h/2 , w/2 , output.size())).copyTo(output)