Commits

Roi Atalla committed 937ebfc

Forgot to add files.

Comments (0)

Files changed (7)

.idea/workspace.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ChangeListManager">
-    <list default="true" id="3bd3582b-975a-4915-888d-8e2c52d85938" name="Default" comment="Fully ported Example 16.1.">
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/Example16_1.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/testdata/Test.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/TextureGenerator.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.ScreenCoords.vert" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.TextureGamma.frag" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.TextureNoGamma.frag" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/testdata/test.txt" />
-      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\util\img\dds\DdsUtil.java" afterPath="" />
-      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\util\img\dds\ImageSet.java" afterPath="" />
-      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\util\img\dds\DdsLoader.java" afterPath="" />
-      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\util\img\dds\ImageCreator.java" afterPath="" />
-      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\util\img\dds\ImageFormat.java" afterPath="" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter14/example3/Example14_3.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter14/example3/Example14_3.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter15/Example15_1.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter15/Example15_1.java" />
+    <list default="true" id="3bd3582b-975a-4915-888d-8e2c52d85938" name="Default" comment="">
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.gamma_ramp.png" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/DdsLoader.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/DdsUtil.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/ImageCreator.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/ImageFormat.java" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/rosick/jglsdk/glimg/ImageSet.java" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
     </list>
     <ignored path="OpenGL.iws" />
     <file path="/a.xml" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850040520" ignored="false" />
     <file path="/a.html" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850041808" ignored="false" />
     <file path="/a.groovy" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850042481" ignored="false" />
-    <file path="/Dummy.txt" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1364718519267" ignored="false" />
+    <file path="/Dummy.txt" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1364718742000" ignored="false" />
     <file path="/Example12_1.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1362027020824" ignored="false" />
     <file path="/example12.1.DiffuseSpecular.frag" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361702005810" ignored="false" />
     <file path="/LightManager.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1362461124226" ignored="false" />
     <disable_hints />
   </component>
   <component name="DebuggerManager">
-    <ui_properties default_suspend_policy="SuspendAll" default_condition_enabled="true" />
     <line_breakpoints default_suspend_policy="SuspendAll" default_condition_enabled="true" />
     <breakpoint_any default_suspend_policy="SuspendAll" default_condition_enabled="true">
       <breakpoint>
         <option name="LOG_MESSAGE" value="&#13;&#13;JAVA" />
       </breakpoint>
     </breakpoint_any>
+    <ui_properties default_suspend_policy="SuspendAll" default_condition_enabled="true" />
     <breakpoint_rules />
     <ui_properties />
   </component>
       <sortByType />
     </navigator>
     <panes>
-      <pane id="PackagesPane">
-        <subPane />
-      </pane>
       <pane id="Scope" />
       <pane id="ProjectPane">
         <subPane>
           </PATH>
         </subPane>
       </pane>
+      <pane id="PackagesPane">
+        <subPane />
+      </pane>
     </panes>
   </component>
   <component name="PropertiesComponent">
     <property name="project.structure.last.edited" value="Facets" />
     <property name="project.structure.proportion" value="0.15" />
     <property name="options.splitter.main.proportions" value="0.3" />
+    <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeWidth1" value="285" />
+    <property name="MemberChooser.sorted" value="false" />
     <property name="recentsLimit" value="5" />
-    <property name="MemberChooser.sorted" value="false" />
-    <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeWidth1" value="285" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeWidth2" value="292" />
     <property name="last_opened_file_path" value="$PROJECT_DIR$/.idea/workspace.xml" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_treeWidth0" value="296" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatWidth2" value="293" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatWidth1" value="292" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatWidth0" value="292" />
-    <property name="options.lastSelected" value="project.propVCSSupport.Ignored.Files" />
+    <property name="options.lastSelected" value="project.propVCSSupport.Mappings" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatOrder1" value="1" />
+    <property name="project.structure.side.proportion" value="0.2" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatOrder0" value="0" />
-    <property name="project.structure.side.proportion" value="0.2" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatOrder3" value="3" />
+    <property name="MemberChooser.copyJavadoc" value="false" />
     <property name="FileHistory.org.zmlx.hg4idea.provider.HgHistoryProvider_flatOrder2" value="2" />
-    <property name="MemberChooser.copyJavadoc" value="false" />
     <property name="restartRequiresConfirmation" value="true" />
+    <property name="dynamic.classpath" value="false" />
     <property name="options.searchVisible" value="true" />
-    <property name="dynamic.classpath" value="false" />
   </component>
   <component name="RecentsManager">
     <key name="CopyClassDialog.RECENTS_KEY">
       <option name="PROGRAM_PARAMETERS" />
       <method />
     </configuration>
-    <configuration default="true" type="AndroidTestRunConfigurationType" factoryName="Android Tests">
-      <module name="" />
-      <option name="TESTING_TYPE" value="0" />
-      <option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
-      <option name="METHOD_NAME" value="" />
-      <option name="CLASS_NAME" value="" />
-      <option name="PACKAGE_NAME" value="" />
-      <option name="TARGET_SELECTION_MODE" value="EMULATOR" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="COMMAND_LINE" value="" />
-      <option name="WIPE_USER_DATA" value="false" />
-      <option name="DISABLE_BOOT_ANIMATION" value="false" />
-      <option name="NETWORK_SPEED" value="full" />
-      <option name="NETWORK_LATENCY" value="none" />
-      <option name="CLEAR_LOGCAT" value="false" />
-      <method />
-    </configuration>
     <configuration default="true" type="MavenRunConfiguration" factoryName="Maven">
       <MavenSettings>
         <option name="myGeneralSettings" />
       </MavenSettings>
       <method />
     </configuration>
+    <configuration default="true" type="AndroidTestRunConfigurationType" factoryName="Android Tests">
+      <module name="" />
+      <option name="TESTING_TYPE" value="0" />
+      <option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
+      <option name="METHOD_NAME" value="" />
+      <option name="CLASS_NAME" value="" />
+      <option name="PACKAGE_NAME" value="" />
+      <option name="TARGET_SELECTION_MODE" value="EMULATOR" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="COMMAND_LINE" value="" />
+      <option name="WIPE_USER_DATA" value="false" />
+      <option name="DISABLE_BOOT_ANIMATION" value="false" />
+      <option name="NETWORK_SPEED" value="full" />
+      <option name="NETWORK_LATENCY" value="none" />
+      <option name="CLEAR_LOGCAT" value="false" />
+      <method />
+    </configuration>
     <configuration default="true" type="Remote" factoryName="Remote">
       <option name="USE_SOCKET_TRANSPORT" value="true" />
       <option name="SERVER_MODE" value="false" />
       <option name="PORT" value="5005" />
       <method />
     </configuration>
+    <configuration default="true" type="Applet" factoryName="Applet">
+      <module name="" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="HTML_FILE_NAME" />
+      <option name="HTML_USED" value="false" />
+      <option name="WIDTH" value="400" />
+      <option name="HEIGHT" value="300" />
+      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
+      <option name="VM_PARAMETERS" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <method />
+    </configuration>
     <configuration default="true" type="TestNG" factoryName="TestNG">
       <module name="" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <listeners />
       <method />
     </configuration>
-    <configuration default="true" type="Applet" factoryName="Applet">
-      <module name="" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="HTML_FILE_NAME" />
-      <option name="HTML_USED" value="false" />
-      <option name="WIDTH" value="400" />
-      <option name="HEIGHT" value="300" />
-      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
-      <option name="VM_PARAMETERS" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <method />
-    </configuration>
     <configuration default="true" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="" />
       <option name="VM_PARAMETERS" value="-Djava.library.path=files/natives/" />
       <created>1364273508722</created>
       <updated>1364273508722</updated>
     </task>
-    <option name="localTasksCounter" value="27" />
+    <task id="LOCAL-00027" summary="Fully ported Example 16.1. Also moved the 'dds' classes to their original packaging for better credit to author.">
+      <created>1364718745149</created>
+      <updated>1364718745149</updated>
+    </task>
+    <option name="localTasksCounter" value="28" />
     <servers />
   </component>
   <component name="TodoView" selected-index="4">
       <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.23987207" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="JetGradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
-      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.34754798" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2707889" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.29530916" sideWeight="0.51387405" order="8" side_tool="true" content_ui="tabs" />
       <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.18366013" sideWeight="0.14915694" order="2" side_tool="true" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.29104477" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
-      <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32942432" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
-      <window_info id="TODO" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.3283582" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.14605543" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.18366013" sideWeight="0.17250325" order="1" side_tool="true" content_ui="tabs" />
       <window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.36819637" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.20864461" sideWeight="0.67164177" order="0" side_tool="true" content_ui="combo" x="2394" y="136" width="397" height="768" />
+      <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.20864461" sideWeight="0.85394454" order="0" side_tool="true" content_ui="combo" x="2394" y="136" width="397" height="768" />
       <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2739872" sideWeight="0.4823906" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Documentation" active="true" anchor="right" auto_hide="false" internal_type="SLIDING" type="FLOATING" visible="true" weight="0.32977587" sideWeight="0.80490404" order="3" side_tool="false" content_ui="combo" x="2005" y="108" width="1736" height="896" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2497332" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.34754798" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32942432" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
       <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39978677" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
     </layout>
     <option name="MAXIMUM_HISTORY_ROWS" value="1000" />
     <option name="FORCE_NON_EMPTY_COMMENT" value="false" />
     <option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="false" />
