For my thesis work, I need to create an IDE and I want to create a splash screen for the IDE.
So my first question is that I don't know which size for the image I must create for the splash screen.
My second question is that probably a lot of different screen resolutions are available in the market and the screen splash might be bigger or smaller for some computers... Is there anything that we could do to solve this ?
P.S.: I really liked the splash screen from IntelliJ IDE (15), I want to create something like that as a splash screen.
//----------------------------------------------------------------//
Solution for question 2:
//Get the resolution of the screen PC
Toolkit toolkit = Toolkit.getDefaultToolkit();
int X = (toolkit.getScreenSize().width);
int Y = (toolkit.getScreenSize().height);
//Get the pixels of the screen middle resolution
int cX = (toolkit.getScreenSize().width / 2) - ((int)((ImageView) s.lookup("#splash_logo")).getFitWidth())/2;
int cY = (toolkit.getScreenSize().height / 2) - ((int)((ImageView) s.lookup("#splash_logo")).getFitHeight()/2);
//Set the position of Stage to middle
primaryStage.setX(cX);
primaryStage.setY(cY);
If you want to scale it in relation to the monitor's resolution, I'd first get the height and width with the java.awt.Toolkit:
Toolkit toolkit = Toolkit.getDefaultToolkit();
int X = (toolkit.getScreenSize().width)
int Y = (toolkit.getScreenSize().height)
Then you can scale an image that you're using for your splashscreen by using this method:
public BufferedImage scaleImage(int multiplier, BufferedImage img) {
BufferedImage bi = new BufferedImage(multiplier * img.getWidth(null), multiplier * img.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D grph = (Graphics2D) bi.getGraphics();
grph.scale(multiplier, multiplier);
// everything drawn with grph from now on will get scaled.
grph.drawImage(img, 0, 0, null);
grph.dispose();
return bi;
}
Then center it on the screen by calculating the middle and setting your component there:
int cX = (toolkit.getScreenSize().width / 2) - (getWidth() / 2);
int cY = (toolkit.getScreenSize().height / 2) - (getHeight() / 2);
component.setLocation(cX, cY);
actual implementation is up to you, but these are the tools I use and it works fine for me. Hope this helps!
Related
double degPi = degrees * Math.PI / 180;
double a = Math.cos(degPi)*tImgCover.getScaledHeight();
double b = Math.sin(degPi)*tImgCover.getScaledWidth();
double c = -Math.sin(degPi) * tImgCover.getScaledHeight();
double d = Math.cos(degPi)* tImgCover.getScaledWidth();
double e = absX;
double f = absY;
contentByte.addImage(imgae, a, b, c, d, e, f);/*add image*/
How to rotate around the image center by itext?
If we have an Image image and coordinates x, y, we can draw the image without rotation with its lower left corner at the given coordinates like this
contentByte.addImage(image, image.getWidth(), 0, 0, image.getHeight(), x, y);
A bitmap image from the resources has a size of 1x1 with the coordinate origin at its lower left. Thus, this operation stretches the image to its correct size and moves it so its lower left is at the given coordinates.
If we want to draw the same image as if the one drawn above was rotated around its center by an angle rotate, therefore, we can do this by moving the 1x1 image so that the origin is in its center, stretch it to its correct size, rotate it, and then move the origin (which still is at the center of the rotated image) to the center of the unrotated image. These operations are easier to express using AffineTransform instances (from package com.itextpdf.awt.geom) instead number tupels. Thus:
// Draw image as if the previous image was rotated around its center
// Image starts out being 1x1 with origin in lower left
// Move origin to center of image
AffineTransform A = AffineTransform.getTranslateInstance(-0.5, -0.5);
// Stretch it to its dimensions
AffineTransform B = AffineTransform.getScaleInstance(image.getWidth(), image.getHeight());
// Rotate it
AffineTransform C = AffineTransform.getRotateInstance(rotate);
// Move it to have the same center as above
AffineTransform D = AffineTransform.getTranslateInstance(x + image.getWidth()/2, y + image.getHeight()/2);
// Concatenate
AffineTransform M = (AffineTransform) A.clone();
M.preConcatenate(B);
M.preConcatenate(C);
M.preConcatenate(D);
//Draw
contentByte.addImage(image, M);
(AddRotatedImage.java test method testAddRotatedImage)
For example drawing both images using
int x = 200;
int y = 300;
float rotate = (float) Math.PI / 3;
results in something like this:
With a Flip
The OP asked in a comment
how to add rotate and flip image?
For this you simply insert a mirroring affine transformation into the sequence of transformations above.
Unfortunately the OP did not mention which he meant a horizontal or a vertical flip. But as changing the rotation angle accordingly transforms one in the other, that isn't really necessary, either.
// Draw image as if the previous image was flipped and rotated around its center
// Image starts out being 1x1 with origin in lower left
// Move origin to center of image
AffineTransform A = AffineTransform.getTranslateInstance(-0.5, -0.5);
// Flip it horizontally
AffineTransform B = new AffineTransform(-1, 0, 0, 1, 0, 0);
// Stretch it to its dimensions
AffineTransform C = AffineTransform.getScaleInstance(image.getWidth(), image.getHeight());
// Rotate it
AffineTransform D = AffineTransform.getRotateInstance(rotate);
// Move it to have the same center as above
AffineTransform E = AffineTransform.getTranslateInstance(x + image.getWidth()/2, y + image.getHeight()/2);
// Concatenate
AffineTransform M = (AffineTransform) A.clone();
M.preConcatenate(B);
M.preConcatenate(C);
M.preConcatenate(D);
M.preConcatenate(E);
//Draw
contentByte.addImage(image, M);
(AddRotatedImage.java test method testAddRotatedFlippedImage)
The result with the same image as above:
With Interpolation
The OP asked in a yet another comment
How anti aliasing ?
The iText Image class knows an Interpolation property. By setting it to true (before adding the image to the document, obviously),
image.setInterpolation(true);
low resolution images are subject to interpolation when drawn.
E.g. using a 2x2 image with differently colored pixels instead of the image of Willi, you get the following results, first without interpolation, then with interpolation:
Confer the AddRotatedImage.java test testAddRotatedInterpolatedImage which adds this image:
Beware: iText Image property Interpolation effectively sets the Interpolate entry in the PDF image dictionary. The PDF specification notes in this context:
NOTE A conforming Reader may choose to not implement this feature of PDF, or may use any specific implementation of interpolation that it wishes.
Thus, on some viewers interpolation may occur differently than in your viewer, maybe even not at all. If you need a specific kind of interpolation on every viewer, upscale the image with the desired amount of interpolation / anti-aliasing before loading it into an iText Image.
public static BufferedImage rotateClockwise90( BufferedImage inputImage ){
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage returnImage = new BufferedImage( height, width , inputImage.getType() );
for( int x = 0; x < width; x++ ) {
for( int y = 0; y < height; y++ ) {
returnImage.setRGB( height-y-1, x, inputImage.getRGB( x, y ) );
}
}
return returnImage;
}
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
I want to be able to scale my image based on the screen size. In a normal java applet I would do something like the following....
int windowWidth = 1280;
int windowHeight = 720;
Image image;
public void paint(Graphics g)
{
g.drawImage(image, x, y, windowWidth / 4, windowHeight / 16, null);
}
I've been searching for an answer for a while and everything I find seems to turn up some weird result. From what I read I might need to do something with Resolution Independent Pixels but I'm not %100 sure.
The thing I am trying to avoid is having to create a whole new set of images and icons just for different screen densities. The method I showed above works for resizing desktop apps without a problem.
Edit:
This is what I have been using to draw an image in android.
Matrix matrix = new Matrix();
Bitmap image;
Constuctor....()
{
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.play);
}
public void render(Canvas c)
{
c.drawBitmap(image, matrix, null);
}
Hi see thsi question I have posted scale bitmap
If you are using canvas get the width and height of the canvas. or if you want to have it formal normal layouts then get the width and height by using
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
dispWidth=metrics.widthPixels;
dispheight=metrics.heightPixels;
and then scale our bitmap according to your requirement like this. In this I Have to have 8 bricks so I have taken the width by dividing with the Number of columns
String strwidth=String.valueOf(((float)(bmp.getWidth())/NO_COLUMNS));
if(strwidth.contains("."))
{
scalebit=Bitmap.createScaledBitmap(bmp, (int)(Math.ceil(((float)bmp.getWidth())/NO_COLUMNS))*NO_COLUMNS, bmp.getHeight(), true);
}
else
{
scalebit=bmp;
}
I had a BufferedImage an image of size (100mb) pixels 6720x9239 and needed many small images with pixels 60x60
firstly i used this code i found on the net
BufferedImage bi= ImageIO.read(new File(filename));
......
//in paint()
Image b=createImage(new FilteredImageSource(bi.getSource(),
new CropImageFilter(x, y , 60, 60)));
needed to wait around 1 to 5 secs for each small image very slow because i my app needed like 50 images which would mean ppl would have to w8 from 50 to 5*50 sec for panel to reload, so i chan that to
BufferedImage bi= ImageIO.read(new File(filename));
......
//in paint()
BufferedImage a = imageMap.getSubimage(x, y , 60, 60);
Image b = createImage(a.getSource());
feel really happy now had to let the world know this
Oh my god you solved my problem which had stumped me for like 5 days. I had just finished typing out the question and was about to submit it. APPARENTLY (now that I know using Images works) when you use a bufferedImage in g2d.drawImage(Image, at, this) the drawing is MUCH slower than if you use an Image. Something like 50x slower. By converting the BufferedImages to Images (I didn't know you could do that, less that would solve the problem) like this:
Inside the loadBullets function:
BufferedImage a;
Image b;
a = spriteSheetPositive.getSubimage(
//going to use the same image 252 times until I get the motherload of data string converted to the format:
//sprites[shotId]=spriteSheetPositive.getSubimage(x, y, width, height);
520, //x 520,1,536,16 (small lime star) id=100
1, //y
16, //width
15 //height
);
b= createImage(a.getSource());
sprites[shotID]=b;
I can now use images from a spritesheet as projectile sprites with as many as 1,000 on screen at time with no lag! Hooray!
My original question:
This is code within the paint function:
for (int i = 0; i < Projectiles.size(); i++) {
Shot02 m = (Shot02) Projectiles.get(i);
//m.getImage();
// g2d.drawImage(m.getImage(), m.getIntX(), m.getIntY(), this);
AffineTransform at = new AffineTransform();
// 4. translate it to the center of the component
at.translate(m.getDrawX(), m.getDrawY());
// 3. do the actual rotation
at.rotate(m.getAngle()); //rotation is Clockwise
g2d.drawImage(m.getImage(), at, this);
}
I am working on a platformer perspective shooting game. I switched from using a simple imageicon image to a bufferedImage created as a subImage from a sprite sheet. However, as a result of that the program lags with as little as 20 projectiles on screen, whereas previously I could have up to around 1000.
private void loadBullets() {//is done only once, when the window starts
// Get Image
ImageIcon icon = new ImageIcon(this.getClass().getResource("AbsoluteWin\\CustomShotsPositive.png"));
Image image = icon.getImage();
// Create empty BufferedImage, sized to Image
BufferedImage spriteSheetPositive =
new BufferedImage(
image.getWidth(null),
image.getHeight(null),
Transparency.BITMASK);
// Draw Image into BufferedImage
Graphics g = spriteSheetPositive.createGraphics();
g.drawImage(image, 0, 0, null);
int shotID = 1;
System.out.println(shotID);
while (shotID <= length) {//fills the array with the bullets from the sprite sheet spriteSheetPositive
sprites[shotID] = spriteSheetPositive.getSubimage(
//going to use the same image 252 times until I get the coordinates for all the other sub-images
//sprites[shotId]=spriteSheetPositive.getSubimage(x, y, width, height);
520, //x 520,1,536,16 (small lime star) id=100
1, //y
16, //width
15 //height
);
shotID += 1;
}
System.out.println(shotID);
}
Shot02 Class:
ImageIcon ii =
new ImageIcon(this.getClass().getResource("missile.png"));
image = ii.getImage();
//image=Destination.sprites[100];//is the source
This is the code in the Shot02 Class that controls the what image the bullets use. Again, if I uncomment the second option and use the BufferedImages, the program slows down like crazy.
I am aware of BufferedImage.getSubimage However, it cant deal with cropping images that are smaller than the cropping size throwing the exception:
java.awt.image.RasterFormatException: (y + height) is outside raster
I want to be able to crop either a PNG/JPG/GIF to a certain size however if the image is smaller than the cropping area centre itself on a white background. Is there a call to do this? Or do I need to create an image manually to centre the image on if so, how would I go about this?
Thanks
You cannot crop an image larger, only smaller. So, you start with the goal dimension,let's say 100x100. And your BufferedImage (bi), let's say 150x50.
Create a rectangle of your goal:
Rectangle goal = new Rectangle(100, 100);
Then intersect it with the dimensions of your image:
Rectangle clip = goal.intersection(new Rectangle(bi.getWidth(), bi.getHeight());
Now, clip corresponds to the portion of bi that will fit within your goal. In this case 100 x50.
Now get the subImage using the value of clip.
BufferedImage clippedImg = bi.subImage(clip,1, clip.y, clip.width, clip.height);
Create a new BufferedImage (bi2), the size of goal:
BufferedImage bi2 = new BufferedImage(goal.width, goal.height);
Fill it with white (or whatever bg color you choose):
Graphics2D big2 = bi2.getGraphics();
big2.setColor(Color.white);
big2.fillRect(0, 0, goal.width, goal.height);
and draw the clipped image onto it.
int x = goal.width - (clip.width / 2);
int y = goal.height - (clip.height / 2);
big2.drawImage(x, y, clippedImg, null);