Was verursacht den Unterschied? em> < /p>
Code: Select all
package com.jthink.songkong.ui.startdialog.editsongs;
import com.jthink.songkong.analyse.general.ArtworkHelper;
import com.jthink.songkong.analyse.musicbrainz.RemoteArtworkLookup;
import com.jthink.songkong.db.ImageCache;
import com.jthink.songkong.db.SongCache;
import com.jthink.songkong.preferences.UserOption;
import com.jthink.songkong.preferences.UserPreferences;
import com.jthink.songkong.ui.MainWindow;
import com.jthink.songkong.ui.startdialog.imagefilters.ImageFileFilter;
import com.jthink.songkong.ui.startdialog.imagefilters.ImageFilterFactory;
import com.jthink.songlayer.CoverImage;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.util.logging.Level;
import static com.jthink.songkong.ui.startdialog.editsongs.ArtworkTab.ARTWORK_SIZE;
import static com.jthink.songkong.ui.startdialog.editsongs.ImageSizeDefaults.MAX_IMAGE_SIZE;
import static com.jthink.songkong.ui.startdialog.editsongs.ImageSizeDefaults.MIN_IMAGE_SIZE;
public class ArtworkDropTarget extends DropTarget
{
private static CoverImage coverImage;
private JLabel displayArtwork;
public static DataFlavor uriListFlavor; //This is used by Linux for loading files
public static DataFlavor imageFlavor; //This is used by Firefox, when drag single image file
public static DataFlavor urlFlavour; //This is used by Firefox, when drag single image file
public static DataFlavor pictImageFlavor; //This is used by OSX for iTunes
public static DataFlavor imageIconDataFlavor; //When dragging from existingArtwork
static
{
try
{
uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
urlFlavour = new DataFlavor("application/x-java-url;class=java.net.URL");
imageFlavor = new DataFlavor("image/x-java-image;class=java.awt.Image");
pictImageFlavor = new DataFlavor("image/x-pict;class=java.io.InputStream");
imageIconDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
";class=\""+javax.swing.Icon.class.getName() + "\"");
}
catch (ClassNotFoundException cne)
{
throw new RuntimeException("unable to create uri-list flavor in drop target:" + cne.getMessage());
}
}
public ArtworkDropTarget(Component c, JLabel displayArtwork)
throws HeadlessException
{
super(c, DnDConstants.ACTION_COPY, null, true, null);
this.displayArtwork= displayArtwork;
}
public static void setCoverImage(CoverImage coverImage)
{
ArtworkDropTarget.coverImage = coverImage;
}
/**
* When used as Drop target
*
* @param dtde
*/
public synchronized void drop(DropTargetDropEvent dtde)
{
MainWindow.logger.severe("Starting Drop");
dtde.acceptDrop(DnDConstants.ACTION_COPY);
Transferable trans = dtde.getTransferable();
try
{
if (trans.isDataFlavorSupported(imageIconDataFlavor))
{
MainWindow.logger.severe("Received ImageIcon:"+trans.getTransferData(imageIconDataFlavor));
ImageIconWithOriginalImage icon = (ImageIconWithOriginalImage)trans.getTransferData(imageIconDataFlavor);
setExistingArtwork((BufferedImage)icon.getOriginalImage());
}
else if (trans.isDataFlavorSupported(DataFlavor.javaFileListFlavor) && ImageFilterFactory.getImageFilter().accept(((java.util.List) trans.getTransferData(DataFlavor.javaFileListFlavor)).get(0)))
{
MainWindow.logger.severe("Received Files:"+trans.getTransferData(DataFlavor.javaFileListFlavor));
File file = ((java.util.List) trans.getTransferData(DataFlavor.javaFileListFlavor)).get(0);
setExistingArtwork(file);
}
else if (trans.isDataFlavorSupported(imageFlavor) && trans.getTransferData(ArtworkDropTarget.imageFlavor) instanceof BufferedImage)
{
MainWindow.logger.severe("Received Image:"+trans.getTransferData(ArtworkDropTarget.imageFlavor));
setExistingArtwork((BufferedImage)trans.getTransferData(ArtworkDropTarget.imageFlavor));
}
else if (trans.isDataFlavorSupported(urlFlavour))
{
URI imageUri = ((URL) trans.getTransferData(ArtworkDropTarget.urlFlavour)).toURI();
MainWindow.logger.severe("Received ImageUrl:" + imageUri);
URI subUri = GoogleImageSearch.getImageUrlFromImageSearchUrl(imageUri);
if (GoogleImageSearch.isGoogleImageSearch(imageUri) && subUri!=null)
{
MainWindow.logger.severe("Received ImageSubUrl:" + subUri);
setExistingArtwork(subUri);
}
else
{
MainWindow.logger.severe("Received ImageUrl:" + imageUri);
setExistingArtwork(imageUri);
}
}
else
{
MainWindow.logger.severe("Unknown DataFlavor for ImageUrl");
for(DataFlavor next:trans.getTransferDataFlavors())
{
MainWindow.logger.severe(next.toString());
}
}
dtde.dropComplete(true);
}
catch(Exception ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
dtde.dropComplete(false);
}
}
/**
* TODO do we have to convert to JPG, cant we keep as PNG
* @param image
*/
private void setExistingArtwork(BufferedImage image)
{
try
{
byte[] imageData = writeCompressedJpegImageToByteArray(image, 1.0f);
coverImage = ImageCache.saveNewCoverImage(image, imageData, "internet", com.jthink.songlayer.CoverImage.createKeyFromData(imageData),
MIN_IMAGE_SIZE,
UserOption.ARTWORK_MAX_SIZE.getIntValue()
);
SongCache.saveImagesForReport(coverImage, null);
createNewArtworkImage(image);
}
catch (IOException ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
/**
* Write Compressed Jpeg, use minimum compression of 1f for best quality
*
* @param bi
* @param compressionLevel
* @return
* @throws IOException
*/
private static byte[] writeCompressedJpegImageToByteArray(BufferedImage bi, float compressionLevel) throws IOException
{
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName( "jpg").next();
ImageWriteParam writeParams = imageWriter.getDefaultWriteParam();
writeParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParams.setCompressionQuality(compressionLevel);
final ByteArrayOutputStream output = new ByteArrayOutputStream();
imageWriter.setOutput( new MemoryCacheImageOutputStream(output));
IIOImage outputImage = new IIOImage(bi, null, null);
imageWriter.write(null, outputImage, writeParams);
imageWriter.dispose();
output.flush();
final byte[] imageData = output.toByteArray();
return imageData;
}
/**
*
* @param imageUri
*/
private void setExistingArtwork(URI imageUri)
{
byte[] imageData = RemoteArtworkLookup.getDirectImage(imageUri.toString());
if (imageData != null)
{
BufferedImage image = ArtworkHelper.createBufferedImageFromRawData(imageData, imageUri.toString());
coverImage = ImageCache.saveNewCoverImage(image, imageData, "internet", com.jthink.songlayer.CoverImage.createKeyFromData(imageData),
UserPreferences.getInstance().getMinImageSize(),
(Integer) UserOption.ARTWORK_MAX_SIZE.getUserPref().getValue());
SongCache.saveImagesForReport(coverImage, null);
createNewArtworkImage(image);
}
else
{
MainWindow.logger.severe("Unable To Decode Image:"+imageUri.toString());
}
}
/**
*
* @param file
*/
private void setExistingArtwork(File file)
{
try
{
ImageFileFilter iff = ImageFilterFactory.getImageFilter();
if(iff.accept(file))
{
byte[] imageData = Files.readAllBytes(file.toPath());
BufferedImage image = ArtworkHelper.createBufferedImageFromRawData(imageData, file.getName());
coverImage = ImageCache.saveNewCoverImage(image, imageData, file.getName(),
com.jthink.songlayer.CoverImage.createKeyFromData(imageData),
UserPreferences.getInstance().getMinImageSize(),
(Integer) UserOption.ARTWORK_MAX_SIZE.getUserPref().getValue());
SongCache.saveImagesForReport(coverImage, null);
createNewArtworkImage(image);
}
}
catch(Exception ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
/**
* Update new artwork label with version of this image
*
* @param image
*/
private void createNewArtworkImage(BufferedImage image)
{
BufferedImage ret = new BufferedImage(ARTWORK_SIZE, ARTWORK_SIZE, BufferedImage.TYPE_INT_RGB);
ret.getGraphics().drawImage(image, 0, 0, ARTWORK_SIZE, ARTWORK_SIZE, null);
ImageIcon ii = new ImageIcon(ret);
displayArtwork.setIcon(ii);
displayArtwork.setText(image.getWidth() + " x " + image.getHeight());
ArtworkFont.formatArtworkLabel(displayArtwork);
}
public static CoverImage getCoverImage()
{
return coverImage;
}
}
Das synchronisierte Schlüsselwort entfernt, wie von VGR vorgeschlagen, wird nun in Drop, wirft aber eine Ausnahme aus
Code: Select all
01/2025 12.52.09:GMT:ArtworkDropTarget:drop:SEVERE: Cannot invoke "String.length()" because "spec" is null
java.awt.dnd.InvalidDnDOperationException: Cannot invoke "String.length()" because "spec" is null
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:274)
at java.desktop/sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
at java.desktop/java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:387)
at com.jthink.songkong.ui.startdialog.editsongs.ArtworkDropTarget.drop(ArtworkDropTarget.java:109)
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer.processDropMessage(SunDropTargetContextPeer.java:548)
at java.desktop/sun.lwawt.macosx.CDropTargetContextPeer.processDropMessage(CDropTargetContextPeer.java:129)
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchDropEvent(SunDropTargetContextPeer.java:864)
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:788)
at java.desktop/sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:48)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4828)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processDropTargetEvent(Container.java:4649)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4511)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4828)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:98)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Update 2 < /p>
, wie auch durch VGR vorgeschlagen wurde, hat mehrere Anrufe nach GetTransferData () entfernt. Daher kann er nur einmal pro Aufruf der Methode aufgerufen werden, machte keinen Unterschied. < /p>
Update 3
Sehen Sie sich die verfügbaren Datenaromen an und tauschten die Anweisung iF aus, sodass es nach
sucht
Code: Select all
uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
< /code>
vor < /p>
urlFlavour = new DataFlavor("application/x-java-url;class=java.net.URL");
Code: Select all
java.awt.dnd.InvalidDnDOperationException: Cannot invoke "String.length()" because "spec" is null
at java.desktop/sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:274)
at java.desktop/sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
at java.desktop/java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:387)