Java - How to access an image packed in an applet jar - java

I have created an applet jar. That jar contains an images in the following folder
com\common\images\red.bmp
Now, I want to display this image on the Swing Applet.
private static final ImageIcon redIndicator = new ImageIcon("com\\common\\images\\red.bmp");
After that, I have attached the redIndicator to a JPanel but I am not able to see this image.
Any suggestions?
==================================EDITED=========================================
private static final ImageIcon marker = loadImage("com/common/images/scale.jpg");
#SuppressWarnings("unused")
private static ImageIcon loadImage(String imagePath) {
BufferedInputStream imgStream = new BufferedInputStream(TpcHandler.class.getResourceAsStream(imagePath));
int count = 0;
if (imgStream != null) {
byte buf[] = new byte[2400];
try {
count = imgStream.read(buf);
} catch (java.io.IOException ioe) {
return null;
} finally {
if (imgStream != null)
try {
imgStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (count <= 0) {
LOGGER.warning("Empty image file: " + imagePath);
return null;
}
return new ImageIcon(Toolkit.getDefaultToolkit().createImage(buf));
} else {
LOGGER.warning("Couldn't find image file: " + imagePath);
return null;
}
}
I am getting the following exception
java.io.IOException: Stream closed
at line count = imgStream.read(buf);

This should do the trick (if called from a class loaded from that same jar):
new ImageIcon(getClass().getResource("/com/common/images/red.bmp"))

Use YourPanel.class.getResourceAsStream("/com/common/images/red.bmp"), read the stream to a byte[] and construct the ImageIcon based on that. (and don't use bmps - prefer png or jpeg)

Applets and Images that is a frequently asked questions so, as for Java applets and images, I recommend you read one of my previous answers hope it helps a bit :)
Good luck

Related

Dynamically get image paths in eclipse

this is my code below
public BufferedImage icon32 = loadBufferedImage("/icon/icon32.png");
public BufferedImage icon64 = loadBufferedImage("/icon/icon64.png");
private BufferedImage loadBufferedImage(String string)
{
try
{
BufferedImage bi = ImageIO.read(this.getClass().getResource(string));
return bi;
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
I just wanted to know if there's a way to dynamically get the images from my image directory in eclipse instead of having to access them one by one

Delete an image on java server

I am doing a project that consists of a java server and a web page. I'd like to do that when you delete an object from the web, the server deletes the image asociated with this object. The images of each object are stored inside the images folder inside the web folder. But when i try to delete an image in the server, it says that the file is used by another process,because the thread of the web server is using it (i use grizzly), so I an't delete it.
//save the image
private void saveImage(Eetakemon e){
String base64Image = e.getImage().split(",")[1];
byte[] imageBytes =
javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);
File imageFile = new File("WEB\\images\\" + e.getName() + ".png");
try {
BufferedImage bufferedImage = ImageIO.read(new
ByteArrayInputStream(imageBytes));
ImageIO.write(bufferedImage, "png", imageFile);
}
catch(Exception ex){
ex.printStackTrace();
}
}
//delete the image
private void deleteImage(Eetakemon e){
try {
Files.deleteIfExists(Paths.get("WEB\\images\\" + e.getName() +
".png"));
}catch(Exception ex){
ex.printStackTrace();
}
}
The funcions are called inside the create and delete methods respectively
Thank you
You should use a separate folder in your filesystem with read/write access and keep your web server responsible for serving only static content, like static images, HTML,CSS and JS files.
To handle dynamic image files that can eventually be deleted during runtime keep the business logic in a separate service such as a REST API or a simple Servlet.
You can temporarily move the deleted images to a separate folder to be marked for deletion by a later scheduled batch job.
example of a service to delete an image:
public void removeFiles(List<String> fileNames) {
try {
String trashFolderLocation = ConfigurationManager.getInstance().getConfig().getImgFileTrashPath();
String uploadedFileLocation = ConfigurationManager.getInstance().getConfig().getFilePath();
FileUtil.moveFilesToFolder(uploadedFileLocation, trashFolderLocation, fileNames);
} catch(FileException e) {
logException(e);
}
}
In FileUtil:
public static boolean moveFilesToFolder(String locationFrom, String locationTo, List<String> fileNames) throws FileException {
try {
for (String fileName : fileNames) {
File afile = new File(locationFrom + fileName);
if (!afile.renameTo(new File(locationTo + fileName))) {
return false;
}
}
} catch (Exception e) {
throw new FileException(e);
}
return true;
}
You are experiencing a windows property of locking files that are used. You need to locate the process that are using the file and close the resource. This is your only viable option unless you are able to run on a system that doesn't lock files in use. Linux/Unix systems doesn't have this behaviour and they would allow you to delete the file even if it used.

Image URL to ParseFile?

I have a Parse Android app for which I am implementing Facebook sign up. Currently I am stuck on grabbing images to set as profile pictures of new ParseUser's. I have successfully used the Facebook Graph API to retrieve the correct URL (I have checked this by plugging it into a browser, where I am shown the right profile picture), but I now need a way to turn that URL into a byte array (byte[]) so that I can save the ParseFile field of our ParseUser's profile picture. I have already looked at all these SO questions:
• java.net.URL read stream to byte[]
• Efficiently read file from URL into byte[] in Java
• Get image with given url and convert it to byte array
None of these have worked. I am currently trying to use the Apache IOutils, like in the solution from the second link. Here is my current code for the AsyncTask:
private class SetProfPicWithURL extends AsyncTask<URL, Integer, byte[]> {
#Override
protected byte[] doInBackground(URL... imageURL) {
Log.i("SetProfPicWithURL", "invocation, URL: " + imageURL[0]);
InputStream is = null;
byte[] bytes = null;
try {
is = imageURL[0].openStream();
bytes = IOUtils.toByteArray(is);
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (is != null) try {
is.close();
if(bytes == null){Log.e("LoginActivity", "bytes is null int SetProfPicWithURL");}
final ParseFile imageFile = new ParseFile("image.jpg", bytes);
imageFile.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("LoginActivity", "getCurrentUser.put");
ParseUser.getCurrentUser().put(ParseUtils.PARSE_PROFILE_IMAGE, imageFile);
ParseUser.getCurrentUser().saveInBackground();
} else {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
}
Now when this code executes, I get no error logs, and a ParseFile is created. However, no profile pictures load within the app, and when I click to examine the file in the dashboard, I get this error message:
The file “tfss-0280f98d-7180-4528-9d24-3ec47d3b25d4-image.jpg” could
not be opened because it is empty.
Honestly, I'm at a loss. I've spent significantly more time on this one photo issue than any other part of implementing the Facebook login. And the way our database is set up, it is really not ideal to create another field to save the URL and load with Picasso. Any help with this issue is truly appreciated!
Directly save your imagefile as profile picture like this :
final ParseFile imageFile = new ParseFile("image.jpg", bytes);
ParseUser.getCurrentUser().put(ParseUtils.PARSE_PROFILE_IMAGE, imageFile);
ParseUser.getCurrentUser().saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("LoginActivity", "Profile saved succesfully");
} else {
e.printStackTrace();
}
}
});
EDIT :
Use this to get image byte array from url.
try {
java.net.URL img_value = new java.net.URL(imageURL);
Bitmap mIcon = BitmapFactory
.decodeStream(img_value.openConnection()
.getInputStream());
if (mIcon != null)
imgByteArray = encodeToByteArray(mIcon);
} catch (Exception e) {
e.printStackTrace();
}
public byte[] encodeToByteArray(Bitmap image) {
Log.d(TAG, "encodeToByteArray");
Bitmap b= image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imgByteArray = baos.toByteArray();
return imgByteArray ;
}

Loading a BufferedImage in a .jar

I'm currently trying working on an own game and created a Animation class, my problem is that i want the programm to be able to still find all the images when i create a jar out of it so I tried to load an Image via
BufferedImage img = ImageIO.read(getClass().getClassLoader().getResourceAsStream("player.png"));
but when I start the code I get a NullPointerException, i checked the location twice but the image exists and there should be no problems, can anyone help me out a bit?
try this
public BufferedImage loadImage(String fileName){
BufferedImage buff = null;
try {
buff = ImageIO.read(getClass().getResourceAsStream(fileName));
} catch (IOException e) {
e.printStackTrace();
return null;
}
return buff;
}

Can't load sound files LibGdx

I would like to load files directly from expansion OBB file by using AssetManager. I implemented my own FileHandleResolver
public class CustomFileHandleResolver implements FileHandleResolver
{
#Override
public FileHandle resolve(String fileName) {
return new CustomFileHandle(fileName);
}
}
I set it to my AssetManager. I created my own FileHandle and I override read() function
#Override
public InputStream read()
{
InputStream input = null;
try {
input = GameInfo.expansionFile.getInputStream(file.getPath().replace('\\', '/'));
} catch (IOException e) {
e.printStackTrace();
}
return input;
}
It loads all the files like .PNG, .PACK, .FNT, except .OGG files, so I guess that all sound files won't be loaded. I'm getting this error:
com.badlogic.gdx.utils.GdxRuntimeException: com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load dependencies of asset: SFx/button_click.ogg
And this error:
com.badlogic.gdx.utils.GdxRuntimeException: java.lang.ClassCastException: com.solidgamesstudio.threedefendersn.framework.CustomFileHandle cannot be cast to com.badlogic.gdx.backends.android.AndroidFileHandle
I read that zip can not be compressed. In 7zip I selected compression to "Store" so that it's not compressed at all, but still this problem occurs.
I traversed what is happening when files are being loaded and I found that AssetManager calls my CustomFileHandleResolver which creates CustomFileHandle. For every file that is not .OGG it calls InputStream read(). In this function it loads the file from the zip and it's fine. But as I said when it comes to loading .OGG it doesn't call this function. So it's not even trying yet to get the file from the zip. Question is, why .OGG file doesn't call InputStream read() in CustomFileHandle()?
UPDATE
I traversed more and I found out that it won't call InputStream read() because it can't create a Sound from FileHandle somehow. Clue to this is
CustomFileHandle cannot be cast to AndroidFileHandle
While to create a sound you need to pass fileHandle.
public Sound newSound (FileHandle fileHandle);
This is called from SoundLoader
#Override
public void loadAsync (AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
sound = Gdx.audio.newSound(file);
}
And that soundLoader uses my CustomFileHandleResolver. I don't know if Sounds are handled differently then other types of files. But by default AssetManager uses
public class InternalFileHandleResolver implements FileHandleResolver {
#Override
public FileHandle resolve (String fileName) {
return Gdx.files.internal(fileName);
}
}
I can't get into Gdx.files.internal to see if there are any special handling for Sounds.
UPDATE
Further analysis give me clue that the main problem is this as mentioned before.
CustomFileHandle cannot be cast to AndroidFileHandle
I don't know why it's casting my FileHandle to AndroidFileHandle while loading OGG file. If it loads fine other type of files, that probably means it doesn't do casting for them. That means that OGG is special and it needs casting. Any clues?
I have not found a way to load sound files from the zip file. Problem is that AssetManager loads sound files differently than other file types. Problem was that it is casting FileHandle to AndroidFileHandle, and since CustomFileHandle extends FileHandle it's impossible to cast it to AndroidFileHandle. I found no way to go around this, because it's deeply rooted.
CustomFileHandle cannot be cast to AndroidFileHandle
In this situation I had to take out all sound files from the OBB file and put them together with the app. I created another instance of AssetManager just for loading sounds. So, sounds are loaded normally as you would with AssetManager and for any other type of file I used AssetManager that uses my own FileHandlerResolver which uses my own FileHandle class that returns a file from the zip. The only problem with this approach is that you are limited to having sounds files only up to 50 MB.
I solved this problem extracting the zip to a specific folder,
and then reading from that external folder.
The extraction of the zip is done by these methods:
public void extract(){
String packageName = getPackageName();
File root = Environment.getExternalStorageDirectory();
File expPath = new File(root.toString() + "/Android/obb/" + packageName);
if (expPath.exists()) {
String strMainPath = null;
try {
strMainPath = expPath + File.separator + "main."
+ getPackageManager().getPackageInfo(
getPackageName(), 0).versionCode + "."
+ packageName + ".obb";
Log.e("Extract File path", "===>"+strMainPath);
File f=new File(strMainPath);
if(f.exists()){
Log.e("Extract From File path", "===> not exist");
}
else
{
Log.e("Extract From File path", "===> exist");
}
String pathToExtract = Environment.getExternalStorageDirectory()+"/"+Cons.FOLDERNAME;
Log.e("Extract to path", "===>"+pathToExtract);
flag = extractZip(strMainPath,pathToExtract);
Log.e("After Extract Zip", "===>"+flag);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
private boolean extractZip(String pathOfZip,String pathToExtract)
{
int BUFFER_SIZE = 1024;
int size;
byte[] buffer = new byte[BUFFER_SIZE];
try {
File f = new File(pathToExtract);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(pathOfZip), BUFFER_SIZE));
fileNum=0;
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = pathToExtract +"/"+ ze.getName();
if (ze.isDirectory()) {
File unzipFile = new File(path);
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
}
else {
updateFileNum();
FileOutputStream out = new FileOutputStream(path, false);
BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
try {
while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
}catch (Exception e) {
Log.e("Exception", "Unzip exception 1:" + e.toString());
}
finally {
fout.flush();
fout.close();
}
}
}
}catch (Exception e) {
Log.e("Exception", "Unzip exception2 :" + e.toString());
}
finally {
zin.close();
}
return true;
}
catch (Exception e) {
Log.e("Exception", "Unzip exception :" + e.toString());
}
return false;
}
Note: Extract it to .Android folder, otherwhise users will have direct acces to the assets. For example they will see the images in the Gallery app.
Well, I'm doing this currently. Whenever you need to get a real FileHandle in order for the sound loading mechanism to work (or in any other case were the casting to AndroidFileHandle is bothering you), unzip that file to a local directory and reuse it if needed:
public static FileHandle getRealFileHandle(String zipEntryPath, ZipFile zipFile) {
if (Gdx.files.local(zipEntryPath).exists()) {
return Gdx.files.local(zipEntryPath);
} else {
Gdx.app.log(TAG, "Unzipping file '" + zipEntryPath + "'...");
try {
FileHandle unzippedFile;
ZipEntry entry = zipFile.getEntry(zipEntryPath);
if (entry != null) {
unzippedFile = Gdx.files.local(zipEntryPath);
InputStream is = zipFile.getInputStream(entry);
byte[] buffer = new byte[65536];
int readLength;
while ((readLength = is.read(buffer)) >= 0) {
unzippedFile.writeBytes(buffer, 0, readLength, true);
}
return unzippedFile;
} else {
Gdx.app.error(TAG, "Entry '" + zipEntryPath + "' not found inside zip file.");
}
} catch (IOException ioe) {
Gdx.app.error(TAG, "A problem occurred while writing to the local file.");
}
}
return null;
}

Categories