mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
use ImageIO in image index
This commit is contained in:
@@ -26,7 +26,6 @@ import icons.ImagesIcons;
|
||||
import org.intellij.images.ImagesBundle;
|
||||
import org.intellij.images.fileTypes.ImageFileTypeManager;
|
||||
import org.intellij.images.vfs.IfsUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -39,7 +38,7 @@ import java.util.Set;
|
||||
*/
|
||||
final class ImageFileTypeManagerImpl extends ImageFileTypeManager {
|
||||
|
||||
@NonNls private static final String IMAGE_FILE_TYPE_NAME = "Images";
|
||||
private static final String IMAGE_FILE_TYPE_NAME = "Image";
|
||||
private static final String IMAGE_FILE_TYPE_DESCRIPTION = ImagesBundle.message("images.filetype.description");
|
||||
private static final UserFileType imageFileType;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.intellij.images.index;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.indexing.*;
|
||||
@@ -33,14 +34,7 @@ import java.io.IOException;
|
||||
* @author spleaner
|
||||
*/
|
||||
public class ImageInfoIndex extends SingleEntryFileBasedIndexExtension<ImageInfoIndex.ImageInfo> {
|
||||
private static final int ourMaxImageSize;
|
||||
static {
|
||||
int maxImageSize = 200;
|
||||
try {
|
||||
maxImageSize = Integer.parseInt(System.getProperty("idea.max.image.filesize", Integer.toString(maxImageSize)), 10);
|
||||
} catch (NumberFormatException ex) {}
|
||||
ourMaxImageSize = maxImageSize;
|
||||
}
|
||||
private static final long ourMaxImageSize = (long)(Registry.get("ide.index.image.max.size").asDouble() * 1024 * 1024);
|
||||
|
||||
public static final ID<Integer, ImageInfo> INDEX_ID = ID.create("ImageFileInfoIndex");
|
||||
|
||||
@@ -94,17 +88,15 @@ public class ImageInfoIndex extends SingleEntryFileBasedIndexExtension<ImageInfo
|
||||
public FileBasedIndex.InputFilter getInputFilter() {
|
||||
return new DefaultFileTypeSpecificInputFilter(ImageFileTypeManager.getInstance().getImageFileType()) {
|
||||
@Override
|
||||
public boolean acceptInput(@NotNull final VirtualFile file) {
|
||||
return file.isInLocalFileSystem() &&
|
||||
file.getLength() / 1024 < ourMaxImageSize
|
||||
;
|
||||
public boolean acceptInput(@NotNull VirtualFile file) {
|
||||
return file.isInLocalFileSystem() && file.getLength() < ourMaxImageSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return 5;
|
||||
return 6;
|
||||
}
|
||||
|
||||
public static class ImageInfo {
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
package org.intellij.images.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author spleaner
|
||||
@@ -35,207 +37,34 @@ public class ImageInfoReader {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Info getInfo(@NotNull final String file) {
|
||||
return read(file);
|
||||
public static Info getInfo(@NotNull String file) {
|
||||
return read(new File(file));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Info getInfo(@NotNull final byte[] data) {
|
||||
return read(data);
|
||||
public static Info getInfo(@NotNull byte[] data) {
|
||||
return read(new ByteArrayInputStream(data));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Info read(@NotNull final String file) {
|
||||
final RandomAccessFile raf;
|
||||
try {
|
||||
//noinspection HardCodedStringLiteral
|
||||
raf = new RandomAccessFile(file, "r");
|
||||
try {
|
||||
return readFileData(raf);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
raf.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// nothing
|
||||
}
|
||||
private static Info read(@NotNull Object input) {
|
||||
try (ImageInputStream iis = ImageIO.createImageInputStream(input)) {
|
||||
Iterator<ImageReader> it = ImageIO.getImageReaders(iis);
|
||||
ImageReader reader = it.hasNext() ? it.next() : null;
|
||||
if (reader != null) {
|
||||
reader.setInput(iis, true);
|
||||
int w = reader.getWidth(0);
|
||||
int h = reader.getHeight(0);
|
||||
int bpp = reader.getRawImageType(0).getColorModel().getPixelSize();
|
||||
return new Info(w, h, bpp);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Info read(@NotNull final byte[] data) {
|
||||
final DataInputStream is = new DataInputStream(new UnsyncByteArrayInputStream(data));
|
||||
try {
|
||||
return readFileData(is);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static Info readFileData(@NotNull final DataInput di) throws IOException {
|
||||
final int b1 = di.readUnsignedByte();
|
||||
final int b2 = di.readUnsignedByte();
|
||||
|
||||
if (b1 == 0x47 && b2 == 0x49) {
|
||||
return readGif(di);
|
||||
}
|
||||
|
||||
if (b1 == 0x89 && b2 == 0x50) {
|
||||
return readPng(di);
|
||||
}
|
||||
|
||||
if (b1 == 0xff && b2 == 0xd8) {
|
||||
return readJpeg(di);
|
||||
}
|
||||
|
||||
//if (b1 == 0x42 && b2 == 0x4d) {
|
||||
// return readBmp(raf);
|
||||
//}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Info readGif(DataInput di) throws IOException {
|
||||
final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
|
||||
final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
|
||||
byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
|
||||
|
||||
di.readFully(a);
|
||||
if ((!eq(a, 0, GIF_MAGIC_89A, 0, 4)) && (!eq(a, 0, GIF_MAGIC_87A, 0, 4))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int width = getShortLittleEndian(a, 4);
|
||||
final int height = getShortLittleEndian(a, 6);
|
||||
|
||||
int flags = a[8] & 0xff;
|
||||
final int bpp = ((flags >> 4) & 0x07) + 1;
|
||||
|
||||
return new Info(width, height, bpp);
|
||||
}
|
||||
|
||||
private static Info readBmp(RandomAccessFile raf) throws IOException {
|
||||
byte[] a = new byte[44];
|
||||
if (raf.read(a) != a.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int width = getIntLittleEndian(a, 16);
|
||||
final int height = getIntLittleEndian(a, 20);
|
||||
|
||||
if (width < 1 || height < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int bpp = getShortLittleEndian(a, 26);
|
||||
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 & bpp != 32) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Info(width, height, bpp);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Info readJpeg(DataInput di) throws IOException {
|
||||
byte[] a = new byte[13];
|
||||
while (true) {
|
||||
di.readFully(a, 0, 4);
|
||||
|
||||
int marker = getShortBigEndian(a, 0);
|
||||
final int size = getShortBigEndian(a, 2);
|
||||
|
||||
if ((marker & 0xff00) != 0xff00) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (marker == 0xffe0) {
|
||||
if (size < 14) {
|
||||
di.skipBytes(size - 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
di.readFully(a, 0, 12);
|
||||
di.skipBytes(size - 14);
|
||||
}
|
||||
else if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
|
||||
di.readFully(a, 0, 6);
|
||||
|
||||
final int bpp = (a[0] & 0xff) * (a[5] & 0xff);
|
||||
final int width = getShortBigEndian(a, 3);
|
||||
final int height = getShortBigEndian(a, 1);
|
||||
|
||||
return new Info(width, height, bpp);
|
||||
}
|
||||
else {
|
||||
di.skipBytes(size - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Info readPng(DataInput di) throws IOException {
|
||||
final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
byte[] a = new byte[27];
|
||||
|
||||
di.readFully(a);
|
||||
if (!eq(a, 0, PNG_MAGIC, 0, 6)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int width = getIntBigEndian(a, 14);
|
||||
final int height = getIntBigEndian(a, 18);
|
||||
int bpp = a[22] & 0xff;
|
||||
int colorType = a[23] & 0xff;
|
||||
if (colorType == 2 || colorType == 6) {
|
||||
bpp *= 3;
|
||||
}
|
||||
|
||||
return new Info(width, height, bpp);
|
||||
}
|
||||
|
||||
private static int getShortBigEndian(byte[] a, int offset) {
|
||||
return (a[offset] & 0xff) << 8 | (a[offset + 1] & 0xff);
|
||||
}
|
||||
|
||||
private static boolean eq(byte[] a1, int offset1, byte[] a2, int offset2, int num) {
|
||||
while (num-- > 0) {
|
||||
if (a1[offset1++] != a2[offset2++]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int getIntBigEndian(byte[] a, int offset) {
|
||||
return (a[offset] & 0xff) << 24 | (a[offset + 1] & 0xff) << 16 | (a[offset + 2] & 0xff) << 8 | a[offset + 3] & 0xff;
|
||||
}
|
||||
|
||||
private static int getIntLittleEndian(byte[] a, int offset) {
|
||||
return (a[offset + 3] & 0xff) << 24 | (a[offset + 2] & 0xff) << 16 | (a[offset + 1] & 0xff) << 8 | a[offset] & 0xff;
|
||||
}
|
||||
|
||||
private static int getShortLittleEndian(byte[] a, int offset) {
|
||||
return (a[offset] & 0xff) | (a[offset + 1] & 0xff) << 8;
|
||||
}
|
||||
|
||||
public static class Info {
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
@@ -97,6 +97,8 @@ ide.javafx.tips.description=(Experimental) Use JavaFX Browser for 'Tips of the D
|
||||
ide.svg.icon=true
|
||||
ide.svg.icon.description=Load & auto-scale svg version of an icon if present
|
||||
|
||||
ide.index.image.max.size=10
|
||||
ide.index.image.max.size.description=Max size of an image to index, in megabytes
|
||||
ide.cached.image.max.size=1.5
|
||||
ide.cached.image.max.size.description=Max size of an image to cache, in megabytes
|
||||
|
||||
|
||||
@@ -46,12 +46,13 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.intellij.util.ui.JBUI.ScaleType.*;
|
||||
import static com.intellij.util.ui.JBUI.ScaleType.PIX_SCALE;
|
||||
import static com.intellij.util.ui.JBUI.ScaleType.SYS_SCALE;
|
||||
|
||||
public class ImageLoader implements Serializable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.ImageLoader");
|
||||
|
||||
public static final int CACHED_IMAGE_MAX_SIZE = (int)Math.round(Registry.doubleValue("ide.cached.image.max.size") * 1024 * 1024);
|
||||
public static final long CACHED_IMAGE_MAX_SIZE = (long)(Registry.doubleValue("ide.cached.image.max.size") * 1024 * 1024);
|
||||
private static final ConcurrentMap<String, Image> ourCache = ContainerUtil.createConcurrentSoftValueMap();
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"}) // set from com.intellij.internal.IconsLoadTime
|
||||
|
||||
Reference in New Issue
Block a user