Rev 3408 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2011.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.imgfmt.app.typ;
import uk.me.parabola.imgfmt.app.BitWriter;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
/**
* A true colour image.
*
* The image is represented by an array of int, with each int in RGBA format.
*
* @author Steve Ratcliffe
*/
public class TrueImage
implements Image {
private final ColourInfo colourInfo
;
private final int[] image
;
// If this is mode 16, then the transparent colour is set.
private int transparentPixel
;
public TrueImage
(ColourInfo colourInfo,
int[] image
) {
analyzeColours
(image, colourInfo
);
this.
colourInfo = colourInfo
;
this.
image = image
;
}
/**
* Write out the image. It is a set of pixel values that are full RGB values, rather than
* table driven as in the other image type. If the colour mode is 32 the colours have an
* extra 4 bit opacity value following.
*
* If the colour mode is 16, then the transparent pixel is written just before the image
* itself.
*/
public void write
(ImgFileWriter writer
) {
int width = colourInfo.
getWidth();
int height = colourInfo.
getHeight();
int mode = colourInfo.
getColourMode();
// For mode 16, the transparent pixel precedes the pixmap data.
if (mode ==
16) {
writer.
put((byte) (transparentPixel
>>8));
writer.
put((byte) (transparentPixel
>>16));
writer.
put((byte) (transparentPixel
>>24));
}
boolean hasAlpha = mode ==
32;
// Unlike the xpm based images, the true-colour image format does not appear to
// have any padding so write as a continuous block.
BitWriter bitWriter =
new BitWriter
();
for (int h =
0; h
< height
; h++
) {
for (int w =
0; w
< width
; w++
) {
int col = image
[h
* width + w
];
bitWriter.
putn(col
>>8 & 0xff,
8);
bitWriter.
putn(col
>>16 & 0xff,
8);
bitWriter.
putn(col
>>24 & 0xff,
8);
if (hasAlpha
) {
int alpha = 0xff -
(col
& 0xff
);
alpha = ColourInfo.
alphaRound4(alpha
);
bitWriter.
putn(alpha,
4);
}
}
}
writer.
put(bitWriter.
getBytes(),
0, bitWriter.
getLength());
}
/**
* Analyze the colours and determine if this should be a mode 16 or 32 image.
*
* By default it will be a mode 0 image. If there is any transparency the appropriate
* colour mode will be selected.
*
* @param image An images as an array of integers. Each integer is a colour in RGBA format.
* @param colourInfo The colour mode will be set in this.
*/
private void analyzeColours
(int[] image, ColourInfo colourInfo
) {
boolean hasTransparent =
false;
boolean hasAlpha =
false;
int nPixels = colourInfo.
getWidth() * colourInfo.
getHeight();
for (int i =
0; i
< nPixels
; i++
) {
int col = image
[i
];
int a = col
& 0xff
;
if (a ==
0) {
// Completely transparent, change all transparent pixels to the same value
if (hasTransparent
)
image
[i
] = transparentPixel
;
else
transparentPixel = image
[i
];
hasTransparent =
true;
} else if (a
< 255) {
// Partially transparent
hasAlpha =
true;
}
}
if (hasAlpha
)
colourInfo.
setColourMode(32);
else if (hasTransparent
)
colourInfo.
setColourMode(16);
}
}