-    <option name="LAST_COMMIT_MESSAGE" value="Fully ported Example 16.1." />
+    <option name="LAST_COMMIT_MESSAGE" value="Fully ported Example 16.1. Also moved the 'dds' classes to their original packaging for better credit to author." />
     <option name="MAKE_NEW_CHANGELIST_ACTIVE" value="false" />
     <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
     <option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false" />
     <option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
     <option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
     <option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
-    <MESSAGE value="Reformat and updated Example 12.1." />
     <MESSAGE value="Example 12.1 completely ported and fully working." />
     <MESSAGE value="Setup Example 12.2." />
     <MESSAGE value="Workspace.xml being weird." />
     <MESSAGE value="Updated README." />
     <MESSAGE value="Forgot to remove the call to setFPS(0) in Example 15.1." />
     <MESSAGE value="Fully ported Example 16.1." />
+    <MESSAGE value="Fully ported Example 16.1. Also moved the 'dds' classes to their original packaging for better credit to author." />
   </component>
   <component name="XDebuggerManager">
     <breakpoint-manager>
     <option name="FILTER_TARGETS" value="false" />
   </component>
   <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/GLProgram.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="186" column="4" selection-start="3703" selection-end="3703" vertical-scroll-proportion="0.65460527">
-          <folding />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter14/example3/Example14_3.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="43" column="13" selection-start="1729" selection-end="1729" vertical-scroll-proportion="0.08583691">
-          <folding />
-        </state>
+        <state line="43" column="13" selection-start="1729" selection-end="1729" vertical-scroll-proportion="0.08583691" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter13/example2/Example13_2.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="33" column="13" selection-start="1234" selection-end="1234" vertical-scroll-proportion="0.021428572">
-          <folding />
-        </state>
+        <state line="33" column="13" selection-start="1234" selection-end="1234" vertical-scroll-proportion="0.021428572" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter12/example3/Example12_3.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="66" column="4" selection-start="2508" selection-end="2508" vertical-scroll-proportion="0.6440367">
-          <folding />
-        </state>
+        <state line="66" column="4" selection-start="2508" selection-end="2508" vertical-scroll-proportion="0.6440367" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/rosick/jglsdk/glimg/ImageCreator.java">
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter15/Example15_1.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="225" column="8" selection-start="7412" selection-end="7634" vertical-scroll-proportion="0.44407895">
-          <folding>
-            <element signature="imports" expanded="true" />
-          </folding>
-        </state>
+        <state line="225" column="8" selection-start="7412" selection-end="7634" vertical-scroll-proportion="0.44407895" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.TextureGamma.frag">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="0" selection-start="216" selection-end="216" vertical-scroll-proportion="0.23026316">
-          <folding />
-        </state>
+        <state line="14" column="0" selection-start="216" selection-end="216" vertical-scroll-proportion="0.23026316" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.TextureNoGamma.frag">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="12" column="0" selection-start="157" selection-end="157" vertical-scroll-proportion="0.19736843">
-          <folding />
-        </state>
+        <state line="12" column="0" selection-start="157" selection-end="157" vertical-scroll-proportion="0.19736843" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/util/math/Matrix4.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="13" column="4" selection-start="225" selection-end="225" vertical-scroll-proportion="0.16447368">
-          <folding />
-        </state>
+        <state line="13" column="4" selection-start="225" selection-end="225" vertical-scroll-proportion="0.16447368" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/Example16_1.java">
     </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.ScreenCoords.vert">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="19" column="0" selection-start="293" selection-end="293" vertical-scroll-proportion="0.4351145">
-          <folding />
-        </state>
+        <state line="19" column="0" selection-start="293" selection-end="293" vertical-scroll-proportion="0.4351145" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/src/rosick/jglsdk/glimg/TextureGenerator.java">
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.gamma_ramp.png">
+      <provider selected="true" editor-type-id="images">
+        <state />
+      </provider>
+    </entry>
   </component>
   <component name="masterDetails">
     <states>
Add a comment to this file

src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example1/example16.1.gamma_ramp.png

Added
New image

src/rosick/jglsdk/glimg/DdsLoader.java

