Refactored album art retrieval to prevent repeat loading of the same image into memory.

This commit is contained in:
neviyn 2016-03-08 17:01:24 +00:00
parent 0401c626e2
commit eb02ca7665
3 changed files with 87 additions and 49 deletions

View File

@ -0,0 +1,84 @@
package musicplayer;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public final class AlbumArtExtractor {
private static final String albumArtRegex = ".*(Cover|Folder|cover|folder)\\.(jpg|png)";
/**
* Get the album art for a song file.
* @param songFile File from which to get album art data
* (Data is either extracted from file metadata or an image in the same folder).
* @return Album art as a byte array.
*/
public static byte[] getImageData(File songFile){
Tag audioTags = null;
try {
audioTags = AudioFileIO.read(songFile).getTag();
} catch (CannotReadException | IOException | ReadOnlyFileException | TagException | InvalidAudioFrameException e) {
return null;
}
byte[] tmpArt = null;
try {
tmpArt = audioTags.getFirstArtwork().getBinaryData();
BufferedImage image = ImageIO.read(new ByteArrayInputStream(tmpArt));
tmpArt = convertImageToBytes(image);
} catch (IOException | NullPointerException e) {
try {
Path dir = songFile.toPath().getParent();
Optional<Path> imageFile = Files.walk(dir).filter(x -> x.toString().matches(albumArtRegex)).findFirst();
if (imageFile.isPresent()) {
Image actualImage = ImageIO.read(imageFile.get().toFile());
tmpArt = convertImageToBytes(actualImage);
}
} catch (NullPointerException | IOException ignored) {}
}
return tmpArt;
}
/**
* Convert an Image into its' byte array representation.
* @param image Image to convert.
* @return image as byte[].
*/
private static byte[] convertImageToBytes(Image image){
int imageScaleToSize = 50;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){
ImageIO.write(convertToBufferedImage(image.getScaledInstance(imageScaleToSize, imageScaleToSize, Image.SCALE_SMOOTH)), "jpg", baos);
baos.flush();
return baos.toByteArray();
} catch (IOException e) { return null; }
}
/**
* Convert an Image to a BufferedImage.
* @param image Source image.
* @return image as BufferedImage.
*/
private static BufferedImage convertToBufferedImage(Image image) {
BufferedImage newImage = new BufferedImage(
image.getWidth(null), image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
}

View File

@ -1,10 +1,12 @@
package musicplayer.db; package musicplayer.db;
import musicplayer.AlbumArtExtractor;
import musicplayer.model.*; import musicplayer.model.*;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -94,7 +96,7 @@ public class Gateway {
session.beginTransaction(); session.beginTransaction();
Optional<Album> albumObj = getOneAlbum(metadata.album); Optional<Album> albumObj = getOneAlbum(metadata.album);
if (!albumObj.isPresent()) { if (!albumObj.isPresent()) {
Album album = new Album(metadata.album, metadata.artwork); Album album = new Album(metadata.album, AlbumArtExtractor.getImageData(new File(metadata.songFile)));
albumObj = Optional.of(album); albumObj = Optional.of(album);
} }
Optional<Artist> artistObj = getOneArtist(metadata.artist); Optional<Artist> artistObj = getOneArtist(metadata.artist);

View File

@ -24,11 +24,8 @@ public class ExtractedMetadata {
public final String genre; public final String genre;
public final String songFile; public final String songFile;
public final String trackNumber; public final String trackNumber;
public final byte[] artwork;
public final String discNumber; public final String discNumber;
private static final String albumArtRegex = ".*(Cover|Folder|cover|folder)\\.(jpg|png)";
/** /**
* @param audioTags jaudiotagger tag data. * @param audioTags jaudiotagger tag data.
* @param songFile Location of the song file on the filesystem. * @param songFile Location of the song file on the filesystem.
@ -41,51 +38,6 @@ public class ExtractedMetadata {
this.genre = audioTags.getFirst(FieldKey.GENRE); this.genre = audioTags.getFirst(FieldKey.GENRE);
this.discNumber = audioTags.getFirst(FieldKey.DISC_NO); this.discNumber = audioTags.getFirst(FieldKey.DISC_NO);
this.songFile = songFile.getAbsolutePath(); this.songFile = songFile.getAbsolutePath();
byte[] tmpArt = null;
try {
tmpArt = audioTags.getFirstArtwork().getBinaryData();
BufferedImage image = ImageIO.read(new ByteArrayInputStream(tmpArt));
tmpArt = convertImageToBytes(image);
} catch (IOException | NullPointerException e) {
try {
Path dir = songFile.toPath().getParent();
Optional<Path> imageFile = Files.walk(dir).filter(x -> x.toString().matches(albumArtRegex)).findFirst();
if (imageFile.isPresent()) {
Image actualImage = ImageIO.read(imageFile.get().toFile());
tmpArt = convertImageToBytes(actualImage);
}
} catch (NullPointerException | IOException ignored) {}
}
artwork = tmpArt;
}
/**
* Convert an Image into its' byte array representation.
* @param image Image to convert.
* @return image as byte[].
*/
private static byte[] convertImageToBytes(Image image){
int imageScaleToSize = 50;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){
ImageIO.write(convertToBufferedImage(image.getScaledInstance(imageScaleToSize, imageScaleToSize, Image.SCALE_SMOOTH)), "jpg", baos);
baos.flush();
return baos.toByteArray();
} catch (IOException e) { return null; }
}
/**
* Convert an Image to a BufferedImage.
* @param image Source image.
* @return image as BufferedImage.
*/
private static BufferedImage convertToBufferedImage(Image image) {
BufferedImage newImage = new BufferedImage(
image.getWidth(null), image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
} }
@Override @Override