1 {
2 $Id: ImagingDds.pas 129 2008-08-06 20:01:30Z galfar $
3 Vampyre Imaging Library
4 by Marek Mauder
5 http://imaginglib.sourceforge.net
7 The contents of this file are used with permission, subject to the Mozilla
8 Public License Version 1.1 (the "License"); you may not use this file except
9 in compliance with the License. You may obtain a copy of the License at
10 http://www.mozilla.org/MPL/MPL-1.1.html
12 Software distributed under the License is distributed on an "AS IS" basis,
13 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 the specific language governing rights and limitations under the License.
16 Alternatively, the contents of this file may be used under the terms of the
17 GNU Lesser General Public License (the "LGPL License"), in which case the
18 provisions of the LGPL License are applicable instead of those above.
19 If you wish to allow use of your version of this file only under the terms
20 of the LGPL License and not to allow others to use your version of this file
21 under the MPL, indicate your decision by deleting the provisions above and
22 replace them with the notice and other provisions required by the LGPL
23 License. If you do not delete the provisions above, a recipient may use
24 your version of this file under either the MPL or the LGPL License.
26 For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
27 }
29 { This unit contains image format loader/saver for DirectDraw Surface images.}
32 {$I ImagingOptions.inc}
34 interface
36 uses
39 type
40 { Class for loading and saving Microsoft DirectDraw surfaces.
41 It can load/save all D3D formats which have coresponding
42 TImageFormat. It supports plain textures, cube textures and
43 volume textures, all of these can have mipmaps. It can also
44 load some formats which have no exact TImageFormat, but can be easily
45 converted to one (bump map formats).
46 You can get some information about last loaded DDS file by calling
47 GetOption with ImagingDDSLoadedXXX options and you can set some
48 saving options by calling SetOption with ImagingDDSSaveXXX or you can
49 simply use properties of this class.
50 Note that when saving cube maps and volumes input image array must contain
51 at least number of images to build cube/volume based on current
52 Depth and MipMapCount settings.}
54 protected
71 public
75 published
76 { True if last loaded DDS file was cube map.}
78 { True if last loaded DDS file was volume texture.}
80 { Number of mipmap levels of last loaded DDS image.}
82 { Depth (slices of volume texture or faces of cube map) of last loaded DDS image.}
84 { True if next DDS file to be saved should be stored as cube map.}
86 { True if next DDS file to be saved should be stored as volume texture.}
88 { Sets the number of mipmaps which should be stored in the next saved DDS file.
89 Only applies to cube maps and volumes, ordinary 2D textures save all
90 levels present in input.}
92 { Sets the depth (slices of volume texture or faces of cube map)
93 of the next saved DDS file.}
97 implementation
99 const
107 const
108 { Four character codes.}
122 { Some D3DFORMAT values used in DDS files as FourCC value.}
129 { Constans used by TDDSurfaceDesc2.Flags.}
139 { Constans used by TDDSPixelFormat.Flags.}
147 { Constans used by TDDSCaps.Caps1.}
152 { Constans used by TDDSCaps.Caps2.}
162 { Flags for TDDSurfaceDesc2.Flags used when saving DDS file.}
166 type
167 { Stores the pixel format information.}
179 { Specifies capabilities of surface.}
186 { Record describing DDS file contents.}
193 // scanline. For comp it is the size in
194 // bytes of the main image
203 { DDS file header.}
210 { TDDSFileFormat class implementation }
213 begin
239 begin
252 var
254 begin
258 begin
260 begin
262 begin
263 // Cube maps are stored like this
264 // Face 0 mimap 0
265 // Face 0 mipmap 1
266 // ...
267 // Face 1 mipmap 0
268 // Face 1 mipmap 1
269 // ...
271 // Modify index so later in for loop we iterate less times
275 begin
279 end
280 else
281 begin
282 // Volume textures are stored in DDS files like this:
283 // Slice 0 mipmap 0
284 // Slice 1 mipmap 0
285 // Slice 2 mipmap 0
286 // Slice 3 mipmap 0
287 // Slice 0 mipmap 1
288 // Slice 1 mipmap 1
289 // Slice 0 mipmap 2
290 // Slice 0 mipmap 3 ...
294 begin
298 Break;
308 var
319 begin
325 begin
334 begin
336 {
337 // Set position to the end of the header (for possible future versions
338 // ith larger header)
339 Seek(Handle, Hdr.Desc.Size + SizeOf(Hdr.Magic) - SizeOf(Hdr),
340 smFromCurrent);
341 }
344 // Get image data format
346 begin
347 // Handle FourCC and large ARGB formats
360 end
362 begin
363 // Handle RGB formats
365 begin
366 // Handle RGB with alpha formats
369 begin
378 begin
384 end
385 else
386 begin
387 // Handle RGB without alpha formats
394 begin
407 begin
414 end
416 begin
417 // Handle luminance formats
419 begin
420 // Handle luminance with alpha formats
423 end
424 else
425 begin
426 // Handle luminance without alpha formats
432 end
434 begin
435 // Handle mixed bump-luminance formats like D3DFMT_X8L8V8U8
439 begin
444 end
446 begin
447 // Handle bumpmap formats like D3DFMT_Q8W8V8U8
452 begin
460 // If DDS format is not supported we will exit
463 // File contains mipmaps for each subimage.
464 { Some DDS writers ignore setting proper Caps and Flags so
465 this check is not usable:
466 if ((Desc.Caps.Caps1 and DDSCAPS_MIPMAP) = DDSCAPS_MIPMAP) and
467 ((Desc.Flags and DDSD_MIPMAPCOUNT) = DDSD_MIPMAPCOUNT) then}
469 begin
474 // File stores volume texture
477 begin
483 // File stores cube texture
485 begin
498 // Allocate and load all images in file
502 // Compute the pitch or get if from file if present
505 // Use linear as default if none is set
508 // Main image pitch or linear size
512 begin
513 // Compute dimensions of surrent subimage based on texture type and
514 // number of mipmaps
520 begin
521 // Compute pitch or linear size for mipmap levels, or even for main image
522 // since some formats do not fill pitch nor size
525 else
530 LoadSize := PitchOrLinear
531 else
535 begin
536 // If DDS does not use Pitch we can simply copy data
538 end
539 else
540 begin
541 // If DDS uses Pitch we must load aligned scanlines
542 // and then remove padding
544 try
548 finally
562 var
573 begin
579 // Some DDS saving rules:
580 // 2D textures: Len is used as mipmap count (FSaveMipMapCount not used!).
581 // Cube maps: FSaveDepth * FSaveMipMapCount images are used, if Len is
582 // smaller than this file is saved as regular 2D texture.
583 // Volume maps: GetVolumeLevelCount(FSaveDepth, FSaveMipMapCount) images are
584 // used, if Len is smaller than this file is
585 // saved as regular 2D texture.
592 begin
593 // Check if we have enough images on Input to save cube map
596 end
598 begin
599 // Check if we have enough images on Input to save volume texture
606 begin
607 // Get number of mipmaps used with 2D texture
611 // we create compatible main image and fill headers
614 try
627 begin
628 // Set proper flags if we have some mipmaps to be saved
635 begin
636 // Set proper cube map flags - number of stored faces is taken
637 // from FSaveDepth
642 begin
647 end
649 begin
650 // Set proper flags for volume texture
658 // Now we set DDS pixel format for main image
661 begin
675 end
677 begin
683 ifA8Gray8:
684 begin
690 end
691 else
692 begin
696 begin
701 begin
705 end
706 else
707 begin
715 // Header and main image are written to output
719 // Write the rest of the images and convert them to
720 // the same format as main image if necessary and ensure proper mipmap
721 // simensions too.
723 begin
724 // Get proper dimensions for this level
728 // Check if input image for this level has the right size and format
733 begin
734 // Input image must be resized or converted to different format
735 // to become valid mipmap level
742 end
743 else
744 // Input image can be used without any changes
747 // Write level data and release temp image if necessary
754 finally
762 var
764 begin
766 // convert indexed and unsupported special formatd to A8R8G8B8
767 ConvFormat := ifA8R8G8B8
769 begin
771 // only swap channels here
772 ConvFormat := ifA16B16G16R16F
773 else
774 // convert other floating point formats to A32B32G32R32F
775 ConvFormat := ifA32B32G32R32F
776 end
778 begin
780 // convert grayscale with alpha to A8Gray8
781 ConvFormat := ifA8Gray8
783 // convert 8bit grayscale to Gray8
784 ConvFormat := ifGray8
785 else
786 // convert 16-64bit grayscales to Gray16
788 end
790 ConvFormat := ifA16B16G16R16
792 // convert the other images with alpha channel to A8R8G8B8
793 ConvFormat := ifA8R8G8B8
794 else
795 // convert the other formats to X8R8G8B8
802 var
805 begin
809 begin
817 initialization
820 {
821 File Notes:
823 -- TODOS ----------------------------------------------------
824 - nothing now
826 -- 0.25.0 Changes/Bug Fixes ---------------------------------
827 - Added support for 3Dc ATI1/2 formats.
829 -- 0.23 Changes/Bug Fixes -----------------------------------
830 - Saved DDS with mipmaps now correctly defineds COMPLEX flag.
831 - Fixed loading of RGB DDS files that use pitch and have mipmaps -
832 mipmaps were loaded wrongly.
834 -- 0.21 Changes/Bug Fixes -----------------------------------
835 - Changed saving behaviour a bit: mipmaps are inlcuded automatically for
836 2D textures if input image array has more than 1 image (no need to
837 set SaveMipMapCount manually).
838 - Mipmap levels are now saved with proper dimensions when saving DDS files.
839 - Made some changes to not be so strict when loading DDS files.
840 Many programs seem to save them in non-standard format
841 (by MS DDS File Reference).
842 - Added missing ifX8R8G8B8 to SupportedFormats, MakeCompatible failed
843 when image was converted to this format (inside).
844 - MakeCompatible method moved to base class, put ConvertToSupported here.
845 GetSupportedFormats removed, it is now set in constructor.
846 - Fixed bug that sometimes saved non-standard DDS files and another
847 one that caused crash when these files were loaded.
848 - Changed extensions to filename masks.
849 - Changed SaveData, LoadData, and MakeCompatible methods according
850 to changes in base class in Imaging unit.
852 -- 0.19 Changes/Bug Fixes -----------------------------------
853 - added support for half-float image formats
854 - change in LoadData to allow support for more images
855 in one stream loading
857 -- 0.17 Changes/Bug Fixes -----------------------------------
858 - fixed bug in TestFormat which does not recognize many DDS files
859 - changed pitch/linearsize handling in DDS loading code to
860 load DDS files produced by NVidia's Photoshop plugin
861 }