+package rosick.jglsdk.glimg;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import rosick.jglsdk.glimg.ImageFormat.BitDepth;
+import rosick.jglsdk.glimg.ImageFormat.ComponentOrder;
+import rosick.jglsdk.glimg.ImageFormat.PixelComponents;
+import rosick.jglsdk.glimg.ImageFormat.PixelDataType;
+import rosick.jglsdk.glimg.ImageFormat.UncheckedImageFormat;
+import rosick.jglsdk.glimg.ImageSet.Dimensions;
+
+/**
+ * Visit https://github.com/integeruser/jglsdk for project info, updates and license terms.
+ * 
+ * @author integeruser
+ */
+public class DdsLoader {
+	public static ImageSet load(InputStream dds) throws IOException {
+		byte[] ddsFile = readDdsFile(dds);
+		
+		// Check the first 4 bytes.
+		int magicTest = readDoubleWord(ddsFile, 0);
+		if(magicTest != MagicNumbers.DDS_MAGIC_NUMBER) {
+			throw new DdsFileMalformedException("The Magic number is missing from the file.");
+		}
+		
+		if(ddsFile.length < DdsHeader.SIZE + 4) {
+			throw new DdsFileMalformedException("The data is way too small to store actual information.");
+		}
+		
+		// Collect info from the DDS file.
+		DdsHeader ddsHeader = new DdsHeader(ddsFile);
+		Dds10Header dds10Header = getDds10Header(ddsFile, ddsHeader);
+		Dimensions ddsDimensions = getDimensions(ddsHeader);
+		UncheckedImageFormat ddsFormat = getFormat(ddsHeader, dds10Header);
+		
+		// Get image counts.
+		int numArrays = (dds10Header.arraySize > 1) ? dds10Header.arraySize : 1;
+		int numFaces = (dds10Header.miscFlag & Dds10MiscFlags.RESOURCE_MISC_TEXTURECUBE) != 0 ? 6 : 1;
+		int numMipmaps = (ddsHeader.flags & DdsFlags.MIPMAPCOUNT) != 0 ? ddsHeader.mipmapCount : 1;
+		
+		int baseOffset = getOffsetToData(ddsHeader);
+		
+		// Build the image creator.
+		ImageCreator imageCreator = new ImageCreator(new ImageFormat(ddsFormat), ddsDimensions, numMipmaps, numArrays, numFaces);
+		int cumulativeOffset = baseOffset;
+		
+		for(int arrayIx = 0; arrayIx < numArrays; arrayIx++) {
+			for(int faceIx = 0; faceIx < numFaces; faceIx++) {
+				for(int mipmapLevel = 0; mipmapLevel < numMipmaps; mipmapLevel++) {
+					int mipmapLevelSize = calcMipmapSize(ddsFormat, ddsDimensions, mipmapLevel);
+					
+					// Get specific data from ddsFile.
+					byte[] mipmapLevelData = Arrays.copyOfRange(ddsFile, cumulativeOffset, cumulativeOffset + mipmapLevelSize);
+					
+					// Set data for the current mipmap level in imageCreator.
+					imageCreator.setImageData(mipmapLevelData, true, mipmapLevel, arrayIx, faceIx);
+					
+					// Advance offset to read next mipmapLevelData from ddsFile.
+					cumulativeOffset += mipmapLevelSize;
+				}
+			}
+		}
+		
+		return imageCreator.createImage();
+	}
+	
+	private static class DdsFileMalformedException extends RuntimeException {
+		private static final long serialVersionUID = -1523221969465221880L;
+		
+		private DdsFileMalformedException(String message) {
+			super(message);
+		}
+	}
+	
+	private static class DdsFileUnsupportedException extends RuntimeException {
+		private static final long serialVersionUID = 377383320427260974L;
+		
+		private DdsFileUnsupportedException(String filename, String message) {
+			super(filename + ": " + message);
+		}
+	}
+	
+	private static class MagicNumbers {
+		static final int DDS_MAGIC_NUMBER = 0x20534444; // "DDS "
+		static final int DDS10_FOUR_CC = 0x30314458; // "DX10"
+		
+		static final int DDSFOURCC_DXT1 = 0x31545844; // "DXT1"
+		static final int DDSFOURCC_DXT3 = 0x33545844; // "DXT3"
+		static final int DDSFOURCC_DXT5 = 0x35545844; // "DXT5"
+	}
+	
+	@SuppressWarnings("unused")
+	private static class DdsFlags {
+		static final int CAPS = 0x00000001;
+		static final int HEIGHT = 0x00000002;
+		static final int WIDTH = 0x00000004;
+		static final int PITCH = 0x00000008;
+		static final int PIXELFORMAT = 0x00001000;
+		static final int MIPMAPCOUNT = 0x00020000;
+		static final int LINEARSIZE = 0x00080000;
+		static final int DEPTH = 0x00800000;
+		
+	}
+	
+	private static class Dds10MiscFlags {
+		static final int RESOURCE_MISC_TEXTURECUBE = 0x00000004;
+	}
+	
+	@SuppressWarnings("unused")
+	private static class Dds10ResourceDimensions {
+		static final int TEXTURE1D = 2;
+		static final int TEXTURE2D = 3;
+		static final int TEXTURE3D = 4;
+	}
+	
+	private static class DdsCaps2 {
+		static final int CUBEMAP = 0x00000200;
+		static final int CUBEMAP_POSITIVEX = 0x00000400;
+		static final int CUBEMAP_NEGATIVEX = 0x00000800;
+		static final int CUBEMAP_POSITIVEY = 0x00001000;
+		static final int CUBEMAP_NEGATIVEY = 0x00002000;
+		static final int CUBEMAP_POSITIVEZ = 0x00004000;
+		static final int CUBEMAP_NEGATIVEZ = 0x00008000;
+		static final int VOLUME = 0x00200000;
+		
+		static final int CUBEMAP_ALL = CUBEMAP |
+				CUBEMAP_POSITIVEX | CUBEMAP_NEGATIVEX |
+				CUBEMAP_POSITIVEY | CUBEMAP_NEGATIVEY |
+				CUBEMAP_POSITIVEZ | CUBEMAP_NEGATIVEZ;
+	}
+	
+	private static class DxgiFormat {
+		static final int UNKNOWN = 0;
+	}
+	
+	@SuppressWarnings("unused")
+	private static class DdsPixelFormat {
+		int size;
+		int flags;
+		int fourCC;
+		int rgbBitCount;
+		int rBitMask;
+		int gBitMask;
+		int bBitMask;
+		int aBitMask;
+	}
+	
+	@SuppressWarnings("unused")
+	private static class DdsPixelFormatFlags {
+		static final int ALPHAPIXELS = 0x00000001;
+		static final int ALPHA = 0x00000002;
+		static final int FOURCC = 0x00000004;
+		static final int RGB = 0x00000040;
+		static final int YUV = 0x00000200;
+		static final int LUMINANCE = 0x00020000;
+	}
+	
+	@SuppressWarnings("unused")
+	private static class DdsHeader {
+		static final int SIZE = (7 + 11 + 8 + 5) * (Integer.SIZE / 8);
+		
+		int size;
+		int flags;
+		int height;
+		int width;
+		int pitchOrLinearSize;
+		int depth;
+		int mipmapCount;
+		
+		int reserved1[] = new int[11];
+		
+		DdsPixelFormat ddsPixelFormat;
+		
+		int caps;
+		int caps2;
+		int caps3;
+		int caps4;
+		int reserved2;
+		
+		DdsHeader(byte[] ddsFile) {
+			size = readDoubleWord(ddsFile, 4);
+			flags = readDoubleWord(ddsFile, 8);
+			height = readDoubleWord(ddsFile, 12);
+			width = readDoubleWord(ddsFile, 16);
+			pitchOrLinearSize = readDoubleWord(ddsFile, 20);
+			depth = readDoubleWord(ddsFile, 24);
+			mipmapCount = readDoubleWord(ddsFile, 28);
+			
+			for(int i = 0; i < reserved1.length; i++) {
+				reserved1[i] = readDoubleWord(ddsFile, 32 + 4 * i);
+			}
+			
+			ddsPixelFormat = new DdsPixelFormat();
+			ddsPixelFormat.size = readDoubleWord(ddsFile, 76);
+			ddsPixelFormat.flags = readDoubleWord(ddsFile, 80);
+			ddsPixelFormat.fourCC = readDoubleWord(ddsFile, 84);
+			ddsPixelFormat.rgbBitCount = readDoubleWord(ddsFile, 88);
+			ddsPixelFormat.rBitMask = readDoubleWord(ddsFile, 92);
+			ddsPixelFormat.gBitMask = readDoubleWord(ddsFile, 96);
+			ddsPixelFormat.bBitMask = readDoubleWord(ddsFile, 100);
+			ddsPixelFormat.aBitMask = readDoubleWord(ddsFile, 104);
+			
+			caps = readDoubleWord(ddsFile, 108);
+			caps2 = readDoubleWord(ddsFile, 112);
+			caps3 = readDoubleWord(ddsFile, 116);
+			caps4 = readDoubleWord(ddsFile, 120);
+			reserved2 = readDoubleWord(ddsFile, 124);
+		}
+	}
+	
+	@SuppressWarnings("unused")
+	private static class Dds10Header {
+		static final int SIZE = 5 * (Integer.SIZE / 8);
+		
+		int dxgiFormat;
+		int resourceDimension;
+		int miscFlag;
+		int arraySize;
+		int reserved;
+	}
+	
+	private static byte[] readDdsFile(InputStream ddsInStream) throws IOException {
+		assert ddsInStream != null;
+		
+		ByteArrayOutputStream ddsOutStream = new ByteArrayOutputStream();
+		int bytesRead;
+		
+		byte[] buffer = new byte[4096];
+		
+		while((bytesRead = ddsInStream.read(buffer)) != -1) {
+			ddsOutStream.write(buffer, 0, bytesRead);
+		}
+		
+		return ddsOutStream.toByteArray();
+	}
+	
+	// Read four bytes.
+	private static int readDoubleWord(byte bytes[], int startIx) {
+		int dw = 0;
+		
+		// Read 4 bytes.
+		for(int i = startIx; i < startIx + 4; i++) {
+			dw += (bytes[i] & 0xff) << (8 * (i - startIx));
+		}
+		
+		return dw;
+	}
+	
+	// Will either generate this or return the actual one.
+	private static Dds10Header getDds10Header(byte[] ddsFile, DdsHeader ddsHeader) {
+		if(ddsHeader.ddsPixelFormat.fourCC == MagicNumbers.DDS10_FOUR_CC) {
+			Dds10Header dds10Header = new Dds10Header();
+			int offsetToNewHeader = DdsHeader.SIZE + 4;
+			
+			dds10Header.dxgiFormat = readDoubleWord(ddsFile, offsetToNewHeader);
+			dds10Header.resourceDimension = readDoubleWord(ddsFile, offsetToNewHeader + 4);
+			dds10Header.miscFlag = readDoubleWord(ddsFile, offsetToNewHeader + 8);
+			dds10Header.arraySize = readDoubleWord(ddsFile, offsetToNewHeader + 12);
+			dds10Header.reserved = readDoubleWord(ddsFile, offsetToNewHeader + 16);
+			
+			return dds10Header;
+		}
+		
+		// Compute the header manually. Namely, compute the DXGI_FORMAT for the given data.
+		Dds10Header dds10header = new Dds10Header();
+		
+		// Get dimensionality. Assume 2D unless otherwise stated.
+		dds10header.resourceDimension = Dds10ResourceDimensions.TEXTURE2D;
+		
+		if((ddsHeader.caps2 & DdsCaps2.VOLUME) != 0 && (ddsHeader.flags & DdsFlags.DEPTH) != 0) {
+			dds10header.resourceDimension = Dds10ResourceDimensions.TEXTURE3D;
+		}
+		
+		// Get cubemap.
+		int cubemapTest = ddsHeader.caps2 & DdsCaps2.CUBEMAP_ALL;
+		if(cubemapTest == 0) {
+			dds10header.miscFlag = 0;
+		} else {
+			// All faces must be specified or none. Otherwise unsupported.
+			if(cubemapTest != DdsCaps2.CUBEMAP_ALL) {
+				throw new DdsFileUnsupportedException("", "All cubemap faces must be specified.");
+			}
+			
+			dds10header.miscFlag = Dds10MiscFlags.RESOURCE_MISC_TEXTURECUBE;
+		}
+		
+		// Array size is... zero?
+		dds10header.arraySize = 0;
+		
+		// Use the old-style format.
+		dds10header.dxgiFormat = DxgiFormat.UNKNOWN;
+		
+		return dds10header;
+	}
+	
+	private static Dimensions getDimensions(DdsHeader ddsHeader) {
+		Dimensions ddsDimensions = new Dimensions();
+		ddsDimensions.numDimensions = 1;
+		ddsDimensions.width = ddsHeader.width;
+		
+		if((ddsHeader.flags & DdsFlags.HEIGHT) != 0) {
+			ddsDimensions.numDimensions = 2;
+			ddsDimensions.height = ddsHeader.height;
+		}
+		
+		if((ddsHeader.flags & DdsFlags.DEPTH) != 0) {
+			ddsDimensions.numDimensions = 3;
+			ddsDimensions.depth = ddsHeader.depth;
+		}
+		
+		return ddsDimensions;
+	}
+	
+	private static UncheckedImageFormat getFormat(DdsHeader ddsHeader, Dds10Header dds10Header) throws DdsFileUnsupportedException {
+		if(dds10Header.dxgiFormat != DxgiFormat.UNKNOWN) {
+			throw new IllegalArgumentException("Format is not unknown.");
+		}
+		
+		for(OldDdsFormatConv o : s_oldFormatConvert)
+			if(doesMatchFormat(o.ddsFmt, ddsHeader))
+				return o.uncheckedImageFormat;
+		
+		throw new DdsFileUnsupportedException("", "Could not use the DDS9's image format.");
+	}
+	
+	private static int getOffsetToData(DdsHeader ddsHeader) {
+		int byteOffset = DdsHeader.SIZE + 4;
+		
+		if(ddsHeader.ddsPixelFormat.fourCC == MagicNumbers.DDS10_FOUR_CC) {
+			byteOffset += Dds10Header.SIZE;
+		}
+		
+		return byteOffset;
+	}
+	
+	// Computes the bytesize of a single scanline of an image of the given format, with the given line width.
+	// For compressed textures, the value returned is the number of bytes for every 4 scanlines.
+	private static int calcLineSize(UncheckedImageFormat ddsFormat, int lineWidth) {
+		// This is from the DDS suggestions for line size computations.
+		if(ddsFormat.bitDepth == BitDepth.COMPRESSED) {
+			int blockSize = 16;
+			
+			if(ddsFormat.type == PixelDataType.COMPRESSED_BC1
+					|| ddsFormat.type == PixelDataType.COMPRESSED_UNSIGNED_BC4
+					|| ddsFormat.type == PixelDataType.COMPRESSED_SIGNED_BC4) {
+				blockSize = 8;
+			}
+			
+			return ((lineWidth + 3) / 4) * blockSize;
+		} else {
+			int bytesPerPixel = DdsUtil.calcBytesPerPixel(new ImageFormat(ddsFormat));
+			
+			return lineWidth * bytesPerPixel;
+		}
+	}
+	
+	private static int calcMipmapSize(UncheckedImageFormat ddsFormat, Dimensions ddsDimensions, int mipmapLevel) {
+		Dimensions mipmapDimensions = DdsUtil.calcMipmapLevelDimensions(ddsDimensions, mipmapLevel);
+		int lineSize = calcLineSize(ddsFormat, mipmapDimensions.width);
+		
+		int effectiveHeight = 1;
+		if(mipmapDimensions.numDimensions > 1) {
+			effectiveHeight = mipmapDimensions.height;
+			
+			if(ddsFormat.bitDepth == BitDepth.COMPRESSED) {
+				effectiveHeight = (effectiveHeight + 3) / 4;
+			}
+		}
+		
+		int effectiveDepth = 1;
+		if(mipmapDimensions.numDimensions > 2) {
+			effectiveDepth = mipmapDimensions.depth;
+			
+			if(ddsFormat.bitDepth == BitDepth.COMPRESSED) {
+				effectiveDepth = (effectiveDepth + 3) / 4;
+			}
+		}
+		
+		int numLines = effectiveHeight * effectiveDepth;
+		
+		return lineSize * numLines;
+	}
+	
+	private static OldDdsFormatConv s_oldFormatConvert[] = {
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGBA, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB | DdsPixelFormatFlags.ALPHAPIXELS,
+					32, 0xff, 0xff00, 0xff0000, 0xff000000, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGBA, ComponentOrder.BGRA,
+					BitDepth.PACKED_32_BIT_8888_REV, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB | DdsPixelFormatFlags.ALPHAPIXELS,
+					32, 0xff0000, 0xff00, 0xff, 0xff000000, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGBX, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 32, 0xff, 0xff00, 0xff0000, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGB, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 24, 0xff, 0xff00, 0xff0000, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGB, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 24, 0xff, 0xff00, 0xff0000, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGB, ComponentOrder.BGRA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 24, 0xff0000, 0xff00, 0xff, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGB, ComponentOrder.RGBA,
+					BitDepth.PACKED_16_BIT_565, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 16, 0xf800, 0x7e0, 0x1f, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGBA, ComponentOrder.BGRA,
+					BitDepth.PACKED_16_BIT_1555_REV, 1),
+					new OldDdsFmtMatch(DdsPixelFormatFlags.RGB, 16, 0x7c00,
+							0x3e0, 0x1f, 0x8000, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RGBA, ComponentOrder.BGRA,
+					BitDepth.PACKED_16_BIT_4444_REV, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 16, 0xf00, 0xf0, 0xf, 0xf000, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.COMPRESSED_BC1, PixelComponents.COLOR_RGB,
+					ComponentOrder.COMPRESSED, BitDepth.COMPRESSED, 1),
+					new OldDdsFmtMatch(DdsPixelFormatFlags.FOURCC, 0, 0, 0, 0,
+							0, MagicNumbers.DDSFOURCC_DXT1)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.COMPRESSED_BC2, PixelComponents.COLOR_RGBA,
+					ComponentOrder.COMPRESSED, BitDepth.COMPRESSED, 1),
+					new OldDdsFmtMatch(DdsPixelFormatFlags.FOURCC, 0, 0, 0, 0,
+							0, MagicNumbers.DDSFOURCC_DXT3)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.COMPRESSED_BC3, PixelComponents.COLOR_RGBA,
+					ComponentOrder.COMPRESSED, BitDepth.COMPRESSED, 1),
+					new OldDdsFmtMatch(DdsPixelFormatFlags.FOURCC, 0, 0, 0, 0,
+							0, MagicNumbers.DDSFOURCC_DXT5)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RG, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_16, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 32, 0xffff, 0xffff0000, 0, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RG, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.RGB, 16, 0xffff, 0xffff0000, 0, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RED, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_16, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.LUMINANCE, 16, 0xffff, 0, 0, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RED, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.LUMINANCE, 8, 0xff, 0, 0, 0, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RG, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_16, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.LUMINANCE
+							| DdsPixelFormatFlags.ALPHAPIXELS, 16, 0xffff, 0,
+					0, 0xffff0000, 0)),
+			
+			new OldDdsFormatConv(new UncheckedImageFormat(
+					PixelDataType.NORM_UNSIGNED_INTEGER,
+					PixelComponents.COLOR_RG, ComponentOrder.RGBA,
+					BitDepth.PER_COMP_8, 1), new OldDdsFmtMatch(
+					DdsPixelFormatFlags.LUMINANCE
+							| DdsPixelFormatFlags.ALPHAPIXELS, 8, 0xff, 0, 0,
+					0xff00, 0)), };
+	
+	private static class OldDdsFmtMatch {
+		int flags;
+		int bitDepth;
+		int rBitmask;
+		int gBitmask;
+		int bBitmask;
+		int aBitmask;
+		int fourCC;
+		
+		OldDdsFmtMatch(int flags, int bitDepth, int rBitmask, int gBitmask,
+				int bBitmask, int aBitmask, int fourCC) {
+			this.flags = flags;
+			this.bitDepth = bitDepth;
+			this.rBitmask = rBitmask;
+			this.gBitmask = gBitmask;
+			this.bBitmask = bBitmask;
+			this.aBitmask = aBitmask;
+			this.fourCC = fourCC;
+		}
+	}
+	
+	private static class OldDdsFormatConv {
+		UncheckedImageFormat uncheckedImageFormat;
+		OldDdsFmtMatch ddsFmt;
+		
+		OldDdsFormatConv(UncheckedImageFormat uncheckedImageFormat, OldDdsFmtMatch ddsFmt) {
+			this.uncheckedImageFormat = uncheckedImageFormat;
+			this.ddsFmt = ddsFmt;
+		}
+	}
+	
+	private static boolean doesMatchFormat(OldDdsFmtMatch ddsFmt, DdsHeader ddsHeader) {
+		if((ddsHeader.ddsPixelFormat.flags & ddsFmt.flags) == 0) {
+			return false;
+		}
+		
+		if((ddsFmt.flags & DdsPixelFormatFlags.FOURCC) != 0) {
+			// None of the bit counts matter. Just check the fourCC
+			if(ddsFmt.fourCC != ddsHeader.ddsPixelFormat.fourCC) {
+				return false;
+			}
+		} else {
+			// Check the bitcounts, not the fourCC.
+			if(ddsHeader.ddsPixelFormat.rgbBitCount != ddsFmt.bitDepth) {
+				return false;
+			}
+			
+			if((ddsFmt.rBitmask & ddsHeader.ddsPixelFormat.rBitMask) != ddsFmt.rBitmask) {
+				return false;
+			}
+			
+			if((ddsFmt.gBitmask & ddsHeader.ddsPixelFormat.gBitMask) != ddsFmt.gBitmask) {
+				return false;
+			}
+			
+			if((ddsFmt.bBitmask & ddsHeader.ddsPixelFormat.bBitMask) != ddsFmt.bBitmask) {
+				return false;
+			}
+			
+			if((ddsFmt.aBitmask & ddsHeader.ddsPixelFormat.aBitMask) != ddsFmt.aBitmask) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+}

src/rosick/jglsdk/glimg/DdsUtil.java

+package rosick.jglsdk.glimg;
+
+import rosick.jglsdk.glimg.ImageFormat.BitDepth;
+import rosick.jglsdk.glimg.ImageFormat.PixelComponents;
+import rosick.jglsdk.glimg.ImageFormat.PixelDataType;
+import rosick.jglsdk.glimg.ImageSet.Dimensions;
+
+/**
+ * Visit https://github.com/integeruser/jglsdk for project info, updates and license terms.
+ * 
+ * @author integeruser
+ */
+class DdsUtil {
+	
+	static <T> boolean isOneOfThese(T testValue, T[] testArray) {
+		for(T arrayElement : testArray) {
+			if(arrayElement.equals(testValue)) {
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	static Dimensions calcMipmapLevelDimensions(Dimensions ddsDimensions, int mipmapLevel) {
+		Dimensions mipmapLevelDimensions = new Dimensions(ddsDimensions);
+		
+		for(int i = 0; i < mipmapLevel; i++) {
+			mipmapLevelDimensions.width /= 2;
+			mipmapLevelDimensions.height /= 2;
+			mipmapLevelDimensions.depth /= 2;
+		}
+		
+		return mipmapLevelDimensions;
+	}
+	
+	static int calcBytesPerPixel(ImageFormat format) {
+		int bytesPerPixel = 0;
+		
+		switch(format.getBitDepth()) {
+			case COMPRESSED:
+				return 0;
+			case PER_COMP_8:
+				bytesPerPixel = 1;
+				break;
+			case PER_COMP_16:
+				bytesPerPixel = 2;
+				break;
+			case PER_COMP_32:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_16_BIT_565:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_16_BIT_5551:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_16_BIT_4444:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_32_BIT_8888:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_32_BIT_1010102:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_32_BIT_248:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_16_BIT_565_REV:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_16_BIT_1555_REV:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_16_BIT_4444_REV:
+				bytesPerPixel = 2;
+				break;
+			case PACKED_32_BIT_8888_REV:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_32_BIT_2101010_REV:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_32_BIT_101111_REV:
+				bytesPerPixel = 4;
+				break;
+			case PACKED_32_BIT_5999_REV:
+				bytesPerPixel = 4;
+				break;
+			default:
+				break;
+		}
+		
+		if(format.getBitDepth().ordinal() < BitDepth.NUM_PER_COMPONENT.ordinal()) {
+			bytesPerPixel *= calcComponentCount(format.getPixelComponents());
+		}
+		
+		return bytesPerPixel;
+	}
+	
+	static int calcComponentCount(PixelComponents component) {
+		PixelComponents[] twoCompFormats = { PixelComponents.COLOR_RG, PixelComponents.DEPTH_X };
+		PixelComponents[] threeCompFormats = { PixelComponents.COLOR_RGB, PixelComponents.COLOR_RGB_SRGB };
+		PixelComponents[] fourCompFormats = { PixelComponents.COLOR_RGBX, PixelComponents.COLOR_RGBA,
+				PixelComponents.COLOR_RGBX_SRGB, PixelComponents.COLOR_RGBA_SRGB };
+		
+		if(isOneOfThese(component, twoCompFormats)) {
+			return 2;
+		}
+		
+		if(isOneOfThese(component, threeCompFormats)) {
+			return 3;
+		}
+		
+		if(isOneOfThese(component, fourCompFormats)) {
+			return 4;
+		}
+		
+		return 1;
+	}
+	
+	static class CompressedBlockData {
+		Dimensions dimensions;
+		int byteCount;
+	}
+	
+	static CompressedBlockData getBlockCompressionData(PixelDataType pixelDataType) {
+		assert pixelDataType.ordinal() >= PixelDataType.NUM_UNCOMPRESSED_TYPES.ordinal();
+		
+		CompressedBlockData blockData = new CompressedBlockData();
+		blockData.dimensions = new Dimensions();
+		blockData.dimensions.numDimensions = 2;
+		blockData.dimensions.width = 4;
+		blockData.dimensions.height = 4;
+		
+		switch(pixelDataType) {
+			case COMPRESSED_BC1:
+			case COMPRESSED_UNSIGNED_BC4:
+			case COMPRESSED_SIGNED_BC4:
+				blockData.byteCount = 8;
+				break;
+			
+			default:
+				blockData.byteCount = 16;
+				break;
+		}
+		
+		return blockData;
+	}
+	
+	static int calcMipmapLevelSize(ImageFormat imageFormat, Dimensions mipmapLevelDimensions) {
+		if(imageFormat.getPixelDataType().ordinal() >= PixelDataType.NUM_UNCOMPRESSED_TYPES.ordinal()) {
+			
+			if(mipmapLevelDimensions.numDimensions == 3)
+				throw new IllegalArgumentException("No support for 3D compressed formats.");
+			
+			CompressedBlockData blockData = getBlockCompressionData(imageFormat.getPixelDataType());
+			int width = (mipmapLevelDimensions.width + (blockData.dimensions.width - 1)) / blockData.dimensions.width;
+			int height;
+			
+			if(mipmapLevelDimensions.numDimensions > 1) {
+				height = (mipmapLevelDimensions.height + (blockData.dimensions.height - 1)) / blockData.dimensions.height;
+			} else {
+				if(blockData.dimensions.numDimensions < 2)
+					throw new IllegalArgumentException("numDimensions must be greater than 2");
+				
+				height = blockData.dimensions.height;
+			}
+			
+			return width * height * blockData.byteCount;
+		} else {
+			int bytesPerPixel = calcBytesPerPixel(imageFormat);
+			int lineSize = imageFormat.alignByteCount(bytesPerPixel * mipmapLevelDimensions.width);
+			
+			if(mipmapLevelDimensions.numDimensions > 1) {
+				lineSize *= mipmapLevelDimensions.height;
+			}
+			
+			if(mipmapLevelDimensions.numDimensions == 3) {
+				lineSize *= mipmapLevelDimensions.depth;
+			}
+			
+			return lineSize;
+		}
+	}
+	
+	static void throwNotYetPortedException() {
+		throw new IllegalArgumentException("Feature not supported.");
+	}
+}

src/rosick/jglsdk/glimg/ImageCreator.java

+package rosick.jglsdk.glimg;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import rosick.jglsdk.glimg.DdsUtil.CompressedBlockData;
+import rosick.jglsdk.glimg.ImageFormat.PixelDataType;
+import rosick.jglsdk.glimg.ImageSet.Dimensions;
+
+/**
+ * Visit https://github.com/integeruser/jglsdk for project info, updates and license terms.
+ * 
+ * @author integeruser
+ */
+class ImageCreator {
+	
+	ImageCreator(ImageFormat ddsFormat, Dimensions ddsDimensions, int mipmapCount, int arrayCount, int faceCount) {
+		m_imageFormat = ddsFormat;
+		m_imageDimensions = new Dimensions(ddsDimensions);
+		
+		m_mipmapCount = mipmapCount;
+		m_arrayCount = arrayCount;
+		m_faceCount = faceCount;
+		
+		if(faceCount != 6 && faceCount != 1) {
+			throw new BadFaceCountException();
+		}
+		
+		if(faceCount == 6 && ddsDimensions.numDimensions != 2) {
+			throw new CubemapsMustBe2DException();
+		}
+		
+		if(ddsDimensions.numDimensions == 3 && arrayCount != 1) {
+			throw new No3DTextureArrayException();
+		}
+		
+		if(mipmapCount <= 0 || arrayCount <= 0) {
+			throw new NoImagesSpecifiedException();
+		}
+		
+		m_imageData = new ArrayList<>(mipmapCount);
+		m_imageSizes = new int[mipmapCount];
+		
+		// Allocate the memory for our data.
+		for(int mipmapLevel = 0; mipmapLevel < mipmapCount; mipmapLevel++) {
+			Dimensions mipmapLevelDimensions = DdsUtil.calcMipmapLevelDimensions(ddsDimensions, mipmapLevel);
+			
+			int mipmapLevelSize = DdsUtil.calcMipmapLevelSize(ddsFormat, mipmapLevelDimensions);
+			m_imageSizes[mipmapLevel] = mipmapLevelSize;
+			
+			byte[] mipmapLevelData = new byte[mipmapLevelSize * faceCount * arrayCount];
+			m_imageData.add(mipmapLevelData);
+		}
+	}
+	
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 */
+	
+	void setImageData(byte sourceData[], boolean isTopLeft, int mipmapLevel, int arrayIx, int faceIx) {
+		if(m_imageData.isEmpty()) {
+			throw new ImageSetAlreadyCreatedException();
+		}
+		
+		// Check inputs.
+		if((arrayIx < 0) || (m_arrayCount <= arrayIx)) {
+			throw new ArrayIndexOutOfBoundsException();
+		}
+		
+		if((faceIx < 0) || (m_faceCount <= faceIx)) {
+			throw new FaceIndexOutOfBoundsException();
+		}
+		
+		if((mipmapLevel < 0) || (m_mipmapCount <= mipmapLevel)) {
+			throw new MipmapLayerOutOfBoundsException();
+		}
+		
+		// Get the image relative to mipmapLevel
+		byte[] imageData = m_imageData.get(mipmapLevel);
+		
+		if(!isTopLeft) {
+			DdsUtil.throwNotYetPortedException();
+		} else {
+			int imageDataOffset = ((arrayIx * m_faceCount) + faceIx) * m_imageSizes[mipmapLevel];
+			copyImageFlipped(sourceData, imageData, imageDataOffset, mipmapLevel);
+		}
+	}
+	
+	ImageSet createImage() {
+		if(m_imageData.isEmpty()) {
+			throw new ImageSetAlreadyCreatedException();
+		}
+		
+		return new ImageSet(m_imageFormat, m_imageDimensions,
+				m_mipmapCount, m_arrayCount, m_faceCount,
+				m_imageData, m_imageSizes);
+	}
+	
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 */
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 */
+	
+	private ImageFormat m_imageFormat;
+	private Dimensions m_imageDimensions;
+	
+	private int m_mipmapCount;
+	private int m_arrayCount;
+	private int m_faceCount;
+	
+	private ArrayList<byte[]> m_imageData;
+	private int[] m_imageSizes;
+	
+	private static class BadFaceCountException extends RuntimeException {
+		private static final long serialVersionUID = -4120563516856357626L;
+	}
+	
+	private static class CubemapsMustBe2DException extends RuntimeException {
+		private static final long serialVersionUID = 4034128602806705190L;
+	}
+	
+	private static class No3DTextureArrayException extends RuntimeException {
+		private static final long serialVersionUID = -9001483779340494905L;
+	}
+	
+	private static class NoImagesSpecifiedException extends RuntimeException {
+		private static final long serialVersionUID = 3390815114957601365L;
+	}
+	
+	private static class ImageSetAlreadyCreatedException extends RuntimeException {
+		private static final long serialVersionUID = -7707381545866051896L;
+	}
+	
+	private static class MipmapLayerOutOfBoundsException extends RuntimeException {
+		private static final long serialVersionUID = 5160364349781356398L;
+	}
+	
+	private static class FaceIndexOutOfBoundsException extends RuntimeException {
+		private static final long serialVersionUID = 5885166000035279615L;
+	}
+	
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 */
+	
+	private void copyImageFlipped(byte[] sourceData, byte[] imageData, int imageDataOffset, int mipmapLevel) {
+		assert (sourceData.length * m_faceCount * m_arrayCount) == imageData.length;
+		
+		Dimensions mipmapImageDimensions = DdsUtil.calcMipmapLevelDimensions(new Dimensions(m_imageDimensions), mipmapLevel);
+		
+		if(m_imageFormat.getPixelDataType().ordinal() < PixelDataType.NUM_UNCOMPRESSED_TYPES.ordinal()) {
+			copyPixelsFlipped(m_imageFormat,
+					sourceData, imageData, imageDataOffset,
+					m_imageSizes[mipmapLevel], mipmapImageDimensions);
+		} else {
+			// Have to decode the pixel data and flip it manually.
+			switch(m_imageFormat.getPixelDataType()) {
+				case COMPRESSED_BC1:
+				case COMPRESSED_BC2:
+				case COMPRESSED_BC3:
+				case COMPRESSED_UNSIGNED_BC4:
+				case COMPRESSED_SIGNED_BC4:
+				case COMPRESSED_UNSIGNED_BC5:
+				case COMPRESSED_SIGNED_BC5:
+					copyBCFlipped(m_imageFormat,
+							sourceData, imageData, imageDataOffset,
+							m_imageSizes[mipmapLevel], mipmapImageDimensions);
+					break;
+				
+				default:
+					DdsUtil.throwNotYetPortedException();
+			}
+		}
+	}
+	
+	private void copyPixelsFlipped(ImageFormat imageFormat,
+			byte[] sourceData, byte[] imageData, int imageDataOffset,
+			int imageSize, Dimensions imageDimensions) {
+		// Flip the data. Copy line by line.
+		final int numLines = imageDimensions.calcNumLines();
+		final int lineSize = imageFormat.alignByteCount(DdsUtil.calcBytesPerPixel(imageFormat) * imageDimensions.width);
+		
+		// Flipped: start from last line of source, going backward
+		int sourceLineOffset = imageSize - lineSize; // start from last line
+		int imageDataLineOffset = imageDataOffset; // start from imageDataOffset
+		
+		for(int line = 0; line < numLines; line++) {
+			byte[] sourceLine = Arrays.copyOfRange(sourceData, sourceLineOffset, sourceLineOffset + lineSize);
+			
+			// Copy the source line into imageData
+			System.arraycopy(sourceLine, 0, imageData, imageDataLineOffset, lineSize);
+			
+			// Update indices
+			sourceLineOffset -= lineSize;
+			imageDataLineOffset += lineSize;
+		}
+	}
+	
+	private void copyBCFlipped(ImageFormat imageFormat,
+			byte[] sourceData, byte[] imageData, int imageDataOffset,
+			int imageSize, Dimensions imageDimensions) {
+		// No support for 3D compressed formats.
+		assert imageDimensions.numDimensions != 3 : "No support for 3D compressed formats.";
+		
+		CompressedBlockData blockData = DdsUtil.getBlockCompressionData(imageFormat.getPixelDataType());
+		final int blocksPerLine = (imageDimensions.width + (blockData.dimensions.width - 1)) / blockData.dimensions.width;
+		
+		final int blockLineSize = blocksPerLine * blockData.byteCount;
+		final int numTotalBlocks = imageSize / blockData.byteCount;
+		final int numLines = numTotalBlocks / blocksPerLine;
+		
+		// Copy each block.
+		int sourceBlockOffset = imageSize - blockLineSize; // start from last block
+		int imageDataBlockOffset = imageDataOffset; // start from imageDataOffset
+		
+		for(int line = 0; line < numLines; ++line) {
+			for(int block = 0; block < blocksPerLine; ++block) {
+				byte[] sourceBlock = Arrays.copyOfRange(sourceData, sourceBlockOffset, sourceBlockOffset + blockData.byteCount);
+				
+				flippingFunc(imageFormat, sourceBlock, imageData, imageDataBlockOffset);
+				
+				sourceBlockOffset += blockData.byteCount;
+				imageDataBlockOffset += blockData.byteCount;
+			}
+			
+			// First goes back to beginning, second goes back one row.
+			sourceBlockOffset -= blockLineSize;
+			sourceBlockOffset -= blockLineSize;
+		}
+	}
+	
+	private void flippingFunc(ImageFormat imageFormat, byte[] sourceData, byte[] imageData, int imageDataOffset) {
+		switch(imageFormat.getPixelDataType()) {
+			case COMPRESSED_BC1:
+				copyBlockBC1Flipped(sourceData, imageData, imageDataOffset);
+				break;
+			
+			default:
+				DdsUtil.throwNotYetPortedException();
+		}
+	}
+	
+	private void copyBlockBC1Flipped(byte[] sourceData, byte[] imageData, int imageDataOffset) {
+		assert sourceData.length == 8;
+		
+		System.arraycopy(sourceData, 0, imageData, imageDataOffset, 4);
+		
+		// Next four bytes are 16 2-bit values, in row-major, top-to-bottom order,
+		// representing the 4x4 pixel data for the block. So copy the bytes in reverse order.
+		imageData[imageDataOffset + 4] = sourceData[7];
+		imageData[imageDataOffset + 5] = sourceData[6];
+		imageData[imageDataOffset + 6] = sourceData[5];
+		imageData[imageDataOffset + 7] = sourceData[4];
+	}
+}

src/rosick/jglsdk/glimg/ImageFormat.java

+package rosick.jglsdk.glimg;
+
+/**
+ * Visit https://github.com/integeruser/jglsdk for project info, updates and license terms.
+ * 
+ * @author integeruser
+ */
+class ImageFormat {
+	enum PixelDataType {
+		NORM_UNSIGNED_INTEGER, // Image data are unsigned integers that are mapped to floats on the range [0, 1].
+		NORM_SIGNED_INTEGER, // Image data are signed integers that are mapped to floats on the range [-1, 1].
+		UNSIGNED_INTEGRAL, // Image data are unsigned integers.
+		SIGNED_INTEGRAL, // Image data are signed integers.
+		FLOAT, // Image data are individual floating-point numbers.
+		SHARED_EXP_FLOAT, // Image data are floats, but each pixel uses the same exponent.
+		NUM_UNCOMPRESSED_TYPES,
+		
+		COMPRESSED_BC1, // Image data is compressed with DXT1/BC1 compression. Unsigned normalized integers.
+		COMPRESSED_BC2, // Image data is compressed with DXT3/BC2 compression. Unsigned normalized integers.
+		COMPRESSED_BC3, // Image data is compressed with DXT5/BC3 compression. Unsigned normalized integers.
+		COMPRESSED_UNSIGNED_BC4, // Image is compressed with BC4 compression (1-component), with unsigned normalized integers.
+		COMPRESSED_SIGNED_BC4, // Image is compressed with BC4 compression (1-component), with signed normalized integers.
+		COMPRESSED_UNSIGNED_BC5, // Image is compressed with BC5 compression (2-component), with unsigned normalized integers.
+		COMPRESSED_SIGNED_BC5, // Image is compressed with BC5 compression (2-component), with signed normalized integers.
+		COMPRESSED_UNSIGNED_BC6H, // Image is compressed with BC6H compression, with unsigned floats [0, +inf).
+		COMPRESSED_SIGNED_BC6H, // Image is compressed with BC6H compression, with floats.
+		COMPRESSED_BC7, // Image data is compressed with BC7 compression. Unsigned normalized integers.
+		
+		NUM_TYPES
+	}
+	
+	enum PixelComponents {
+		COLOR_RED, // Image contains 1 color component, namely red.
+		COLOR_RG, // Image contains 2 color components, red and green.
+		COLOR_RGB, // Image contains 3 color components, red, green, and blue.
+		COLOR_RGBX, // Image contains 3 color components, red, green, and blue. There is a fourth component, which takes up space in the data but should be discarded.
+		COLOR_RGBA, // Image contains 4 color components, red, green, blue, and alpha.
+		COLOR_RGB_SRGB, // Image contains 3 color components, which are in the sRGB colorspace.
+		COLOR_RGBX_SRGB, // Image contains 3 color components, which are in the sRGB colorspace. There is a fourth component, which takes up space in the data but should be discarded.
+		COLOR_RGBA_SRGB, // Image contains 4 color components; the RGB components are in the sRGB colorspace.
+		
+		DEPTH, // Image contains a single depth component.
+		DEPTH_X, // Image contains a depth value (unsigned normalized integer) and a second component, who's value is discarded/irrelevant.
+		
+		NUM_FORMATS
+	}
+	
+	enum ComponentOrder {
+		RGBA, // Standard RGBA ordering.
+		BGRA, // Often used in conjunction with _REV Bitdepths.
+		RGBE, // For PixelDataType.DT_SHARED_EXP_FLOAT types. The E is the exponent, and it comes first.
+		
+		DEPTH_STENCIL, // Ordering for depth and depth-stencil image formats.
+		
+		COMPRESSED, // The order is built into the compressed data format.
+		
+		NUM_ORDERS
+	}
+	
+	enum BitDepth {
+		COMPRESSED, // Used for compressed data types. They do not have a bitdepth.
+		
+		PER_COMP_8, // Each component takes up 8 bits.
+		PER_COMP_16, // Each component takes up 16 bits.
+		PER_COMP_32, // Each component takes up 32 bits.
+		NUM_PER_COMPONENT,
+		
+		PACKED_16_BIT_565, // The first and third components take up 5 bits, while the second takes up 6.
+		PACKED_16_BIT_5551, // The first three components take up 5 bits, and the last takes up 1.
+		PACKED_16_BIT_4444, // Each component takes up 4 bits.
+		
+		PACKED_32_BIT_8888, // Each component takes up 8 bits.
+		PACKED_32_BIT_1010102, // The first three components take up 10 bits, and the last takes up 2.
+		PACKED_32_BIT_248, // The first component takes up 24 bits; the second takes up 8 bits.
+		
+		PACKED_16_BIT_565_REV, // Reverse order. The first and third components take up 5 bits, while the second takes up 6.
+		PACKED_16_BIT_1555_REV, // Reverse order. The first three components take up 5 bits, and the last takes up 1.
+		PACKED_16_BIT_4444_REV, // Reverse order. Each component takes up 4 bits.
+		
+		PACKED_32_BIT_8888_REV, // Reverse order. Each component takes up 8 bits.
+		PACKED_32_BIT_2101010_REV, // Reverse order. The first three components take up 10 bits, and the last takes up 2.
+		PACKED_32_BIT_101111_REV, // Reverse order. The first two components take 11 bits, and the third takes 10. Used for PixelDataType.DT_FLOAT types.
+		PACKED_32_BIT_5999_REV, // Reverse order. The first 3 components take 9 bits, and the last takes 5. Used for PixelDataType.DT_SHARED_EXP_FLOAT types.
+		
+		NUM_BITDEPTH
+	}
+	
+	static class UncheckedImageFormat {
+		PixelDataType type; // The type of pixel data.
+		PixelComponents format; // The components stored by a pixel.
+		ComponentOrder order; // The order of the components of the pixel.
+		BitDepth bitDepth; // The bitdepth of each pixel component.
+		int lineAlignment; // The byte alignment of a horizontal line of pixel data.
+		
+		UncheckedImageFormat() {}
+		
+		UncheckedImageFormat(PixelDataType type, PixelComponents format,
+				ComponentOrder order, BitDepth bitdepth, int lineAlignment) {
+			this.type = type;
+			this.format = format;
+			this.order = order;
+			this.bitDepth = bitdepth;
+			this.lineAlignment = lineAlignment;
+		}
+		
+		private String validateFormatText() {
+			// Alignment only matters for uncompressed types.
+			if(type.ordinal() < PixelDataType.NUM_UNCOMPRESSED_TYPES.ordinal()) {
+				Integer[] tests = { 1, 2, 4, 8 };
+				
+				if(!DdsUtil.isOneOfThese(lineAlignment, tests)) {
+					return "Alignment must be 1, 2, 4, or 8 bytes.";
+				}
+				
+				if(order == ComponentOrder.COMPRESSED) {
+					return "ComponentOrder.COMPRESSED can only be used with compressed types.";
+				}
+				
+				if(bitDepth == BitDepth.COMPRESSED) {
+					return "BitDepth.COMPRESSED can only be used with compressed types.";
+				}
+			}
+			else {
+				if(order != ComponentOrder.COMPRESSED) {
+					return "Compressed types must use ComponentOrder.COMPRESSED ordering.";
+				}
+				
+				if(bitDepth != BitDepth.COMPRESSED) {
+					return "Compressed types must use BitDepth.COMPRESSED bitdepth.";
+				}
+				
+				// Test the compressed formats with the colors.
+				if(type == PixelDataType.COMPRESSED_BC2
+						|| type == PixelDataType.COMPRESSED_BC3
+						|| type == PixelDataType.COMPRESSED_BC7)
+				{
+					if(!DdsUtil.isOneOfThese(format, s_alphaFormats)) {
+						return "BC2, 3, and 7 compression must use an RGBA format.";
+					}
+				}
+				else if(type == PixelDataType.COMPRESSED_BC1) {
+					if(!DdsUtil.isOneOfThese(format, s_rgbFormats) &&
+							!DdsUtil.isOneOfThese(format, s_alphaFormats))
+					{
+						return "BC1 compression must use an RGB or RGBA format";
+					}
+				}
+				
+				if(type == PixelDataType.COMPRESSED_UNSIGNED_BC4
+						|| type == PixelDataType.COMPRESSED_SIGNED_BC4)
+				{
+					if(format != PixelComponents.COLOR_RED) {
+						return "BC4 compression must use the RED format.";
+					}
+				}
+				
+				if(type == PixelDataType.COMPRESSED_UNSIGNED_BC5
+						|| type == PixelDataType.COMPRESSED_SIGNED_BC5)
+				{
+					if(format != PixelComponents.COLOR_RG) {
+						return "BC5 compression must use the RG format.";
+					}
+				}
+				
+				if(type == PixelDataType.COMPRESSED_UNSIGNED_BC6H
+						|| type == PixelDataType.COMPRESSED_SIGNED_BC6H)
+				{
+					if(format != PixelComponents.COLOR_RGB) {
+						return "BC6H compression must use the RGB format.";
+					}
+				}
+				
+				// End of compressed stuff.
+				return "";
+			}
+			
+			// Check for shared float. It has only one legal arrangement of forms.
+			{
+				boolean sharedExp = (type == PixelDataType.SHARED_EXP_FLOAT);
+				boolean sharedOrder = (order == ComponentOrder.RGBE);
+				boolean sharedDepth = (bitDepth == BitDepth.PACKED_32_BIT_5999_REV);
+				
+				if(sharedExp != sharedOrder || sharedOrder != sharedDepth) {
+					return "Shared floats must use PixelDataType.SHARED_EXP_FLOAT type, " +
+							"ComponentOrder.RGBE order, and BitDepth.PACKED_32_BIT_5999_REV bitdepth.";
+				}
+				
+				if(sharedExp && (format != PixelComponents.COLOR_RGB)) {
+					return "Shared floats must use RGB format.";
+				}
+				
+				// Shared exponent only comes in one form.
+				if(sharedExp) {
+					return "";
+				}
+			}
+			
+			// Check depth.
+			if(format == PixelComponents.DEPTH || format == PixelComponents.DEPTH_X) {
+				if(order != ComponentOrder.DEPTH_STENCIL) {
+					return "Depth formats must use ComponentOrder.DEPTH_STENCIL ordering.";
+				}
+				
+				// Depth can be either 16-bit normalized, 32-bit float, or 24x8 normalized.
+				if(type == PixelDataType.NORM_UNSIGNED_INTEGER) {
+					if(format == PixelComponents.DEPTH) {
+						if(bitDepth != BitDepth.PER_COMP_16) {
+							return "PixelComponents.DEPTH format with unsigned normalized integers must use BitDepth.PER_COMP_16";
+						}
+					}
+					else {
+						if(bitDepth != BitDepth.PACKED_32_BIT_248) {
+							return "PixelComponents.DEPTH_X format with unsigned normalized integers must use BitDepth.PACKED_32_BIT_248";
+						}
+					}
+				}
+				else if(type == PixelDataType.FLOAT) {
+					// Must be 32-bit float.
+					if(bitDepth != BitDepth.PER_COMP_32) {
+						return "PixelDataType.FLOAT types with depth formats must use BitDepth.PER_COMP_32 bitdepth";
+					}
+				}
+				else {
+					// Must be either normalized unsigned or float.
+					return "Depth formats must use either unsigned normalized or floating point types.";
+				}
+				
+				// Short circuit. We've tested all possibilities for depth formats.
+				return "";
+			}
+			
+			// We would not be here if the format contained depth, and this can only use depth.
+			if(bitDepth == BitDepth.PACKED_32_BIT_248) {
+				return "BitDepth.PACKED_32_BIT_248 can only be used with a depth format.";
+			}
+			
+			// Floats must be at least 16-bits per component, or 101111.
+			if(type == PixelDataType.FLOAT) {
+				if(!DdsUtil.isOneOfThese(bitDepth, s_floatBitdepths)) {
+					return "Floating-point types must use 16 or 32-bit bitdepths, or the Bitdepth.PACKED_32_BIT_101111_REV";
+				}
+			}
+			
+			// Only normalized unsigned integers can be sRGB.
+			if(DdsUtil.isOneOfThese(format, s_srgbFormats)) {
+				if(type != PixelDataType.NORM_UNSIGNED_INTEGER) {
+					return "Only normalized, unsigned integers can be in the sRGB colorspace.";
+				}
+			}
+			
+			// If 101111, then must be BGR, and must be float.
+			if(bitDepth == BitDepth.PACKED_32_BIT_101111_REV) {
+				if(!(type == PixelDataType.FLOAT && order == ComponentOrder.RGBA
+				&& format == PixelComponents.COLOR_RGB)) {
+					return "The Bitdepth.PACKED_32_BIT_101111_REV bitdepth can only be used with PixelDataType.FLOAT, ComponentOrder.RGBA, and FMT_COLOR_RGB.";
+				}
+				
+				// Short circuit.
+				return "";
+			}
+			
+			// Test all packed bitdepths.
+			if(bitDepth.ordinal() >= BitDepth.NUM_PER_COMPONENT.ordinal()) {
+				// Only unsigned integers and certain special floats can be packed.
+				// The special floats have already been checked, so let them through.
+				if(type != PixelDataType.NORM_UNSIGNED_INTEGER && type != PixelDataType.FLOAT) {
+					return "Only normalized, unsigned integers and floats can use packed bitdepths.";
+				}
+				
+				// Ensure that bitdepth and the format match in terms of component count.
+				switch(DdsUtil.calcComponentCount(format)) {
+					case 1:
+						// This can never work.
+						return "Single-component formats cannot work with packed bitdepths.";
+					case 2:
+						// Covered previously.
+						return "Non-depth two-component formats cannot work with packed bitdepths.";
+					case 3:
+						if(!DdsUtil.isOneOfThese(bitDepth, s_threeCompBitdepths)) {
+							return "The only packed formats available to 3-component formats are 565 or 565_REV.";
+						}
+						break;
+					case 4:
+						if(DdsUtil.isOneOfThese(bitDepth, s_threeCompBitdepths)) {
+							return "Cannot use 565 or 565_REV with 4-component formats.";
+						}
+						break;
+				}
+			}
+			
+			// Normalized types cannot use 32-bit per-component.
+			if(bitDepth == BitDepth.PER_COMP_32) {
+				if(type == PixelDataType.NORM_UNSIGNED_INTEGER || type == PixelDataType.NORM_SIGNED_INTEGER) {
+					return "Normalized integer formats cannot be used with 32-bit per-component data.";
+				}
+			}
+			
+			// BGRA ordering can only use 3 and 4 component types.
+			if(order == ComponentOrder.BGRA) {
+				if(DdsUtil.calcComponentCount(format) < 3) {
+					return "BGRA ordering can only use 3 or 4 components.";
+				}
+			}
+			
+			return "";
+		}
+	}
+	
+	ImageFormat(UncheckedImageFormat uncheckedImageFormat) {
+		m_uncheckedImageFormat = uncheckedImageFormat;
+		
+		String message = m_uncheckedImageFormat.validateFormatText();
+		if(!message.equals("")) {
+			throw new InvalidFormatException(message);
+		}
+	}
+	
+	final PixelDataType getPixelDataType() {
+		return m_uncheckedImageFormat.type;
+	}
+	
+	final PixelComponents getPixelComponents() {
+		return m_uncheckedImageFormat.format;
+	}
+	
+	final ComponentOrder getComponentOrder() {
+		return m_uncheckedImageFormat.order;
+	}
+	
+	final BitDepth getBitDepth() {
+		return m_uncheckedImageFormat.bitDepth;
+	}
+	
+	final int alignByteCount(int byteCount) {
+		return (byteCount + (m_uncheckedImageFormat.lineAlignment - 1)) / m_uncheckedImageFormat.lineAlignment;
+	}
+	
+	final int getLineAlignment() {
+		return m_uncheckedImageFormat.lineAlignment;
+	}
+	
+	private static PixelComponents[] s_alphaFormats = { PixelComponents.COLOR_RGBA, PixelComponents.COLOR_RGBA_SRGB };
+	private static PixelComponents[] s_rgbFormats = { PixelComponents.COLOR_RGB, PixelComponents.COLOR_RGB_SRGB };
+	private static PixelComponents[] s_srgbFormats = { PixelComponents.COLOR_RGB_SRGB, PixelComponents.COLOR_RGBX_SRGB, PixelComponents.COLOR_RGBA_SRGB };
+	
+	private static BitDepth[] s_floatBitdepths = { BitDepth.PER_COMP_16, BitDepth.PER_COMP_32, BitDepth.PACKED_32_BIT_101111_REV };
+	private static BitDepth[] s_threeCompBitdepths = { BitDepth.PACKED_16_BIT_565, BitDepth.PACKED_16_BIT_565_REV };
+	
+	private UncheckedImageFormat m_uncheckedImageFormat;
+	
+	private static class InvalidFormatException extends RuntimeException {
+		private static final long serialVersionUID = -7933858147860721000L;
+		
+		InvalidFormatException(String message) {
+			super(message);
+		}
+	}
+}

src/rosick/jglsdk/glimg/ImageSet.java

+package rosick.jglsdk.glimg;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+import org.lwjgl.BufferUtils;
+
+/**
+ * Visit https://github.com/integeruser/jglsdk for project info, updates and license terms.
+ * 
+ * @author integeruser
+ */
+public class ImageSet {
+	
+	public static class Dimensions {
+		public int numDimensions; // The number of dimensions of an image. Can be 1, 2, or 3.
+		public int width; // The width of the image. Always valid.
+		public int height; // The height of the image. Only valid if numDimensions is 2 or 3.
+		public int depth; // The depth of the image. Only valid if numDimensions is 3.
+		
+		public Dimensions() {}
+		
+		public Dimensions(Dimensions dimensions) {
+			numDimensions = dimensions.numDimensions;
+			width = dimensions.width;
+			height = dimensions.height;
+			depth = dimensions.depth;
+		}
+		
+		// Computes the number of rows of pixel data in the image.
+		public int calcNumLines() {
+			switch(numDimensions) {
+				case 1:
+					return 1;
+				case 2:
+					return height;
+				case 3:
+					return depth * height;
+			}
+			
+			// Should not be possible.
+			return -1;
+		}
+	}
+	
+	public static class SingleImage {
+		public Dimensions getDimensions() {
+			return m_imageSet.getDimensions(m_mipmapLevel);
+		}
+		
+		public ByteBuffer getImageData() {
+			return m_imageSet.getImageData(m_mipmapLevel, m_arrayIx, m_faceIx);
+		}
+		
+		public final int getSize() {
+			return m_imageSet.getSize(m_mipmapLevel);
+		}
+		
+		private ImageSet m_imageSet;
+		private int m_arrayIx, m_faceIx, m_mipmapLevel;
+		
+		private SingleImage(ImageSet imageSet, int mipmapLevel, int arrayIx, int faceIx) {
+			m_imageSet = imageSet;
+			m_arrayIx = arrayIx;
+			m_faceIx = faceIx;
+			m_mipmapLevel = mipmapLevel;
+		}
+	}
+	
+	public final int getMipmapCount() {
+		return m_mipmapCount;
+	}
+	
+	public final ImageFormat getFormat() {
+		return m_format;
+	}
+	
+	public final Dimensions getDimensions() {
+		return m_dimensions;
+	}
+	
+	public final Dimensions getDimensions(int mipmapLevel) {
+		return DdsUtil.calcMipmapLevelDimensions(m_dimensions, mipmapLevel);
+	}
+	
+	public final SingleImage getImage(int mipmapLevel, int arrayIx, int faceIx) {
+		return new SingleImage(this, mipmapLevel, arrayIx, faceIx);
+	}
+	
+	ImageSet(ImageFormat imageFormat, Dimensions imageDimensions, int mipmapCount, int arrayCount, int faceCount,
+			ArrayList<byte[]> imageData, int[] imageSizes) {
+		m_format = imageFormat;
+		m_dimensions = imageDimensions;
+		m_imageData = imageData;
+		m_imageSizes = imageSizes;
+		m_arrayCount = arrayCount;
+		m_mipmapCount = mipmapCount;
+		m_faceCount = faceCount;
+	}
+	
+	final int getArrayCount() {
+		return m_arrayCount;
+	}
+	
+	final int getFaceCount() {
+		return m_faceCount;
+	}
+	
+	final int getSize(int mipmap) {
+		return m_imageSizes[mipmap];
+	}
+	
+	final ByteBuffer getImageData(int mipmapLevel, int arrayIx, int faceIx) {
+		byte[] imageData = m_imageData.get(mipmapLevel);
+		int imageDataOffset = ((arrayIx * m_faceCount) + faceIx) * m_imageSizes[mipmapLevel];
+		
+		ByteBuffer imageDataBuffer = BufferUtils.createByteBuffer(m_imageSizes[mipmapLevel]);
+		for(int i = imageDataOffset; i < imageDataOffset + m_imageSizes[mipmapLevel]; i++) {
+			imageDataBuffer.put(imageData[i]);
+		}
+		
+		imageDataBuffer.flip();
+		
+		return imageDataBuffer;
+	}
+	
+	private ImageFormat m_format;
+	private Dimensions m_dimensions;
+	
+	private int[] m_imageSizes;
+	private ArrayList<byte[]> m_imageData;
+	
+	private int m_arrayCount;
+	private int m_faceCount;
+	private int m_mipmapCount;
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.