Java SWT Image Resize Not Working - java

I am trying to resize a picture and save it however the picture I am saving is not resized.
Here is the code I am trying use.
if(CC_Files.fileExists(path)){
if(path.contains(".jpg") || path.contains(".png") || path.contains(".gif") ){
Image image = (Image) SWTResourceManager
.getImage(path);
ImageData imgData = image.getImageData();
imgData.scaledTo(150, 150);
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] {imgData};
imageLoader.save(Variables.getStrResources() + "\\Pics\\" + a.getHerd_id() + ".jpg",SWT.IMAGE_JPEG);
}
}

Your problem is that you do not read the JavaDoc where is wrriten
ImageData#scaledTo(int width, int height) - Returns a copy of the receiver which has been stretched or shrunk to the specified size.
So the solution is:
imgData = imgData.scaledTo(150, 150);
Documentation

Java SWT Image Resize is proper Working
ImageLoader class are used to load images from, and save images to, a file or stream
imageLoader.save(result, SWT.IMAGE_COPY)
FileDialog class allow the user to navigate the file system and select or enter a file name.
Button btnOpen = new Button(parent, SWT.NONE);
btnOpen.setBounds(200, 55, 68, 23);
btnOpen.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN);
String result = dialog.open();
if(result!=null)
{
Image image=SWTResourceManager.getImage(result);
//ImageData class are device-independent descriptions of images
ImageData imgData = image.getImageData();
imgData=imgData.scaledTo(200, 200);
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] {imgData};
imageLoader.save(result, SWT.IMAGE_COPY);
System.out.println("Width: "+imgData.width+".....Height: "+imgData.height);
lbl_image_text.setBounds(25,88,imgData.width+10,imgData.height+10);
lbl_image_text.setImage(SWTResourceManager.getImage(result));
}
}
});
btnOpen.setText("open");
CLabel lbl_image_text = new CLabel(parent, SWT.Resize);
Image size set to Label Dynamically
Button btnOpen = new Button(parent, SWT.NONE);
btnOpen.setBounds(200, 55, 68, 23);
btnOpen.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN);
String result = dialog.open();
if(result!=null)
{
Image image=SWTResourceManager.getImage(result);
//get Image width and height
lbl_image_text.setBounds(25,88,image.getBounds().width+10,image.getBounds().height+10);
lbl_image_text.setImage(SWTResourceManager.getImage(result));
}
}
});
btnOpen.setText("open");
CLabel lbl_image_text = new CLabel(parent, SWT.Resize);

Call this method from the SWT.addListener(SWT.Close, new CustomShellCloseListener()). Tha parameters required to pass are LabelImage(Do not Use Label.getImage() ,pass the direct path),label.getBounds.width ,label.getBounds.height
protected Image resize(Image imageFromSource, int width, int height) {
if(width>0 && height>0){
Image scaledImage = new Image(shellCCMPFMatrixBomCompare.getDisplay(), width, height);
GC gc = new GC(scaledImage); //Graphics Capabilities(GC instance) in SWT used to draw an Image, graphics, display
gc.setAntialias(SWT.ON); // Anti aliasing is used for making the low resolution image to redraw and make into a good resolution Image
gc.setInterpolation(SWT.HIGH); //Interpolation is based in the Graphics, it may not work properly in some systems
gc.drawImage(imageFromSource, 0, 0,
imageFromSource.getBounds().width, imageFromSource.getBounds().height,
0, 0, width, height);
/*drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight)
Copies a rectangular area from the source image into a (potentially different sized) rectangular area in the receiver.*/
gc.dispose();
return scaledImage;
}
else return imageFromSource;
}

Related

Image not showing in Jtable with renderer

