package greenfoot.importer.scratch;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;


| A Scratch image resource, loaded from the Scratch Form class. | | @author neil | public class ScratchImage extends ScratchObject{ private ScratchObject bitsRef; private int w; private int h; private int d; private int offset; private BufferedImage img; private ScratchObject paletteRef; private Color[] palette; private boolean isResolved = false;
| Constructs a ScratchImage using the data read from the file | @param w Width of image | @param h Height of image | @param d Depth (number of *bits* (not bytes) per pixel) | @param offset Offset (TODO work out how this is used) | @param bitsRef Reference to byte array with raw compressed data | @param paletteRef Reference to palette (array of colours) | public ScratchImage(int w, int h, int d, int offset, ScratchObject bitsRef, ScratchObject paletteRef) { this.w = w; this.h = h; this.d = d; this.offset = offset; this.bitsRef = bitsRef; this.paletteRef = paletteRef; }
| Resolves the references for bits and palette, and decodes the image | public ScratchObject resolve(ArrayList<ScratchObject> objects) { if (isResolved) return this; if (paletteRef != null) { ScratchObject resolvedPalette = paletteRef.resolve(objects); ScratchObject[] pal = (ScratchObject[])resolvedPalette.getValue(); palette = new Color[pal.length]; for (int i = 0;i < pal.length;i++) { palette[i] = (Color)pal[i].resolve(objects).getValue(); } } img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); ScratchObject resolved = bitsRef.resolve(objects); if (resolved.getValue() instanceof int[]) { int[] values = (int[])resolved.getValue(); for (int pos = 0; pos < values.length;pos++) { setBitmapEntry(pos, values[pos]); } } else if (resolved.getValue() instanceof byte[]) { ByteArrayInputStream bitsInput = new ByteArrayInputStream((byte[]) resolved.getValue()); int bitmapPos = 0; decodeLen(bitsInput); for (int rawN = decodeLen(bitsInput);rawN != -1;rawN = decodeLen(bitsInput)) { int wordCount = rawN >> 2; switch (rawN & 0x3) { case 0: bitmapPos += wordCount; break; case 1: { int b = bitsInput.read(); int x = (b << 24) | (b << 16) | (b << 8) | b; int end = bitmapPos + wordCount; while (bitmapPos < end){ setBitmapEntry(bitmapPos++, x); } } break; case 2: { int x = 0; for (int i = 0; i < 4; i++) { x <<= 8; x |= bitsInput.read(); } int end = bitmapPos + wordCount; while (bitmapPos < end){ setBitmapEntry(bitmapPos++, x); } } break; case 3: { int end = bitmapPos + wordCount; while (bitmapPos < end){ int x = 0; for (int i = 0; i < 4; i++) { x <<= 8; x |= bitsInput.read(); } setBitmapEntry(bitmapPos++, x); } } break; } } } isResolved = true; return this; } private void setBitmapEntry(int pos, int val) { final int pixelsPerWord = 32 / d; for (int i = 0; i < pixelsPerWord;i++) { int index = d == 32 ? val : val & ((1 << d) - 1); int realWidth = (w + (pixelsPerWord - 1)) / pixelsPerWord; int x = ((pos % realWidth) * pixelsPerWord) + (pixelsPerWord - i); int y = pos / realWidth; if (x < w && y < h) { if (palette != null) { img.setRGB(x, y, palette[index].getRGB()); } else { if (index >> 24 == 0 && (index & 0xFFFFFF) != 0) { index |= 0xFF000000; } img.setRGB(x, y, index); } } val >>= d; } }
| Decodes a count field. | Anything above 0xE0 has its low bits (& 0x1F) merged with the next number | private int decodeLen(ByteArrayInputStream bitsInput) { int x = 0; int first = bitsInput.read(); if (first == -1) return -1; if (first == 0xFF) { for (int i = 0; i < 4; i++) { x <<= 8; x |= bitsInput.read(); } return x; } else if (first >= 0xE0) { x = (first & 0x1F) << 8; x |= bitsInput.read(); } else { x = first; } return x; } public int getWidth() { return w; } public int getHeight() { return h; } public BufferedImage getBufferedImage() { return img; } }
top, use, map, class ScratchImage

.   ScratchImage
.   resolve
.   setBitmapEntry
.   decodeLen
.   getWidth
.   getHeight
.   getBufferedImage




281 neLoCode + 12 LoComm