diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CImageWriterTGA.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CImageWriterTGA.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CImageWriterTGA.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CImageWriterTGA.cpp new file mode 100644 index 0000000..4a87eeb --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CImageWriterTGA.cpp | |||
@@ -0,0 +1,147 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "CImageWriterTGA.h" | ||
6 | |||
7 | #ifdef _IRR_COMPILE_WITH_TGA_WRITER_ | ||
8 | |||
9 | #include "CImageLoaderTGA.h" | ||
10 | #include "IWriteFile.h" | ||
11 | #include "CColorConverter.h" | ||
12 | #include "irrString.h" | ||
13 | |||
14 | namespace irr | ||
15 | { | ||
16 | namespace video | ||
17 | { | ||
18 | |||
19 | IImageWriter* createImageWriterTGA() | ||
20 | { | ||
21 | return new CImageWriterTGA; | ||
22 | } | ||
23 | |||
24 | CImageWriterTGA::CImageWriterTGA() | ||
25 | { | ||
26 | #ifdef _DEBUG | ||
27 | setDebugName("CImageWriterTGA"); | ||
28 | #endif | ||
29 | } | ||
30 | |||
31 | bool CImageWriterTGA::isAWriteableFileExtension(const io::path& filename) const | ||
32 | { | ||
33 | return core::hasFileExtension ( filename, "tga" ); | ||
34 | } | ||
35 | |||
36 | bool CImageWriterTGA::writeImage(io::IWriteFile *file, IImage *image,u32 param) const | ||
37 | { | ||
38 | STGAHeader imageHeader; | ||
39 | imageHeader.IdLength = 0; | ||
40 | imageHeader.ColorMapType = 0; | ||
41 | imageHeader.ImageType = 2; | ||
42 | imageHeader.FirstEntryIndex[0] = 0; | ||
43 | imageHeader.FirstEntryIndex[1] = 0; | ||
44 | imageHeader.ColorMapLength = 0; | ||
45 | imageHeader.ColorMapEntrySize = 0; | ||
46 | imageHeader.XOrigin[0] = 0; | ||
47 | imageHeader.XOrigin[1] = 0; | ||
48 | imageHeader.YOrigin[0] = 0; | ||
49 | imageHeader.YOrigin[1] = 0; | ||
50 | imageHeader.ImageWidth = image->getDimension().Width; | ||
51 | imageHeader.ImageHeight = image->getDimension().Height; | ||
52 | |||
53 | // top left of image is the top. the image loader needs to | ||
54 | // be fixed to only swap/flip | ||
55 | imageHeader.ImageDescriptor = (1 << 5); | ||
56 | |||
57 | // chances are good we'll need to swizzle data, so i'm going | ||
58 | // to convert and write one scan line at a time. it's also | ||
59 | // a bit cleaner this way | ||
60 | void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0; | ||
61 | switch(image->getColorFormat()) | ||
62 | { | ||
63 | case ECF_A8R8G8B8: | ||
64 | CColorConverter_convertFORMATtoFORMAT | ||
65 | = CColorConverter::convert_A8R8G8B8toA8R8G8B8; | ||
66 | imageHeader.PixelDepth = 32; | ||
67 | imageHeader.ImageDescriptor |= 8; | ||
68 | break; | ||
69 | case ECF_A1R5G5B5: | ||
70 | CColorConverter_convertFORMATtoFORMAT | ||
71 | = CColorConverter::convert_A1R5G5B5toA1R5G5B5; | ||
72 | imageHeader.PixelDepth = 16; | ||
73 | imageHeader.ImageDescriptor |= 1; | ||
74 | break; | ||
75 | case ECF_R5G6B5: | ||
76 | CColorConverter_convertFORMATtoFORMAT | ||
77 | = CColorConverter::convert_R5G6B5toA1R5G5B5; | ||
78 | imageHeader.PixelDepth = 16; | ||
79 | imageHeader.ImageDescriptor |= 1; | ||
80 | break; | ||
81 | case ECF_R8G8B8: | ||
82 | CColorConverter_convertFORMATtoFORMAT | ||
83 | = CColorConverter::convert_R8G8B8toR8G8B8; | ||
84 | imageHeader.PixelDepth = 24; | ||
85 | imageHeader.ImageDescriptor |= 0; | ||
86 | break; | ||
87 | #ifndef _DEBUG | ||
88 | default: | ||
89 | break; | ||
90 | #endif | ||
91 | } | ||
92 | |||
93 | // couldn't find a color converter | ||
94 | if (!CColorConverter_convertFORMATtoFORMAT) | ||
95 | return false; | ||
96 | |||
97 | if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader)) | ||
98 | return false; | ||
99 | |||
100 | u8* scan_lines = (u8*)image->lock(); | ||
101 | if (!scan_lines) | ||
102 | return false; | ||
103 | |||
104 | // size of one pixel in bytes | ||
105 | u32 pixel_size = image->getBytesPerPixel(); | ||
106 | |||
107 | // length of one row of the source image in bytes | ||
108 | u32 row_stride = (pixel_size * imageHeader.ImageWidth); | ||
109 | |||
110 | // length of one output row in bytes | ||
111 | s32 row_size = ((imageHeader.PixelDepth / 8) * imageHeader.ImageWidth); | ||
112 | |||
113 | // allocate a row do translate data into | ||
114 | u8* row_pointer = new u8[row_size]; | ||
115 | |||
116 | u32 y; | ||
117 | for (y = 0; y < imageHeader.ImageHeight; ++y) | ||
118 | { | ||
119 | // source, length [pixels], destination | ||
120 | if (image->getColorFormat()==ECF_R8G8B8) | ||
121 | CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.ImageWidth, 1, 0, 0, true); | ||
122 | else | ||
123 | CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.ImageWidth, row_pointer); | ||
124 | if (file->write(row_pointer, row_size) != row_size) | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | delete [] row_pointer; | ||
129 | |||
130 | image->unlock(); | ||
131 | |||
132 | STGAFooter imageFooter; | ||
133 | imageFooter.ExtensionOffset = 0; | ||
134 | imageFooter.DeveloperOffset = 0; | ||
135 | strncpy(imageFooter.Signature, "TRUEVISION-XFILE.", 18); | ||
136 | |||
137 | if (file->write(&imageFooter, sizeof(imageFooter)) < (s32)sizeof(imageFooter)) | ||
138 | return false; | ||
139 | |||
140 | return imageHeader.ImageHeight <= y; | ||
141 | } | ||
142 | |||
143 | } // namespace video | ||
144 | } // namespace irr | ||
145 | |||
146 | #endif | ||
147 | |||