001/** 002 * Copyright (c) 2008-2014 Ardor Labs, Inc. 003 * 004 * This file is part of Ardor3D. 005 * 006 * Ardor3D is free software: you can redistribute it and/or modify it 007 * under the terms of its license which may be found in the accompanying 008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>. 009 */ 010 011package com.ardor3d.image.util.dds; 012 013import static com.ardor3d.image.util.dds.DdsUtils.isSet; 014 015import java.io.IOException; 016import java.util.logging.Logger; 017 018import com.ardor3d.util.LittleEndianDataInput; 019 020class DdsHeader { 021 private static final Logger logger = Logger.getLogger(DdsHeader.class.getName()); 022 023 // ---- VALUES USED IN dwFlags ---- 024 // Required caps flag. 025 final static int DDSD_CAPS = 0x1; 026 // Required caps flag. 027 final static int DDSD_HEIGHT = 0x2; 028 // Required caps flag. 029 final static int DDSD_WIDTH = 0x4; 030 // Required when pitch is provided for an uncompressed texture. 031 final static int DDSD_PITCH = 0x8; 032 // Required caps flag. 033 final static int DDSD_PIXELFORMAT = 0x1000; 034 // Required in a mipmapped texture. 035 final static int DDSD_MIPMAPCOUNT = 0x20000; 036 // Required when pitch is provided for a compressed texture. 037 final static int DDSD_LINEARSIZE = 0x80000; 038 // Required in a depth texture. 039 final static int DDSD_DEPTH = 0x800000; 040 // ---- /end VALUES USED IN dwFlags ---- 041 042 // ---- VALUES USED IN dwCaps ---- 043 // Optional; must be used on any file that contains more than one surface (a mipmap, a cubic environment map, or 044 // volume texture). 045 final static int DDSCAPS_COMPLEX = 0x8; 046 // Optional; should be used for a mipmap. 047 final static int DDSCAPS_MIPMAP = 0x400000; 048 // Required caps flag. 049 final static int DDSCAPS_TEXTURE = 0x1000; 050 // ---- /end VALUES USED IN dwCaps ---- 051 052 // ---- VALUES USED IN dwCaps2 ---- 053 // Required for a cube map. 054 final static int DDSCAPS2_CUBEMAP = 0x200; 055 // Required when these surfaces are stored in a cube map. 056 final static int DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; 057 // Required when these surfaces are stored in a cube map. 058 final static int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; 059 // Required when these surfaces are stored in a cube map. 060 final static int DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; 061 // Required when these surfaces are stored in a cube map. 062 final static int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; 063 // Required when these surfaces are stored in a cube map. 064 final static int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; 065 // Required when these surfaces are stored in a cube map. 066 final static int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; 067 // Required for a volume texture. 068 final static int DDSCAPS2_VOLUME = 0x200000; 069 // ---- /end VALUES USED IN dwCaps2 ---- 070 071 int dwSize; 072 int dwFlags; 073 int dwHeight; 074 int dwWidth; 075 int dwLinearSize; 076 int dwDepth; 077 int dwMipMapCount; 078 int dwAlphaBitDepth; 079 int[] dwReserved1 = new int[10]; 080 DdsPixelFormat ddpf; 081 int dwCaps; 082 int dwCaps2; 083 int dwCaps3; 084 int dwCaps4; 085 int dwTextureStage; 086 087 static DdsHeader read(final LittleEndianDataInput in) throws IOException { 088 final DdsHeader header = new DdsHeader(); 089 header.dwSize = in.readInt(); 090 if (header.dwSize != 124) { 091 throw new Error("invalid dds header size: " + header.dwSize); 092 } 093 header.dwFlags = in.readInt(); 094 header.dwHeight = in.readInt(); 095 header.dwWidth = in.readInt(); 096 header.dwLinearSize = in.readInt(); 097 header.dwDepth = in.readInt(); 098 header.dwMipMapCount = in.readInt(); 099 header.dwAlphaBitDepth = in.readInt(); 100 for (int i = 0; i < header.dwReserved1.length; i++) { 101 header.dwReserved1[i] = in.readInt(); 102 } 103 header.ddpf = DdsPixelFormat.read(in); 104 header.dwCaps = in.readInt(); 105 header.dwCaps2 = in.readInt(); 106 header.dwCaps3 = in.readInt(); 107 header.dwCaps4 = in.readInt(); 108 header.dwTextureStage = in.readInt(); 109 110 final int expectedMipmaps = 1 + (int) Math.ceil(Math.log(Math.max(header.dwHeight, header.dwWidth)) 111 / Math.log(2)); 112 113 if (isSet(header.dwCaps, DDSCAPS_MIPMAP)) { 114 if (!isSet(header.dwFlags, DDSD_MIPMAPCOUNT)) { 115 header.dwMipMapCount = expectedMipmaps; 116 } else if (header.dwMipMapCount != expectedMipmaps) { 117 logger.fine("Got " + header.dwMipMapCount + " mipmaps, expected " + expectedMipmaps); 118 } 119 } else { 120 header.dwMipMapCount = 1; 121 } 122 123 return header; 124 } 125}