summaryrefslogtreecommitdiff
path: root/src/graphics/Bitmap.h
blob: 8a46a99dd788f3304c9424dfc5c1aac8ec9c63cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//
//  libavg - Media Playback Engine. 
//  Copyright (C) 2003-2014 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#ifndef _Bitmap_H_
#define _Bitmap_H_

#include "../api.h"
#include "Pixel32.h"
#include "PixelFormat.h"

#include "../base/Rect.h"
#include "../base/GLMHelper.h"
#include "../base/UTF8String.h"

#include <boost/shared_ptr.hpp>

#if defined(__SSE__) || defined(_WIN32)
#include <xmmintrin.h>
#endif

#include <stdlib.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

namespace avg {

typedef std::vector<int> Histogram;
typedef boost::shared_ptr<Histogram> HistogramPtr;

class Bitmap;
typedef boost::shared_ptr<Bitmap> BitmapPtr;

class AVG_API Bitmap
{
public:
    Bitmap(glm::vec2 size, PixelFormat pf, const UTF8String& sName="", int stride=0);
    Bitmap(IntPoint size, PixelFormat pf, const UTF8String& sName="", int stride=0);
    Bitmap(IntPoint size, PixelFormat pf, unsigned char * pBits, 
            int stride, bool bCopyBits, const UTF8String& sName="");
    Bitmap(const Bitmap& origBmp);
    Bitmap(const Bitmap& origBmp, bool bOwnsBits);
    Bitmap(Bitmap& origBmp, const IntRect& rect);
    virtual ~Bitmap();

    Bitmap &operator =(const Bitmap & origBmp);
    
    // Does pixel format conversion if nessesary.
    void copyPixels(const Bitmap& origBmp);
    void copyYUVPixels(const Bitmap& yBmp, const Bitmap& uBmp, const Bitmap& vBmp,
            bool bJPEG);
    void save(const UTF8String& sName);
    
    IntPoint getSize() const;
    int getStride() const;
    PixelFormat getPixelFormat() const;
    void setPixelFormat(PixelFormat pf);
    unsigned char* getPixels();
    const unsigned char* getPixels() const;
    std::string getPixelsAsString() const;
    void setPixels(const unsigned char* pPixels);
    void setPixelsFromString(const std::string& sPixels);
    bool ownsBits() const;
    const std::string& getName() const;
    int getBytesPerPixel() const;
    int getLineLen() const;
    int getMemNeeded() const;
    bool hasAlpha() const;
    HistogramPtr getHistogram(int stride = 1) const;
    void getMinMax(int stride, int& min, int& max) const;
    void setAlpha(const Bitmap& alphaBmp);

    Pixel32 getPythonPixel(const glm::vec2& pos);
    template<class PIXEL>
    void setPixel(const IntPoint& p, PIXEL color);
    template<class PIXEL>
    void drawLine(IntPoint p0, IntPoint p1, PIXEL color);

    BitmapPtr subtract(const Bitmap& pOtherBmp);
    void blt(const Bitmap& otherBmp, const IntPoint& pos);
    float getAvg() const;
    float getChannelAvg(int channel) const;
    float getStdDev() const;

    bool operator ==(const Bitmap& otherBmp);
    void dump(bool bDumpPixels=false) const;

    static int getPreferredStride(int width, PixelFormat pf);

private:
    void initWithData(unsigned char* pBits, int stride, bool bCopyBits);
    void allocBits(int stride=0);
    void YCbCrtoBGR(const Bitmap& origBmp);
    void YCbCrtoI8(const Bitmap& origBmp);
    void I8toI16(const Bitmap& origBmp);
    void I8toRGB(const Bitmap& origBmp);
    void I16toI8(const Bitmap& origBmp);
    void BGRtoB5G6R5(const Bitmap& origBmp);
    void ByteRGBAtoFloatRGBA(const Bitmap& origBmp);
    void FloatRGBAtoByteRGBA(const Bitmap& origBmp);
    void BY8toRGBNearest(const Bitmap& origBmp);
    void BY8toRGBBilinear(const Bitmap& origBmp);

    IntPoint m_Size;
    int m_Stride;
    PixelFormat m_PF;
    unsigned char* m_pBits;
    bool m_bOwnsBits;
    UTF8String m_sName;

    static bool s_bMagickInitialized;
    static bool s_bGTKInitialized;
};

BitmapPtr YCbCr2RGBBitmap(BitmapPtr pYBmp, BitmapPtr pUBmp, BitmapPtr pVBmp);

template<class PIXEL>
void Bitmap::setPixel(const IntPoint& p, PIXEL color)
{
    *(PIXEL*)(&(m_pBits[p.y*m_Stride+p.x*getBytesPerPixel()])) = color;
}

// TODO: This is slow, and it clips incorrectly. Replace with external lib?
template<class PIXEL>
void Bitmap::drawLine(IntPoint p0, IntPoint p1, PIXEL color)
{
    IntRect BmpRect(IntPoint(0,0), m_Size);
    p0 = BmpRect.cropPoint(p0);
    p1 = BmpRect.cropPoint(p1);

    bool bSteep = abs(p1.y - p0.y) > abs(p1.x - p0.x);
    if (bSteep) {
        std::swap(p0.x, p0.y);
        std::swap(p1.x, p1.y);
    }
    if (p0.x > p1.x) {
        std::swap(p0, p1); 
    }
    int deltax = p1.x - p0.x;
    int deltay = abs(p1.y - p0.y);
    int error = -deltax/2;
    int ystep;
    int y = p0.y;
    if (p0.y < p1.y) {
        ystep = 1;
    } else {
        ystep = -1;
    }
    for (int x = p0.x; x <= p1.x; x++) {
        if (bSteep) {
            setPixel(IntPoint(y, x), color); 
        } else {
            setPixel(IntPoint(x, y), color);
        }
        error += deltay;
        if (error > 0) {
            y += ystep;
            error -= deltax;
        }
    }
}
#if defined(__SSE__) || defined(_WIN32)
std::ostream& operator<<(std::ostream& os, const __m64 &val);
#endif

}
#endif