public void setData(byte[] data) throws IOException { int pos = 512; // skip the first 512 bytes - they are MAC specific crap byte[] compressed = compress(data, pos, data.length - pos); Header header = new Header(); header.wmfsize = data.length - 512; // we don't have a PICT reader in java, have to set default image size 200x200 header.bounds = new java.awt.Rectangle(0, 0, 200, 200); header.size = new java.awt.Dimension( header.bounds.width * Shape.EMU_PER_POINT, header.bounds.height * Shape.EMU_PER_POINT); header.zipsize = compressed.length; byte[] checksum = getChecksum(data); ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(checksum); out.write(new byte[16]); // 16-byte prefix which is safe to ignore header.write(out); out.write(compressed); setRawData(out.toByteArray()); }
private void initFromData(int d3dFormat, int width, int height, ByteBuffer[] mipmapData) throws IllegalArgumentException { // Check size of mipmap data compared against format, width and // height int topmostMipmapSize = width * height; int pitchOrLinearSize = width; boolean isCompressed = false; switch (d3dFormat) { case D3DFMT_R8G8B8: topmostMipmapSize *= 3; pitchOrLinearSize *= 3; break; case D3DFMT_A8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; case D3DFMT_X8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; case D3DFMT_DXT1: case D3DFMT_DXT2: case D3DFMT_DXT3: case D3DFMT_DXT4: case D3DFMT_DXT5: topmostMipmapSize = computeCompressedBlockSize(width, height, 1, d3dFormat); pitchOrLinearSize = topmostMipmapSize; isCompressed = true; break; default: throw new IllegalArgumentException("d3dFormat must be one of the known formats"); } // Now check the mipmaps against this size int curSize = topmostMipmapSize; int mipmapWidth = width; int mipmapHeight = height; int totalSize = 0; for (int i = 0; i < mipmapData.length; i++) { if (mipmapData[i].remaining() != curSize) { throw new IllegalArgumentException( "Mipmap level " + i + " didn't match expected data size (expected " + curSize + ", got " + mipmapData[i].remaining() + ")"); } /* Change Daniel Senff * I got the problem, that MipMaps below the dimension of 8x8 blocks with DXT5 * where assume smaller than they are created. * Assumed: < 16byte where 16byte where used by the compression. */ if (isCompressed) { // size calculation for compressed mipmaps if (mipmapWidth > 1) mipmapWidth /= 2; if (mipmapHeight > 1) mipmapHeight /= 2; curSize = computeCompressedBlockSize(mipmapWidth, mipmapHeight, 1, d3dFormat); } else { curSize /= 4; } totalSize += mipmapData[i].remaining(); } // OK, create one large ByteBuffer to hold all of the mipmap data totalSize += Header.writtenSize(); ByteBuffer buf = ByteBuffer.allocate(totalSize); buf.position(Header.writtenSize()); for (int i = 0; i < mipmapData.length; i++) { buf.put(mipmapData[i]); } this.buf = buf; // Allocate and initialize a Header header = new Header(); header.size = Header.size(); header.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; if (mipmapData.length > 1) { header.flags |= DDSD_MIPMAPCOUNT; header.mipMapCountOrAux = mipmapData.length; } header.width = width; header.height = height; if (isCompressed) { header.flags |= DDSD_LINEARSIZE; header.pfFlags |= DDPF_FOURCC; header.pfFourCC = d3dFormat; } else { header.flags |= DDSD_PITCH; // Figure out the various settings from the pixel format header.pfFlags |= DDPF_RGB; switch (d3dFormat) { case D3DFMT_R8G8B8: header.pfRGBBitCount = 24; break; case D3DFMT_A8R8G8B8: header.pfRGBBitCount = 32; header.pfFlags |= DDPF_ALPHAPIXELS; break; case D3DFMT_X8R8G8B8: header.pfRGBBitCount = 32; break; } header.pfRBitMask = 0x00FF0000; header.pfGBitMask = 0x0000FF00; header.pfBBitMask = 0x000000FF; if (d3dFormat == D3DFMT_A8R8G8B8) { header.pfABitMask = 0xFF000000; } } header.pitchOrLinearSize = pitchOrLinearSize; header.pfSize = Header.pfSize(); // Not sure whether we can get away with leaving the rest of the // header blank }