~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CImageWriterBMP.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 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 "CImageWriterBMP.h"
 
6
 
 
7
#ifdef _IRR_COMPILE_WITH_BMP_WRITER_
 
8
 
 
9
#include "CImageLoaderBMP.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* createImageWriterBMP()
 
20
{
 
21
        return new CImageWriterBMP;
 
22
}
 
23
 
 
24
CImageWriterBMP::CImageWriterBMP()
 
25
{
 
26
#ifdef _DEBUG
 
27
        setDebugName("CImageWriterBMP");
 
28
#endif
 
29
}
 
30
 
 
31
bool CImageWriterBMP::isAWriteableFileExtension(const io::path& filename) const
 
32
{
 
33
        return core::hasFileExtension ( filename, "bmp" );
 
34
}
 
35
 
 
36
bool CImageWriterBMP::writeImage(io::IWriteFile* file, IImage* image, u32 param) const
 
37
{
 
38
        // we always write 24-bit color because nothing really reads 32-bit
 
39
 
 
40
        SBMPHeader imageHeader;
 
41
        imageHeader.Id = 0x4d42;
 
42
        imageHeader.Reserved = 0;
 
43
        imageHeader.BitmapDataOffset = sizeof(imageHeader);
 
44
        imageHeader.BitmapHeaderSize = 0x28;
 
45
        imageHeader.Width = image->getDimension().Width;
 
46
        imageHeader.Height = image->getDimension().Height;
 
47
        imageHeader.Planes = 1;
 
48
        imageHeader.BPP = 24;
 
49
        imageHeader.Compression = 0;
 
50
        imageHeader.PixelPerMeterX = 0;
 
51
        imageHeader.PixelPerMeterY = 0;
 
52
        imageHeader.Colors = 0;
 
53
        imageHeader.ImportantColors = 0;
 
54
 
 
55
        // data size is rounded up to next larger 4 bytes boundary
 
56
        imageHeader.BitmapDataSize = imageHeader.Width * imageHeader.BPP / 8;
 
57
        imageHeader.BitmapDataSize = (imageHeader.BitmapDataSize + 3) & ~3;
 
58
        imageHeader.BitmapDataSize *= imageHeader.Height;
 
59
 
 
60
        // file size is data size plus offset to data
 
61
        imageHeader.FileSize = imageHeader.BitmapDataOffset + imageHeader.BitmapDataSize;
 
62
 
 
63
        // bitmaps are stored upside down and padded so we always do this
 
64
        void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0;
 
65
        switch(image->getColorFormat())
 
66
        {
 
67
        case ECF_R8G8B8:
 
68
                CColorConverter_convertFORMATtoFORMAT
 
69
                        = CColorConverter::convert_R8G8B8toR8G8B8;
 
70
                break;
 
71
        case ECF_A8R8G8B8:
 
72
                CColorConverter_convertFORMATtoFORMAT
 
73
                        = CColorConverter::convert_A8R8G8B8toB8G8R8;
 
74
                break;
 
75
        case ECF_A1R5G5B5:
 
76
                CColorConverter_convertFORMATtoFORMAT
 
77
                        = CColorConverter::convert_A1R5G5B5toR8G8B8;
 
78
                break;
 
79
        case ECF_R5G6B5:
 
80
                CColorConverter_convertFORMATtoFORMAT
 
81
                        = CColorConverter::convert_R5G6B5toR8G8B8;
 
82
                break;
 
83
        }
 
84
 
 
85
        // couldn't find a color converter
 
86
        if (!CColorConverter_convertFORMATtoFORMAT)
 
87
                return false;
 
88
 
 
89
        // write the bitmap header
 
90
        if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader))
 
91
                return false;
 
92
 
 
93
        u8* scan_lines = (u8*)image->lock();
 
94
        if (!scan_lines)
 
95
                return false;
 
96
 
 
97
        // size of one pixel in bytes
 
98
        u32 pixel_size = image->getBytesPerPixel();
 
99
 
 
100
        // length of one row of the source image in bytes
 
101
        u32 row_stride = (pixel_size * imageHeader.Width);
 
102
 
 
103
        // length of one row in bytes, rounded up to nearest 4-byte boundary
 
104
        s32 row_size = ((3 * imageHeader.Width) + 3) & ~3;
 
105
 
 
106
        // allocate and clear memory for our scan line
 
107
        u8* row_pointer = new u8[row_size];
 
108
        memset(row_pointer, 0, row_size);
 
109
 
 
110
        // convert the image to 24-bit BGR and flip it over
 
111
        s32 y;
 
112
        for (y = imageHeader.Height - 1; 0 <= y; --y)
 
113
        {
 
114
                if (image->getColorFormat()==ECF_R8G8B8)
 
115
                        CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.Width, 1, 0, false, true);
 
116
                else
 
117
                        // source, length [pixels], destination
 
118
                        CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.Width, row_pointer);
 
119
                if (file->write(row_pointer, row_size) < row_size)
 
120
                        break;
 
121
        }
 
122
 
 
123
        // clean up our scratch area
 
124
        delete [] row_pointer;
 
125
 
 
126
        // give back image handle
 
127
        image->unlock();
 
128
 
 
129
        return y < 0;
 
130
}
 
131
 
 
132
} // namespace video
 
133
} // namespace irr
 
134
 
 
135
#endif
 
136