Inserting an image blob into MySQL - NullPointerException - java

I'm working on a database application in which I'm inserting images into a database. I'm storing the InputStreams in the database as a BLOB, and I am having issues retrieving them and setting them to an ImageIcon.
try{
// Return a resultset That contains
// the photos from the hashtags the user is following.
preparedStatement = conn.prepareStatement("SELECT * FROM PHOTOS WHERE CARID=?");
preparedStatement.setInt(1, 1);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
newPhoto = new Photo(resultSet.getInt(1), resultSet.getInt(2),
resultSet.getLong(3), resultSet.getBinaryStream(4));
System.out.println(resultSet.getBinaryStream(4));
photos.add(newPhoto);
System.out.println("Retrieving a photo");
}
}
photos is an ArrayList using my Photo class, which I am returning. Every time I try to display the images, I am getting the following error...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at business.appdev.Home.paintEditFrame(Home.java:577)
which is coming from the following code..
editImageLabel[i].setIcon(
new ImageIcon(img.getScaledInstance(imageSize, imageSize, imageSize)));
I have some basic println commands that are showing me what's returning from the MySQL database, which is
java.io.ByteArrayInputStream#2c0213a5
Retrieving a photo
java.io.ByteArrayInputStream#252ab7be
Retrieving a photo
where img is a BufferedImage. Any help would be greatly appreciated, Thanks!
Code for handling of the InputStream returned from the resultSet
for(int i = 0; i < photos.size(); i++){
img = ImageIO.read(photos.get(i).getInputStream());
editImageLabel[i] = new JLabel("");
editImageLabel[i].setIcon(new ImageIcon(img.getScaledInstance(imageSize, imageSize, imageSize)));
updated Photo class with byte[] data
Based on some other posts I've read, I'm storing the byte[] into a varbinary in MySQL. After that, I grab the photo data from my database using
InputStream in = resultSet.getBinaryStream(4);
byte[] photoData = new byte[(int) resultSet.getLong(3)];
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int len; (len = in.read(photoData)) != -1;)
os.write(photoData, 0, len);
os.flush();
I then create my photo object and return an ArrayList of photos. This has eliminated the NullPointerException, but I now cannot get the ImageIcon JLabels to show up. I use the following code to add them to a JPanel,
InputStream in = new ByteArrayInputStream(photos.get(i).getData());
BufferedImage newImage = ImageIO.read(in);
editImageLabel[i] = new JLabel("");
editImageLabel[i].setIcon(new ImageIcon(newImage.getScaledInstance(imageSize, imageSize, Image.SCALE_DEFAULT)));
and then I place the Label onto the JPanel.

Avoid the trouble of encoding and decoding images by storing the image in the filesystem and just the path to the image in your database. This can help to keep your database size down which, in turn, can help your transactional efficiency. You can write up some quick code to make a numeric filename for the file on your server.

Related

Why is this java code unable to save image in mysql database?

I have passed BufferedImage as argument from jsp to java with following code:
<%BufferedImage citizen = ImageIO.read(new File(add1));%>
<%BufferedImage degree=ImageIO.read(new File(deg1));%>
<%String available=com.Package1.UpdataStudentInfo.useValues(citizen, degree);%>
Here "add1" and "deg1" are the path of images.
In java page, I have written following code so that I could update those Image to database (Here, I had no image saved in db column previously, so I wanted to update those columns with no images). I have kept name of variables same in argument; i.e. BufferedImage citizen of jsp is BufferedImage citizen in java and BufferedImage degree of jsp is BufferedImage degree in java as well. So there is no problem in variable name.
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
try{
ByteArrayOutputStream os1 = new ByteArrayOutputStream();
ImageIO.write(citizen, "PNG", os1);
ByteArrayInputStream citizen_is = new ByteArrayInputStream(os1.toByteArray());
ByteArrayOutputStream os2 = new ByteArrayOutputStream();
ImageIO.write(degree, "PNG", os2);
ByteArrayInputStream degree_is = new ByteArrayInputStream(os2.toByteArray());
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/crm","root","");
PreparedStatement stmt=con.prepareStatement("UPDATE student SET citizenship=?, degree=? WHERE sn=? ");
stmt.setBlob(1, (Blob) citizen_is);
stmt.setBlob(2, (Blob) degree_is);
stmt.setInt(3, p);
int x=stmt.executeUpdate();
con.close();
}
I have catch statement as well to handle exception. But there is no any exception, no any runtime error and compile time error. But the image is not getting stored in the database.
Please, help me to store these two image in mysql database.
String updateSQL = "UPDATE student SET citizenship=?, degree=? WHERE sn=? ";
File os1 = new File(filenameImageCitizenShip); //load image as file
File os2 = new File(filenameImageDegree); //load image as file
FileInputStream inputOs1 = new FileInputStream(os1);
FileInputStream inputOs2 = new FIleInputStream(os2);
try{
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/crm","root","");
PreparedStatement pstmt = conn.prepareStatement(updateSQL);
pstmt.setBinaryStream(1,os1);
pstmt.setBinaryStream(2,os2);
pstmt.setBinaryStream(3,p);
pstmt.executeUpdate();
}catch(Exception e){
}

Retrieve a BLOB image from database and display it as Image on javafx

