Копирование частей изображений Java SWT с альфа - PullRequest
5 голосов
/ 20 февраля 2012

Я использую изображения Java SWT с полными 32-битными цветными и альфа-каналами (org.eclipse.swt.graphics.Image). Мне нужно извлечь прямоугольник изображения как новое изображение, включая полную информацию о альфа-канале.

Например, у меня может быть изображение размером 100 × 100, и мне нужно создать новое изображение с точным размером 50 × 50 пикселей в верхнем левом углу, точно так же, как в изображении 100 × 100. (Я режу, а не масштабирую.)

Моя первоначальная попытка состояла в том, чтобы создать чистое изображение нужного мне размера (50 × 50 в этом примере), затем получить ГХ для нового изображения, а затем нарисовать правильную часть старого изображения на новом изображении. Проблема заключалась в том, что прозрачность не была сохранена. Если бы мое новое изображение стало непрозрачным, то результат после рисования был бы полностью непрозрачным. Если бы мое новое изображение стало прозрачным, то результат после рисования был бы полностью прозрачным (со всеми правильными цветами RGB, но невидимым, потому что альфа была бы нулевой для всех пикселей).

Мое текущее решение неуклюже: я использую ГХ для рисования изображения, а затем вручную копирую рядный ряд альфа-канала.

/**
 * Returns a sub-rectangle from the image, preserving alpha transparency.
 * @param source The image from which to copy a portion
 * @param sourceData The ImageData of the source image
 * @param xInSource The x-coordinate in the source image from which to start copying
 * @param yInSource The y-coordinate in the source image from which to start copying
 * @param widthInSource The width (in pixels) of the copied image portion
 * @param heightInSource The height (in pixels) of the copied image portion
 * @param disp The display to use for the new image, or null for the current display
 * @return New image copied from a portion of the source.
 */
private static Image getRectHelper(final Image source, final ImageData sourceData,
        final int xInSource, final int yInSource, final int widthInSource, final int heightInSource, final Display disp)
{
    // In cases like extracting multiple frames at once, we need both the Image and its ImageData without
    // having to extract the ImageData over and over. That’s why this helper takes both parameters.

    // New up an image of the appropriate size
    final Display d = disp==null ? Display.getDefault() : disp;
    final Image dest = new Image(d, widthInSource, heightInSource);

    // This draws the colors from the original image, but does not set the destination alphas
    // (For the  Image class, alpha transparency doesn’t work well – it seems to have been tacked on as an afterthought.)
    final GC g = new GC(dest);
    g.drawImage(source, xInSource, yInSource, widthInSource, heightInSource, 0, 0, widthInSource, heightInSource);
    g.dispose();

    // Get a copy of the dest image data, then sets the destination alphas from the source image
    final ImageData destData = dest.getImageData();
    copyAlpha(sourceData, destData, xInSource, yInSource, widthInSource, heightInSource, 0, 0);

    // Construct a new image with the modified image data
    final Image ret = new Image(d, destData);
    dest.dispose();

    return ret;
}

/**
 * Copies a block of alpha channel information from the sourceData to the destaData. 
 * 
 * @param sourceData The source image data from which to copy alpha information
 * @param destData The destination image data to modify with new alpha information
 * @param xInSource The x-coordinate from which the alpha information should be copied
 * @param yInSource The y-coordinate from which the alpha information should be copied
 * @param width The width (in pixels) of the alpha information to copy
 * @param height The height (in pixels) of the alpha information to copy
 * @param xInDest The x-coordinate to which the alpha information should be copied 
 * @param yInDest The y-coordinate to which the alpha information should be copied
 */
private static void copyAlpha(final ImageData sourceData, final ImageData destData,
        final int xInSource, final int yInSource, final int width, final int height,
        final int xInDest, final int yInDest)
{
    final byte[] alphas = new byte[width];
    for (int ySrc = yInSource, yDst = yInDest; ySrc < yInSource+height; ++ySrc, ++yDst) {
        sourceData.getAlphas(xInSource, ySrc, width, alphas, 0);
        destData.setAlphas(xInDest, yDst, width, alphas, 0);
    }
}

Что мне здесь не хватает? Я новичок в Java, поэтому, возможно, я делаю что-то не так. Является ли альфа-канал запоздалой мыслью для класса SWT Image? Конечно, есть более простой и быстрый способ сделать это. У меня возникает соблазн просто использовать объекты ImageData напрямую и полностью обойти использование GC.

1 Ответ

0 голосов
/ 08 июля 2016

Так что одна вещь, которую вы можете упустить, это то, что существует несколько типов прозрачности для изображения.http://help.eclipse.org/kepler/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/ImageData.html#getTransparencyType()

В коде изменения размера, который мы используем для изображений SWT, мы сначала создаем новое изображение и получаем его ImageData.Затем, основываясь на типе прозрачности исходного ImageData изображения, мы делаем одно из следующих действий:

  • Если SWT.TRANSPARENCY_ALPHA, то применение альфа-аналога в вашем примере должно сработать.
  • Если SWT.TRANSPARENCY_PIXEL, то мы устанавливаем свойство transparentPixel ImageData в соответствии с ImageData исходного изображения.
  • Если SWT.TRANSPARENCY_MASK, то мы устанавливаем свойства maskData и maskPad нового ImageData для исходного изображения.ImageData.

Затем мы используем ImageData, чтобы создать новое изображение (избавиться от первого) и нарисовать его с помощью GC.

Надеемся, что вышеизложенное поможет вам приблизиться к решениювопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...