Я создал образец приложения SWT. Я загружаю в приложение несколько изображений. Мне нужно изменить размер всех изображений с разрешением выше 16x16 (ширина * высота) и сохранить их в отдельном месте.
По этой причине я масштабирую изображение и сохраняю масштабированное изображение в моем месте назначения. Ниже приведен фрагмент кода, который я использую для этого.
Используя getImageData() для получения данных изображения и сохранения, я использую метод ImageLoader save().
final Image mySampleImage = ImageResizer.scaleImage(img, 16, 16);
final ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { mySampleImage.getImageData() };
final String fileExtension = inputImagePath.substring(inputImagePath.lastIndexOf(".") + 1);
if ("GIF".equalsIgnoreCase(fileExtension)) {
imageLoader.save(outputImagePath, SWT.IMAGE_GIF);
} else if ("PNG".equalsIgnoreCase(fileExtension)) {
imageLoader.save(outputImagePath, SWT.IMAGE_PNG);
}
ImageLoader imageLoader.save(outputImagePath, SWT.IMAGE_GIF); выдает исключение, указанное ниже, когда я пытаюсь сохранить несколько определенных изображений (формат GIF или PNG).
org.eclipse.swt.SWTException: Unsupported color depth
at org.eclipse.swt.SWT.error(SWT.java:4533)
at org.eclipse.swt.SWT.error(SWT.java:4448)
at org.eclipse.swt.SWT.error(SWT.java:4419)
at org.eclipse.swt.internal.image.GIFFileFormat.unloadIntoByteStream(GIFFileFormat.java:427)
at org.eclipse.swt.internal.image.FileFormat.unloadIntoStream(FileFormat.java:124)
at org.eclipse.swt.internal.image.FileFormat.save(FileFormat.java:112)
at org.eclipse.swt.graphics.ImageLoader.save(ImageLoader.java:218)
at org.eclipse.swt.graphics.ImageLoader.save(ImageLoader.java:259)
at mainpackage.ImageResizer.resize(ImageResizer.java:55)
at mainpackage.ImageResizer.main(ImageResizer.java:110)
Сообщите мне, есть ли другой способ сделать то же самое (или) есть ли способ решить эту проблему.
@ greg-449 Спасибо за информацию. В настоящее время я использую только 2 формата, то есть GIF и PNG, и в зависимости от типа файла ImageResizer преобразует в соответствующий тип изображения. Никакого другого формата она не производит.
Под «форматом» здесь я подразумеваю точные значения полей в ImageData, которые вы передаете ImageLoader. Вы получаете исключение, потому что значение поля ImageData.depth не равно 1, 4 или 8.
@ greg-449 Я проверил глубину в данных изображения моего масштабированного изображения, и это 32, что является причиной этого исключения. Есть ли обходной путь для этой ситуации?
Вам либо нужно исправить средство изменения размера, чтобы сохранить палитру и глубину цвета, либо вам нужно написать код для преобразования изображения с измененным размером обратно в изображение на основе индексированной палитры с правильной глубиной цвета - я не знаю никакого SWT-кода, чтобы сделать это .




Наконец, я получил решение, сославшись на существующую ошибку Eclipse Неподдерживаемая ошибка затмения глубины цвета. В приведенном ниже коде я создал PaletteData со значениями RGB и обновил свои данные изображения.
Мой метод updateImagedata () принимает масштабированное изображение и возвращает правильные обновленные данные imageData, если глубина изображения составляет 32 или более.
private static ImageData updateImagedata(Image image) {
ImageData data = image.getImageData();
if (!data.palette.isDirect && data.depth <= 8)
return data;
// compute a histogram of color frequencies
HashMap<RGB, ColorCounter> freq = new HashMap<>();
int width = data.width;
int[] pixels = new int[width];
int[] maskPixels = new int[width];
for (int y = 0, height = data.height; y < height; ++y) {
data.getPixels(0, y, width, pixels, 0);
for (int x = 0; x < width; ++x) {
RGB rgb = data.palette.getRGB(pixels[x]);
ColorCounter counter = (ColorCounter) freq.get(rgb);
if (counter == null) {
counter = new ColorCounter();
counter.rgb = rgb;
freq.put(rgb, counter);
}
counter.count++;
}
}
// sort colors by most frequently used
ColorCounter[] counters = new ColorCounter[freq.size()];
freq.values().toArray(counters);
Arrays.sort(counters);
// pick the most frequently used 256 (or fewer), and make a palette
ImageData mask = null;
if (data.transparentPixel != -1 || data.maskData != null) {
mask = data.getTransparencyMask();
}
int n = Math.min(256, freq.size());
RGB[] rgbs = new RGB[n + (mask != null ? 1 : 0)];
for (int i = 0; i < n; ++i)
rgbs[i] = counters[i].rgb;
if (mask != null) {
rgbs[rgbs.length - 1] = data.transparentPixel != -1 ? data.palette.getRGB(data.transparentPixel)
: new RGB(255, 255, 255);
}
PaletteData palette = new PaletteData(rgbs);
ImageData newData = new ImageData(width, data.height, 8, palette);
if (mask != null)
newData.transparentPixel = rgbs.length - 1;
for (int y = 0, height = data.height; y < height; ++y) {
data.getPixels(0, y, width, pixels, 0);
if (mask != null)
mask.getPixels(0, y, width, maskPixels, 0);
for (int x = 0; x < width; ++x) {
if (mask != null && maskPixels[x] == 0) {
pixels[x] = rgbs.length - 1;
} else {
RGB rgb = data.palette.getRGB(pixels[x]);
pixels[x] = closest(rgbs, n, rgb);
}
}
newData.setPixels(0, y, width, pixels, 0);
}
return newData;
}
Чтобы найти минимальный индекс:
static int closest(RGB[] rgbs, int n, RGB rgb) {
int minDist = 256*256*3;
int minIndex = 0;
for (int i = 0; i < n; ++i) {
RGB rgb2 = rgbs[i];
int da = rgb2.red - rgb.red;
int dg = rgb2.green - rgb.green;
int db = rgb2.blue - rgb.blue;
int dist = da*da + dg*dg + db*db;
if (dist < minDist) {
minDist = dist;
minIndex = i;
}
}
return minIndex;
}
Класс ColourCounter:
class ColorCounter implements Comparable<ColorCounter> {
RGB rgb;
int count;
public int compareTo(ColorCounter o) {
return o.count - count;
}
}
При сохранении в формате GIF будет сохранено только изображение с глубиной цвета 1, 4 или 8 и с непрямой палитрой. Если ваш
ImageResizerвоспроизводит какой-либо другой формат, вам придется его преобразовать.