I have an Image in a database as a Blob and I want to display it as an Image on javafx, I did this:
Image imagenMonstruo = null;
Blob blob = rs.getBlob(12);
InputStream is = blob.getBinaryStream();
System.out.println(is.toString());
imagenMonstruo = new Image(is);
is.close();
And added to the object but when I run the application i don't get any error but I still don't getting the image display, with the system.out.println I get:
java.io.ByteArrayInputStream#e0debc3
So I don't know if i'm doing this properly and the others similar question asked here doesn't work.
Can you help me please?
EDIT where i get the image from my pc and it works but my problem is the image from the database in Blob format.
File file = new File("C:\\\\xampp\\htdocs\\monsterHunter\\imagenes\\anjanath.jpg");
BufferedImage imagen = ImageIO.read(file);
Image imagenMonstruo = SwingFXUtils.toFXImage(imagen, null );

How to load 1000+ images in jtable without java.lang.OutOfMemoryError: Java heap space exception

I am developing a swing application where i am displaying profile information along with their photo, after loading about 120 photos i get the exception
java.lang.OutOfMemoryError: Java heap space
I need to display around 1000+ profile informations.
This is how i load my images onto the jtable
try{
byte[] imageAsByteArray = getImageAsByteArray("E:\\Project\\WinPak\\Database\\UserImage\\"+employee.getLink3().trim()+"-1.jpg");
if(imageAsByteArray != null)
{
InputStream imageInputStream =new ByteArrayInputStream(imageAsByteArray);
Image img = ImageIO.read(imageInputStream);
ImageIcon imgIcon = new ImageIcon(img.getScaledInstance(100,100,Image.SCALE_AREA_AVERAGING));
data[index][10] =imgIcon; // data is of type object which i use to populate the jtable
imageInputStream.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
public byte[] getImageAsByteArray(String url)
{
try
{
InputStream is = new BufferedInputStream(new FileInputStream(url));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
is.close();
return buffer.toByteArray();
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
How do i overcome this problem. Is there any other way to display the information in swing?
If you are not aware of -Xmx command line argument to Java, you should learn about that and try that as a short term workaround. See documentation here.
The larger issue, though, is whether you really need to keep all of these images in memory at the same time. For a table that is displaying images, you might want to load the image only if it is currently supposed to be displayed or in a row near to what is being displayed.
I don't see anything obviously wrong with the way that you are reading the images, but I haven't worked with I/O of images in Java much, so perhaps that could be improved too.
In outline,
Create thumbnail-sized copies of your images, as shown here and here, to make instances of ImageIcon; use a background thread, as shown here, to keep the GUI responsive.
In your TableModel, return ImageIcon from getColumnClass() for the image column; the default renderer will display it automatically.
Use an adjacent component or popup to display the full size image on demand.

Saving an Image on Data Base

Basically I have to save an image I put on a JLabel on my DB(I have a BLOB var there)
JLabel LImg = new JLabel();
ImageIcon img = new ImageIcon("**filepath**");
LImg.setIcon(img);
stmt.executeUpdate("INSERT INTO CLIENT(ID, IMAGE) VALUES (1,"+LImg.getIcon()+")");
After running a few tests, I found out the getIcon method returns the file path, which explains this error
GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 132
:
Please, be especific on your answer(I'm new on JAVA)
You cannot paste the image itself into a SQL statement. You need to use a parameterized prepared statement, and set the value being inserted as a byte array:
BufferedImage bi = (BufferedImage)LImg.getImage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, type, baos);
byte[] dataToWrite = baos.toByteArray();
PreparedStatement stmt = con.prepareStatement("INSERT INTO CLIENT(ID, IMAGE) VALUES (1,?)");
stmt.setBlob(1, dataToWrite);
stmt.executeUpdate();

Retrieve Image in different Size from Database

I have stored some images in database, while retrieving them i want to resize it to 177x122. How can i do that in JAVA?
Here is some code that i have used to retrieve image from database, what changes need to be done to get a image of 177x122.
PreparedStatement pstm1 = con.prepareStatement("select * from image");
ResultSet rs1 = pstm1.executeQuery();
while(rs1.next()) {
InputStream fis1;
FileOutputStream fos;
String image_id;
try {
fis1 = rs1.getBinaryStream("image");
image_id=rs1.getString("image_id");
fos = new FileOutputStream(new File("images" + (image_id) + ".jpg"));
int c;
while ((c = fis1.read()) != -1) {
fos.write(c);
}
fis1.close();
fos.close();
JOptionPane.showMessageDialog(null, "Image Successfully Retrieved");
} catch (Exception ex) {
System.out.println(ex);
}
}
You can use the AWT provided BufferedImage and Graphics2D classes to resize your images. Source
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
Assuming the data in the image column is a image format that the Java Image I/O can read (such as JPEG and PNG), the Thumbnailator library should be able to achieve this.
The code which would retrieve the image data from the ResultSet as an InputStream and write to specified file can be written like this:
// Get the information we need from the database.
String imageId = rs1.getString("image_id");
InputStream is = rs1.getBinaryStream("image");
// Perform the thumbnail generation.
// You may want to substitute variables for the hard-coded 177 and 122.
Thumbnails.of(is)
.size(177, 122)
.toFile("images" + (imageId) + ".jpg");
// Thumbnailator does not automatically close InputStreams
// (which is actually a good thing!), so we'll have to close it.
is.close();
(I should disclaim that I haven't actually run this code against an actual database.)
Thumbnailator will read the image data from the InputStream retrieving binary data from the image column, then resize the image to fit into the 172 x 122 region, and finally output the thumbnail as a JPEG to the specified file.
By default, Thumbnailator will preserve the aspect ratio of the original image when resizing images (to prevent the thumbnail from looking distorted), so the image size will not necessarily be 172 x 122. If this behavior is undesirable, calling the forceSize method instead of the size method can achieve that.
Disclaimer: I maintain the Thumbnailator library.

Categories