Example #1
0
  // Microsoft doesn't follow their own specifications and the
  // simplest conversion using the DxTex tool to e.g. a DXT3 texture
  // results in an illegal .dds file without either DDSD_PITCH or
  // DDSD_LINEARSIZE set in the header's flags. This code, adapted
  // from the DevIL library, fixes up the header in these situations.
  private void fixupHeader() {
    if (isCompressed() && !isSurfaceDescFlagSet(DDSD_LINEARSIZE)) {
      // Figure out how big the linear size should be
      int depth = header.backBufferCountOrDepth;
      if (depth == 0) {
        depth = 1;
      }

      header.pitchOrLinearSize =
          computeCompressedBlockSize(getWidth(), getHeight(), depth, getCompressionFormat());
      header.flags |= DDSD_LINEARSIZE;
    }
  }
Example #2
0
  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
  }