I have created a CellRenderer for my table.
It works fine if the image is with small size.
However , if it's a little large it shows me blank space
public class ImageRenderer extends DefaultTableCellRenderer {
JLabel lbl = new JLabel();
JButton bouton ;
List<Commentaire> liste;
ImageIcon icon ;
Commentaire commentaire;
// Increase the height of each row by 50% so we can see the whole
// image.
public ImageRenderer() {
liste= new CommentaireDAO().findCommentaire();
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
if (column==0){
int id = (int)value;
Client c = new ClientDAO().findClientById(id);
InputStream photo= c.getPhoto();
try {
if (photo != null) {
int size = photo.available();
byte[] imageBytes = new byte[size];
photo.read(imageBytes);
ImageIcon icon = new ImageIcon(imageBytes);
Image img = icon.getImage();
BufferedImage bi = new BufferedImage(img.getWidth(null),img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.createGraphics();
g.drawImage(img, 0, 0, 50, 50, null);
ImageIcon newIcon = new ImageIcon(bi);
lbl.setSize(250,250);
lbl.setHorizontalAlignment(CENTER);
lbl.setIcon(newIcon);
}else{
System.out.println("photo null");
}
} catch (IOException ex) {
Logger.getLogger(OffreClientGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Is there any method to resize the image to fit in the column ?
The code in a renderer should be very fast and efficient. You should not be doing processing to create the image every time the cell is rendered.
Instead you should be storing an ImageIcon in the TableModel. Then you override the getColumnClass(...) method of the TableModel to return Icon.class and the JTable will used the default table renderer for the Icon.
If you want to dynamically scale the Icon you can add a Stretch Icon to the TableModel.

How to copy an area from a canvas into an image

I am trying to copy an area around the mouse cursor from my Canvas into an Image using the gc.copyarea method. Afterwards I want to paint that image onto a composite which appears after the mouse has been pressed for 1 second.
Below is my code so far:
In the paintControl Method of my canvas I copy the area to an image:
img = new Image(display, 40, 40);
gc.copyArea(img, mousePosition.x-20, mousePosition.y-20);
In the paintControl Method of my Composite I paint that image:
if (img != null) {
gc.drawImage(img, 0, 0);
}
The problem I am having is that only a very small part of the area is actually copied and painted onto the composite. Of the 40x40 pixel area, only an area of 10x20 pixel area in the bottom left corner is visible in the composite.
Example:
The cursor is next to the top left corner of the compisite. Only a small part of the area around the cursor is painted onto the compisite
Question: How can I copy an area from my canvas and paint it onto another composite correctly? What did I do wrong in my Code?
With some trial and error I managed to get something working that supposedly comes close to what you want.
public class CopyArea {
public static void main( String[] args ) {
CopyArea copyArea = new CopyArea();
copyArea.create();
copyArea.run();
}
private Display display;
private Image sourceImage;
private Point canvasSize;
private Shell shell;
private Canvas source;
private Canvas destination;
private Point snippetOrigin;
private Image snippet;
CopyArea() {
display = new Display();
sourceImage = new Image( display, getClass().getResourceAsStream( "mona-lisa.jpeg" ) );
canvasSize = new Point( sourceImage.getBounds().width, sourceImage.getBounds().height );
shell = new Shell( display );
source = new Canvas( shell, SWT.NONE );
destination = new Canvas( shell, SWT.NONE );
}
void create() {
shell.setLayout( new RowLayout() );
source.setLayoutData( new RowData( canvasSize ) );
source.addPaintListener( new PaintListener() {
#Override
public void paintControl( PaintEvent event ) {
event.gc.drawImage( sourceImage, 0, 0 );
if( snippetOrigin != null ) {
snippet = new Image( display, 40, 40 );
event.gc.copyArea( snippet, snippetOrigin.x, snippetOrigin.y );
destination.redraw();
snippetOrigin = null;
}
}
} );
source.addMouseListener( new MouseAdapter() {
#Override
public void mouseDown( MouseEvent event ) {
snippetOrigin = new Point( event.x, event.y );
source.redraw();
}
} );
destination.setLayoutData( new RowData( canvasSize ) );
destination.addPaintListener( new PaintListener() {
#Override
public void paintControl( PaintEvent event ) {
event.gc.setBackground( display.getSystemColor( SWT.COLOR_WHITE ) );
event.gc.fillRectangle( event.gc.getClipping() );
if( snippet != null ) {
event.gc.drawImage( snippet, 0, 0 );
}
}
} );
}
void run() {
shell.pack();
shell.open();
while( !shell.isDisposed() ) {
if( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
}
The sourceImage is just a placeholder for your drawing code. The source Canvas listens to mouse-down events and then draws a 40x40 snippet of its client are to the destination Canvas. Note that I used Canvas in both cases, but Canvas and Composite should also work.
Here is how it works: The mouse-listeners stores the mouse location into snippetOrigin and triggers a repaint of the source. The paint-listener of source takes a partial screen-shot of what it just has drawn if requested (snippetOrigin != null) and then forces destination to redrawitself. The paint-listener of destination simple draws the snippet image if there is any.
The code deos not yet correctly clip the copied image. If you press the mouse in the lower right corner of the source Canvas, some of the shell`s trimming will be copied as well.
For brevity, the code does not dispose of the snippet image before reusing it (and may have other leaks).
If you own the drawing code that paints your equivalent of the source Canvas, I would rather refactor it so that arbitrary portions can be drawn and then call the code with appropriate parameters to draw on the destination widget.
try this code, sample to get a copy of an canvas area and paste in an object
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 50, 50);
function copy() {
var imgData = ctx.getImageData(10, 10, 50, 50);
ctx.putImageData(imgData, 10, 70);
}
in this case the copy was paste at the canvas destination as origin
try this reference
https://www.w3schools.com/tags/canvas_getimagedata.asp
and this it the API reference
https://developer.mozilla.org/es/docs/Web/API/CanvasRenderingContext2D/getImageData

Formatting JPanel to Include ArrayList<JComponent> and Split View depending on view mode clicked

I'm trying to create this basic photo editing app via java swing. I have my code to work somewhat for when 1 picture is imported; I have 3 views - photo view which displays the photo only, thumbnail view which should display thumbnails of the pictures and split view which should be a combination of photo in BorderLayout.CENTER and thumbnail in BorderLayout.SOUTH. I've put in images and code excerpts as to why this isn't working the way it should. I can't upload any images but hopefully the excerpts provide much detail.
Split View Related Excerpts:
public void changeMode(boolean p, boolean b, boolean s){
/*
* Photo View will display a single PhotoComponent2 in a large area.
*/
isPhoto = p;
if (isPhoto){
//have a child JPanel set as CENTER component of BorderLayout of the JScrollPane (scroll)
childPhoto = new JPanel();
childPhoto.add(displayPhotos.get(getCurrentPhoto()), BorderLayout.CENTER);
System.out.println("in lc photo view class");
}
/*
* Browser View will hold all the images.
*/
isBrowse = b;
if(isBrowse){
//have a child JPanel set as CENTER component of BorderLayout to hold grid of thumbnails within
// JScrollPanel (scroll)
this.removeAll();
childBrowse = new JPanel();
tc2 = new ThumbnailComponent(displayPhotos.get(getCurrentPhoto()));
childBrowse.setLayout(new WrapLayout());
childBrowse.add(tc2);
// for(int i = 0; i < displayThumbs.size(); i++){
// childBrowse.add(displayThumbs.get(i));
// System.out.println(displayThumbs.get(i));
// }
System.out.println("in lc browser view class");
}
/*
* Split View is a combination of Photo and Browser View in that the top half
* is Photo View and the bottom half is Browser View.
*/
isSplit = s;
if(isSplit){
//have a child JPanel in CENTER to hold PhotoComponent plus a child JPanel in SOUTH to hold thumbnails
containsAll = new JPanel();
containsAll.setLayout(new BorderLayout());
containsAll.add(childPhoto, BorderLayout.CENTER);
containsAll.add(childBrowse, BorderLayout.SOUTH);
System.out.println("in lc split view class");
}
}
This is basically all of my problems right now. Currently the thumbnails that are being created are based on the current image. If I go to photo view and and change the image being displayed with my forward/backward buttons and then go back to browser view I get the thumbnail of the respective image. However, I want to be able to create thumbnails for all images being imported and then display it. I tried the for loop (which I've commented out) and that didn't help either. The other code associated with this are my main class that creates the JFrame and the buttons,etc., the photoComponent that has my paintComponent method I use in my thumbnails and lightComponent classes.
MyPhotos3:
view = new JMenu("View");
mbar.add(view);
pv = new JRadioButton("Photo Viewer");
pv.addActionListener(new ActionListener(){ //change status
public void actionPerformed(ActionEvent e){
sbar.setText("Status: By clicking this, you'll be able to view your photos one at a time");
boolean p = true;
boolean b = false;
boolean s = false;
lc.changeMode(p,b,s);
scroll.add(lc.childPhoto);
scroll.setViewportView(lc.childPhoto);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
b = new JRadioButton("Browser");
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){ //change status
sbar.setText("Status: By clicking this, you'll be able to view all your photos as thumbnails");
boolean p = false;
boolean b = true;
boolean s = false;
lc.changeMode(p,b,s);
scroll.setViewportView(lc.childBrowse);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
sm = new JRadioButton("Split Mode");
sm.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){ //change status
sbar.setText("Status: By clicking this, you'll be able to view a single photo with a film strip dimensional view");
boolean p = false;
boolean b = false;
boolean s = true;
lc.changeMode(p,b,s);
scroll.setViewportView(lc.containsAll);
scroll.getViewport().setBackground(Color.BLUE);
scroll.revalidate();
scroll.repaint();
}
});
PhotoComponent:
public PhotoComponent2(boolean f, Image img){
isFlip = f;
init = img;
x = init.getWidth(null);
y = init.getHeight(null);
setPreferredSize(new Dimension (x,y));
bi = new BufferedImage(init.getWidth(null),init.getHeight(null),BufferedImage.TYPE_INT_ARGB);
newIcon = new ImageIcon(bi);
img1 = new JLabel("", newIcon, JLabel.CENTER);
image = img1;
this.add(img1);
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocus(true);
//System.out.println("In constructor");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(init, 0, 0, null);
this.addMouseListener(this);
this.addMouseMotionListener(this);
//System.out.println("In paintComponent");
Thumbnails:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.JComponent;
public class ThumbnailComponent extends JComponent{
/**
* ThumbnailComponent class is a way to create smaller versions of each photo passed in.
*
* #author Puja Sheth
* #version 1.0 10/16/2014
*/
private static final long serialVersionUID = 1L;
PhotoComponent2 pc;
Image img;
double x;
double y;
int newX;
int newY;
public ThumbnailComponent(PhotoComponent2 input){
pc = input;
img = pc.init;
x = (img.getWidth(null))/(.5);
y = (img.getHeight(null))/(.5);
newX = (int)x;
newY = (int)y;
setPreferredSize(new Dimension (newX,newY));
// add(input);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics gCopy = g.create();
Graphics2D g2d = (Graphics2D)gCopy;
g2d.scale(.5,.5);
pc.paintComponent(g2d);
}
}
Any help would be greatly appreciated!!!!
Won't solve your problem, but a few general comments about your code:
scroll.add(lc.childPhoto);
scroll.setViewportView(lc.childPhoto);
scroll.revalidate();
scroll.repaint();
You should never add a component to a scrollpane. The only line of code you need is:
scroll.setViewportView(lc.childPhoto);
The scrollpane will automatically revalidate() and repaint() itself when the viewport view is changed.
super.paintComponent(g);
g.drawImage(init, 0, 0, null);
this.addMouseListener(this);
this.addMouseMotionListener(this);
Never add listener to a component is a painting method. Painting methods are for painting only. A listener has nothing to do with painting. Also, the painting methods are invoked whenever Swing determines the component needs to be repainted so you will be adding multiple listeners to the component.

How to create a screenshot of a JFace Dialog for printing?

I'm currently working on a eclipse plugin which shows the user a table of entries.
If the user double-clicks on a tablerow, a custom JFace-Dialog is opened in which the user can either print or cancel the dialog.
How can I create a screenshot of the dialog as an image?
My attemp at the moment gives me just a small rectangle.
PrintDialog dialog = new PrintDialog(this.getShell(), SWT.NONE);
PrinterData data = dialog.open();
if(data == null)
{
return;
}
GC gc = new GC(this.getShell().getDisplay());
final Image image = new Image(this.getShell().getDisplay(), this.getShell().getBounds());
gc.copyArea(image, this.getShell().getBounds().x, this.getShell().getBounds().y);
gc.dispose();
Printer printer = new Printer(data);
if(printer.startJob("Print"))
{
GC g = new GC(printer);
if(printer.startPage())
{
g.drawImage(image, 0, 0);
}
g.dispose();
printer.endPage();
}
printer.endJob();
printer.dispose();
The problem was the order. The image should be created first.
I didn't recognize that the screenshot size was right, but covered with the PrinterDialog.
GC gc = new GC(this.getShell().getDisplay());
final Image image = new Image(this.getShell().getDisplay(),this.getShell().getBounds());
gc.copyArea(image, this.getShell().getBounds().x, this.getShell().getBounds().y);
gc.dispose();
PrintDialog dialog = new PrintDialog(this.getShell(), SWT.NONE);
PrinterData data = dialog.open();
if(data == null)
{
return;
}
Printer printer = new Printer(data);
if(printer.startJob("Print"))
{
GC g = new GC(printer);
if(printer.startPage())
{
g.drawImage(image, 0, 0);
}
g.dispose();
printer.endPage();
}
printer.endJob();
printer.dispose();

Getting a black screen after trying to resize an image

I am currently trying to resize a picture that I am downloading from the web and putting it into a JPanel.
First, I am using the following code to download the image from the web:
public static Image MSImageHigh(){
URL imageUrl = null;
try {
imageUrl = new URL("http://www.hmdb.ca/labm/metabolites/"
+ HMDB + "/ms/spectraH/" + HMDB + "H.png");
} catch (MalformedURLException e) {
e.printStackTrace();
}
Image image = Toolkit.getDefaultToolkit().createImage(imageUrl);
return image;
}
Then I made a new method that resizes the image:
public static BufferedImage resizeImage() {
final BufferedImage bufferedImage = new BufferedImage(300, 500,BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setComposite(AlphaComposite.Src);
graphics2D.drawImage(MSImageHigh(), 0, 0, 200, 200, null);
graphics2D.dispose();
return bufferedImage;
}
This should produce s a new image that is resized to 200x200 px. What it in fact does is give me a black screen that is 200x200px in size. Btw, I also tried using TYPE_INT_ARGB instead of TYPE_INT_RGB, and this produces a totally transparent image, so that is not working either.
I used ImageIO.read(imageUrl) instead of Toolkit.getDefaultToolkit().createImage(imageUrl) and that solved the problem. Thanks #Hovercraft Full Of Eels!

Categories