JavaScript DXT1/5 декомпрессия в помощь с переводом Java

Я пытаюсь перевести этот код JavaScript, который распаковывает изображения DXT5, в Java. У меня были серьезные проблемы до сегодняшнего дня, когда я понял, что отсутствие в Java типов без знака может быть проблемой с математикой и сдвигом битов (где сегодня я узнал, что в Java есть >>>). После исправления, теперь все на 99% правильно, но все еще не совсем идеально.

Я не знаком с JavaScript, а автор ссылки не знаком с Java (хотя они до сих пор были очень полезны).

Я подозреваю, что я все еще что-то пропустил в переводе, потому что декомпрессия все еще не совсем правильна, как демонстрируют эти два изображения. Прикрепленные изображения в основном прозрачные, со слабой тенью, идущей по диагонали снизу слева вверху справа. Вы можете видеть на плохом изображении случайные пиксели в областях, где оно должно быть полностью прозрачным. Одно изображение было получено из методов по ссылке, а другое было получено из кода ниже.

Я что-то пропустил в своем переводе, связанный с подписью или иным образом?

public void decode(){
    ByteBuffer bbIn = ByteBuffer.allocate(imageDataSize);
    bbIn.put(imageData, 0, imageDataSize);
    bbIn.position(0);

    byte[] decodedImage = new byte[height * width * 4];
    int currentX = 0;
    int currentY = 0;

    int position = 0;
    while (position < imageData.length) {
        if ((currentX == width) && (currentY == height)) {
            break;
        }

        switch (textureFormat) {
            case 10:
                //decodeDXT1(imageData, position, decodedImage, width, height, currentX, currentY);
                break;
            case 12:
                decodeDXT5(bbIn, position, decodedImage, width, height, currentY, currentX);
                break;
            default:
        }

        currentX += 4;
        if (currentX + 4 > width) {
            currentX = 0;
            currentY += 4;
        }
        position += textureFormat == 10 ? 8 : 16;
    }
}

private void decodeDXT5(ByteBuffer encodedBytes, int position, byte[] decodedBytes, int width, int height, int currentY, int currentX) {
    encodedBytes.order(ByteOrder.LITTLE_ENDIAN);
    encodedBytes.position(position);
    short alpha0 = (short)(encodedBytes.get() & 0xFF);
    short alpha1 = (short)(encodedBytes.get() & 0xFF);
    byte[] alphaCodes = new byte[6];
    encodedBytes.get(alphaCodes, 0, 6);

    byte[] color0 = RGB565_to_RGB888(encodedBytes.getShort());
    byte[] color1 = RGB565_to_RGB888(encodedBytes.getShort());
    byte[] c = new byte[]{encodedBytes.get(), encodedBytes.get(), encodedBytes.get(), encodedBytes.get()};

    byte[] alphaTable = new byte[]{
        (byte) (0x7 & alphaCodes[0]),
        (byte) (0x7 & (alphaCodes[0] >>> 3)),
        (byte) (0x7 & (((0x1 & alphaCodes[1]) << 2) + (alphaCodes[0] >>> 6))),
        (byte) (0x7 & (alphaCodes[1] >>> 1)),
        (byte) (0x7 & (alphaCodes[1] >>> 4)),
        (byte) (0x7 & (((0x3 & alphaCodes[2]) << 1) + (alphaCodes[1] >>> 7))),
        (byte) (0x7 & (alphaCodes[2] >>> 2)),
        (byte) (0x7 & (alphaCodes[2] >>> 5)),
        (byte) (0x7 & alphaCodes[3]),
        (byte) (0x7 & (alphaCodes[3] >>> 3)),
        (byte) (0x7 & (((0x1 & alphaCodes[4]) << 2) + (alphaCodes[3] >>> 6))),
        (byte) (0x7 & (alphaCodes[4] >>> 1)),
        (byte) (0x7 & (alphaCodes[4] >>> 4)),
        (byte) (0x7 & (((0x3 & alphaCodes[5]) << 1) + (alphaCodes[4] >>> 7))),
        (byte) (0x7 & (alphaCodes[5] >>> 2)),
        (byte) (0x7 & (alphaCodes[5] >>> 5))
    };

    for (int i = 0; i < 16; i++) {
        int e = i / 4;
        int pos = width * 4 * (height - 1 - currentY - e) + 4 * currentX + ((i - (e * 4)) * 4);
        decodedBytes[pos] = c2Value(3 & c[e], color0[0], color1[0]); //red
        decodedBytes[pos + 1] = c2Value(3 & c[e], color0[1], color1[1]); //green
        decodedBytes[pos + 2] = c2Value(3 & c[e], color0[2], color1[2]); //blue
        decodedBytes[pos + 3] = a2Value(alphaTable[i], alpha0, alpha1); //alpha

        c[e] >>>= 2;
    }
}

private byte[] RGB565_to_RGB888(short rgb) {
    byte r = (byte) (((rgb >>> 11) & 0x1F) * 8);
    byte g = (byte) (((rgb >>> 5) & 0x3F) * 4);
    byte b = (byte) ((rgb & 0x1F) * 8);

    return new byte[]{r, g, b};
}

private byte c2Value(int code, byte color0, byte color1) {
    short c0 = (short) (color0 & 0x00FF);
    short c1 = (short) (color1 & 0x00FF);
    switch (code) {
        case 0: return (byte) c0;
        case 1: return (byte) c1;
        case 2: 
        case 3: return (byte) ((c0 + c1 + 1) >>> 1);
    }
    return (byte) c0;
}

private byte a2Value(byte code, short a0, short a1) {
    if (a0 > a1) {
        switch (code) {
            case 0: return (byte) a0;
            case 1: return (byte) a1;
            case 2: return (byte) ((6 * a0 + 1 * a1) / 7);
            case 3: return (byte) ((5 * a0 + 2 * a1) / 7);
            case 4: return (byte) ((4 * a0 + 3 * a1) / 7);
            case 5: return (byte) ((3 * a0 + 4 * a1) / 7);
            case 6: return (byte) ((2 * a0 + 5 * a1) / 7);
            case 7: return (byte) ((1 * a0 + 6 * a1) / 7);
            default: LOG.error("a2Value code : " + code);
        }
    } else {
        switch (code) {
            case 0: return (byte) a0;
            case 1: return (byte) a1;
            case 2: return (byte) ((4 * a0 + 1 * a1) / 5);
            case 3: return (byte) ((3 * a0 + 2 * a1) / 5);
            case 4: return (byte) ((2 * a0 + 3 * a1) / 5);
            case 5: return (byte) ((1 * a0 + 4 * a1) / 5);
            case 6: return 0;
            case 7: return (byte) 0xFF;
            default: LOG.error("a2Value code : " + code);
        }
    }

    return (byte) a0;
}

плохое декодирование

хорошее декодирование

0 ответов

Другие вопросы по тегам