view dwt/internal/image/PngTrnsChunk.d @ 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents 9a64a7781bab
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 * Port to the D programming language:
 *     Frank Benoit <benoit@tionex.de>
 *******************************************************************************/
module dwt.internal.image.PngTrnsChunk;

import dwt.DWT;
import dwt.graphics.PaletteData;
import dwt.graphics.RGB;
import dwt.internal.image.PngChunk;
import dwt.internal.image.PNGFileFormat;
import dwt.internal.image.PngFileReadState;
import dwt.internal.image.PngIhdrChunk;
import dwt.internal.image.PngPlteChunk;

public class PngTrnsChunk : PngChunk {

    alias PngChunk.validate validate;

    static const int TRANSPARENCY_TYPE_PIXEL = 0;
    static const int TRANSPARENCY_TYPE_ALPHAS = 1;
    static const int RGB_DATA_LENGTH = 6;

this(RGB rgb) {
    super(RGB_DATA_LENGTH);
    setType(TYPE_tRNS);
    setInt16(DATA_OFFSET, rgb.red);
    setInt16(DATA_OFFSET + 2, rgb.green);
    setInt16(DATA_OFFSET + 4, rgb.blue);
    setCRC(computeCRC());
}

this(byte[] reference){
    super(reference);
}

override int getChunkType() {
    return CHUNK_tRNS;
}

void validateLength(PngIhdrChunk header, PngPlteChunk paletteChunk) {
    bool valid;
    switch (header.getColorType()) {
        case PngIhdrChunk.COLOR_TYPE_RGB:
            // Three 2-byte values (RGB)
            valid = getLength() is 6;
            break;
        case PngIhdrChunk.COLOR_TYPE_PALETTE:
            // Three 2-byte values (RGB)
            valid = getLength() <= paletteChunk.getLength();
            break;
        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
            // One 2-byte value
            valid = getLength() is 2;
            break;
        // Cannot use both Alpha and tRNS
        case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
        default:
            valid = false;
    }
    if (!valid) {
        DWT.error(DWT.ERROR_INVALID_IMAGE);
    }
}

/**
 * Answer whether the chunk is a valid tRNS chunk.
 */
void validate(PngFileReadState readState, PngIhdrChunk headerChunk, PngPlteChunk paletteChunk) {
    if (!readState.readIHDR
        || (headerChunk.getMustHavePalette() && !readState.readPLTE)
        || readState.readIDAT
        || readState.readIEND)
    {
        DWT.error(DWT.ERROR_INVALID_IMAGE);
    } else {
        readState.readTRNS = true;
    }

    validateLength(headerChunk, paletteChunk);

    super.validate(readState, headerChunk);
}


int getTransparencyType(PngIhdrChunk header) {
    if (header.getColorType() is PngIhdrChunk.COLOR_TYPE_PALETTE) {
        return TRANSPARENCY_TYPE_ALPHAS;
    }
    return TRANSPARENCY_TYPE_PIXEL;
}

/**
 * Answer the transparent pixel RGB value.
 * This is not valid for palette color types.
 * This is not valid for alpha color types.
 * This will convert a grayscale value into
 * a palette index.
 * It will compress a 6 byte RGB into a 3 byte
 * RGB.
 */
int getSwtTransparentPixel(PngIhdrChunk header) {
    switch (header.getColorType()) {
        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
            int gray = ((reference[DATA_OFFSET] & 0xFF) << 8)
                + (reference[DATA_OFFSET + 1] & 0xFF);
            if (header.getBitDepth() > 8) {
                return PNGFileFormat.compress16BitDepthTo8BitDepth(gray);
            }
            return gray & 0xFF;
        case PngIhdrChunk.COLOR_TYPE_RGB:
            int red = ((reference[DATA_OFFSET] & 0xFF) << 8)
                | (reference[DATA_OFFSET + 1] & 0xFF);
            int green = ((reference[DATA_OFFSET + 2] & 0xFF) << 8)
                | (reference[DATA_OFFSET + 3] & 0xFF);
            int blue = ((reference[DATA_OFFSET + 4] & 0xFF) << 8)
                | (reference[DATA_OFFSET + 5] & 0xFF);
            if (header.getBitDepth() > 8) {
                red = PNGFileFormat.compress16BitDepthTo8BitDepth(red);
                green = PNGFileFormat.compress16BitDepthTo8BitDepth(green);
                blue = PNGFileFormat.compress16BitDepthTo8BitDepth(blue);
            }
            return (red << 16) | (green << 8) | blue;
        default:
            DWT.error(DWT.ERROR_INVALID_IMAGE);
            return -1;
    }
}

/**
 * Answer an array of Alpha values that correspond to the
 * colors in the palette.
 * This is only valid for the COLOR_TYPE_PALETTE color type.
 */
byte[] getAlphaValues(PngIhdrChunk header, PngPlteChunk paletteChunk) {
    if (header.getColorType() !is PngIhdrChunk.COLOR_TYPE_PALETTE) {
        DWT.error(DWT.ERROR_INVALID_IMAGE);
    }
    byte[] alphas = new byte[paletteChunk.getPaletteSize()];
    int dataLength = getLength();
    int i = 0;
    for (i = 0; i < dataLength; i++) {
        alphas[i] = reference[DATA_OFFSET + i];
    }
    /**
     * Any palette entries which do not have a corresponding
     * alpha value in the tRNS chunk are spec'd to have an
     * alpha of 255.
     */
    for (int j = i; j < alphas.length; j++) {
        alphas[j] = cast(byte) 255;
    }
    return alphas;
}
}