Bläddra i källkod

Added Texture

Thomas Buck 10 år sedan
förälder
incheckning
e02c9affed
3 ändrade filer med 700 tillägg och 0 borttagningar
  1. 175
    0
      include/Texture.h
  2. 1
    0
      src/CMakeLists.txt
  3. 524
    0
      src/Texture.cpp

+ 175
- 0
include/Texture.h Visa fil

@@ -0,0 +1,175 @@
1
+/*!
2
+ * \file include/Texture.h
3
+ * \brief Texture registry
4
+ *
5
+ * \author Mongoose
6
+ * \author xythobuz
7
+ */
8
+
9
+#ifndef _TEXTURE_H
10
+#define _TEXTURE_H
11
+
12
+#include <stdio.h>
13
+
14
+/*!
15
+ * \brief Texture registry
16
+ */
17
+class Texture {
18
+public:
19
+
20
+    enum ColorMode {
21
+        GREYSCALE = 1,
22
+        RGB,
23
+        RGBA,
24
+        ARGB
25
+    };
26
+
27
+    enum TextureFlag {
28
+        fUseMipmaps      = (1 << 0),
29
+        fUseMultiTexture = (1 << 1),
30
+        fUseSDL_TTF      = (1 << 2)
31
+    };
32
+
33
+    /*!
34
+    * \brief Constructs an object of Texture
35
+    */
36
+    Texture();
37
+
38
+   /*!
39
+    * \brief Deconstructs an object of Texture
40
+    */
41
+    ~Texture();
42
+
43
+    /*!
44
+     * \brief Generates a texture buffer with (width * height * 4) bytes.
45
+     * \param rgba 32bpp RGBA color to fill into buffer
46
+     * \param width width of newly allocated buffer, power of 2, pref same as height
47
+     * \param height height of newly allocated buffer, power of 2, pref same as width
48
+     * \returns newly allocated texture buffer filled with specified color
49
+     */
50
+    static unsigned char *generateColorTexture(unsigned char rgba[4],
51
+                                                unsigned int width,
52
+                                                unsigned int height);
53
+
54
+    /*!
55
+     * \brief Get number of textures in use
56
+     * \returns used texture count, or -1 on error (uninitialized)
57
+     */
58
+    int getTextureCount();
59
+
60
+    /*!
61
+     * \brief Dumps a screenshot to disk.
62
+     *
63
+     * Avoids overwriting files with same base name.
64
+     * \param base base filename
65
+     * \param width viewport width
66
+     * \param height viewport height
67
+     */
68
+    void glScreenShot(char *base, unsigned int width, unsigned int height);
69
+
70
+    /*!
71
+     * \brief Sets up multitexture rendering with passed ids
72
+     * \param texture0 first texture for multitexture
73
+     * \param texture1 second texture for multitexture
74
+     */
75
+    void bindMultiTexture(int texture0, int texture1);
76
+
77
+    /*!
78
+     * \brief Binds the texture for use in GL
79
+     * \param n valid texture index
80
+     */
81
+    void bindTextureId(unsigned int n);
82
+
83
+    /*!
84
+     * \brief Clears an option flag
85
+     * \param flag flag to clear
86
+     */
87
+    void clearFlag(TextureFlag flag);
88
+
89
+    void disableMultiTexture();
90
+
91
+    /*!
92
+     * \brief Loads Buffer as texture
93
+     * \param image pixmap matching other params
94
+     * \param width width of image
95
+     * \param height height of image
96
+     * \param mode mode of image
97
+     * \param bpp bits per pixel of image
98
+     * \returns texture ID or < 0 on error
99
+     */
100
+    int loadBuffer(unsigned char *image,
101
+                    unsigned int width, unsigned int height,
102
+                    ColorMode mode, unsigned int bpp);
103
+
104
+    /*!
105
+     * \brief Loads Buffer as texture
106
+     * \param image pixmap matching other params
107
+     * \param width width of image
108
+     * \param height height of image
109
+     * \param mode mode of image
110
+     * \param bpp bits per pixel of image
111
+     * \param slot slot (ID) of image
112
+     * \returns texture ID or < 0 on error
113
+     */
114
+    int loadBufferSlot(unsigned char *image,
115
+                        unsigned int width, unsigned int height,
116
+                        ColorMode mode, unsigned int bpp,
117
+                        unsigned int slot);
118
+
119
+    /*!
120
+     * \brief Generates and loads a solid color texture.
121
+     * \param rgba color for new texture
122
+     * \param width width of new texture
123
+     * \param height height of new texture
124
+     * \returns texture ID or -1 on error
125
+     */
126
+    int loadColorTexture(unsigned char rgba[4],
127
+                            unsigned int width, unsigned int height);
128
+
129
+    /*!
130
+     * \brief Loads TGA file as texture
131
+     * \param filename Existing TGA file
132
+     * \returns ID of new texture or -1 on error
133
+     */
134
+    int loadTGA(const char *filename);
135
+
136
+    /*!
137
+     * \brief Resets all texture data
138
+     */
139
+    void reset();
140
+
141
+    /*!
142
+     * \brief Sets an option flag
143
+     * \param flag flag to set
144
+     */
145
+    void setFlag(TextureFlag flag);
146
+
147
+    /*!
148
+     * \brief Sets up GL texturing.
149
+     *
150
+     * Must be called as first setup step!
151
+     * \param n maximum number of textures you wish to allow
152
+     */
153
+    void setMaxTextureCount(unsigned int n);
154
+
155
+    void useMultiTexture(float u, float v);
156
+
157
+    void useMultiTexture(float aU, float aV, float bU, float bV);
158
+
159
+private:
160
+
161
+    int nextPower(int seed);
162
+
163
+    unsigned char *scaleBuffer(unsigned char *image, int width, int height,
164
+                                int components);
165
+
166
+    unsigned int *mTextureIds;  //!< GL texture list
167
+    unsigned int mTextureCount; //!< Texture counter
168
+    unsigned int mTextureLimit; //!< The texture limit
169
+    unsigned int mFlags;        //!< Class options
170
+    int mTextureId;             //!< Currently bound texture id
171
+    int mTextureId2;            //!< Multitexture Texture Id
172
+};
173
+
174
+#endif
175
+

+ 1
- 0
src/CMakeLists.txt Visa fil

@@ -42,6 +42,7 @@ set (SRCS ${SRCS} "OpenRaider.cpp")
42 42
 set (SRCS ${SRCS} "Particle.cpp")
43 43
 set (SRCS ${SRCS} "SkeletalModel.cpp")
44 44
 set (SRCS ${SRCS} "Sound.cpp")
45
+set (SRCS ${SRCS} "Texture.cpp")
45 46
 set (SRCS ${SRCS} "TombRaider.cpp")
46 47
 set (SRCS ${SRCS} "ViewVolume.cpp")
47 48
 set (SRCS ${SRCS} "Window.cpp")

+ 524
- 0
src/Texture.cpp Visa fil

@@ -0,0 +1,524 @@
1
+/*!
2
+ * \file src/Texture.cpp
3
+ * \brief Texture registry
4
+ *
5
+ * \author Mongoose
6
+ * \author xythobuz
7
+ */
8
+
9
+#include <string.h>
10
+#include <stdlib.h>
11
+#include <stdio.h>
12
+#include <stdarg.h>
13
+
14
+#ifdef __APPLE__
15
+#include <OpenGL/gl.h>
16
+#include <OpenGL/glu.h>
17
+#else
18
+#include <GL/gl.h>
19
+#include <GL/glu.h>
20
+#endif
21
+
22
+#include "utils/tga.h"
23
+#include "Texture.h"
24
+
25
+Texture::Texture() {
26
+    mTextureIds = NULL;
27
+    mFlags = 0;
28
+    mTextureId = -1;
29
+    mTextureId2 = -1;
30
+    mTextureCount = 0;
31
+    mTextureLimit = 0;
32
+}
33
+
34
+Texture::~Texture() {
35
+    reset();
36
+}
37
+
38
+unsigned char *Texture::generateColorTexture(unsigned char rgba[4],
39
+        unsigned int width, unsigned int height) {
40
+    unsigned char *image;
41
+    unsigned int i, size;
42
+
43
+    image = new unsigned char[height*width*4];
44
+
45
+    for (i = 0, size = width*height; i < size; ++i) {
46
+        /* RBGA */
47
+        image[i*4]   = rgba[0];
48
+        image[i*4+1] = rgba[1];
49
+        image[i*4+2] = rgba[2];
50
+        image[i*4+3] = rgba[3];
51
+    }
52
+
53
+    return image;
54
+}
55
+
56
+int Texture::loadColorTexture(unsigned char rgba[4],
57
+        unsigned int width, unsigned int height) {
58
+    unsigned char *image;
59
+    int id;
60
+
61
+    image = generateColorTexture(rgba, width, height);
62
+    id = loadBuffer(image, width, height, RGBA, 32);
63
+    delete [] image;
64
+
65
+    return id;
66
+}
67
+
68
+void Texture::setFlag(TextureFlag flag) {
69
+    mFlags |= flag;
70
+}
71
+
72
+void Texture::clearFlag(TextureFlag flag) {
73
+    mFlags |= flag;
74
+    mFlags ^= flag;
75
+}
76
+
77
+void Texture::reset() {
78
+    if (mTextureIds) {
79
+        glDeleteTextures(mTextureLimit, mTextureIds);
80
+        delete [] mTextureIds;
81
+    }
82
+
83
+    mTextureIds = 0x0;
84
+    mTextureCount = 0;
85
+    mTextureLimit = 0;
86
+}
87
+
88
+void Texture::disableMultiTexture() {
89
+    mFlags ^= fUseMultiTexture;
90
+    mTextureId = -1;
91
+    mTextureId2 = -1;
92
+
93
+    glDisable(GL_TEXTURE_2D);
94
+    glActiveTextureARB(GL_TEXTURE0_ARB);
95
+}
96
+
97
+void Texture::useMultiTexture(float aU, float aV, float bU, float bV) {
98
+    if (!(mFlags & fUseMultiTexture))
99
+        return;
100
+
101
+    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, aU, aV);
102
+    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, bU, bV);
103
+}
104
+
105
+void Texture::useMultiTexture(float u, float v) {
106
+    if (!(mFlags & fUseMultiTexture))
107
+        return;
108
+
109
+    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
110
+    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
111
+}
112
+
113
+void Texture::bindMultiTexture(int texture0, int texture1) {
114
+    if (//(int)a == mTextureId && (int)b == mTextureId2 ||
115
+            !mTextureIds ||
116
+            texture0 < 0 || texture0 > (int)mTextureCount ||
117
+            texture1 < 0 || texture1 > (int)mTextureCount) {
118
+        return;
119
+    }
120
+
121
+    mFlags |= fUseMultiTexture;
122
+    mTextureId  = texture0;
123
+    mTextureId2 = texture1;
124
+
125
+    glActiveTextureARB(GL_TEXTURE0_ARB);
126
+    glEnable(GL_TEXTURE_2D);
127
+    glBindTexture(GL_TEXTURE_2D, mTextureIds[texture0]);
128
+
129
+    glActiveTextureARB(GL_TEXTURE1_ARB);
130
+    glEnable(GL_TEXTURE_2D);
131
+    glBindTexture(GL_TEXTURE_2D, mTextureIds[texture1]);
132
+}
133
+
134
+void Texture::setMaxTextureCount(unsigned int n) {
135
+    mTextureLimit = n;
136
+
137
+    mTextureIds = new unsigned int[n];
138
+
139
+    glGenTextures(n, mTextureIds);
140
+}
141
+
142
+int Texture::getTextureCount() {
143
+    return (mTextureCount-1);
144
+}
145
+
146
+int Texture::loadBuffer(unsigned char *image,
147
+        unsigned int width, unsigned int height,
148
+        ColorMode mode, unsigned int bpp) {
149
+    int id;
150
+
151
+    id = loadBufferSlot(image, width, height, mode, bpp, mTextureCount++);
152
+
153
+    if (id < 0)
154
+        return id;
155
+
156
+    return ++id;
157
+}
158
+
159
+void convertARGB32bppToRGBA32bpp(unsigned char *image,
160
+        unsigned int w, unsigned int h) {
161
+    unsigned int i, size = w*h;
162
+    unsigned char swap;
163
+
164
+    for (i = 0; i < size; ++i)
165
+    {
166
+        /* 32-bit ARGB to RGBA */
167
+        swap = image[i*4+3];
168
+        image[i*4]   = image[i*4+1];
169
+        image[i*4+1] = image[i*4+2];
170
+        image[i*4+2] = image[i*4+3];
171
+        image[i*4+3] = swap;
172
+    }
173
+}
174
+
175
+// http://mmmovania.blogspot.de/2011/01/opengl-30-and-above-deprecated-func-and.html
176
+// http://www.g-truc.net/post-0256.html
177
+GLint deprecated_gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data) {
178
+    glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
179
+    glTexImage2D(target, 0, internalFormat, width, height, 0, format, type, data);
180
+    return 0;
181
+}
182
+
183
+int Texture::loadBufferSlot(unsigned char *image,
184
+        unsigned int width, unsigned int height,
185
+        ColorMode mode, unsigned int bpp,
186
+        unsigned int slot) {
187
+    unsigned char bytes;
188
+    unsigned int glcMode;
189
+
190
+
191
+    if (!mTextureIds || slot >= mTextureLimit) {
192
+        printf("Texture::Load> ERROR Not initialized or out of free slots\n");
193
+        return -1000;
194
+    }
195
+
196
+    if (!width || !height || !image) {
197
+        printf("Texture::Load> ERROR Assertion 'image is valid' failed\n");
198
+        return -1;
199
+    }
200
+
201
+    switch (mode) {
202
+        case GREYSCALE:
203
+            if (bpp != 8) {
204
+                printf("Texture::Load> ERROR Unsupported GREYSCALE, %i bpp\n", bpp);
205
+                return -2;
206
+            }
207
+            bytes = 1;
208
+            glcMode = GL_LUMINANCE;
209
+            break;
210
+        case RGB:
211
+            if (bpp != 24) {
212
+                printf("Texture::Load> ERROR Unsupported RGB, %i bpp\n", bpp);
213
+                return -2;
214
+            }
215
+            bytes = 3;
216
+            glcMode = GL_RGB;
217
+            break;
218
+        case ARGB:
219
+            if (bpp == 32) {
220
+                convertARGB32bppToRGBA32bpp(image, width, height);
221
+            } else {
222
+                printf("Texture::Load> ERROR Unsupported ARGB, %i bpp\n", bpp);
223
+                return -2;
224
+            }
225
+            bytes = 4;
226
+            glcMode = GL_RGBA;
227
+            break;
228
+        case RGBA:
229
+            if (bpp != 32) {
230
+                printf("Texture::Load> ERROR Unsupported RGBA, %i bpp\n", bpp);
231
+                return -2;
232
+            }
233
+            bytes = 4;
234
+            glcMode = GL_RGBA;
235
+            break;
236
+    }
237
+
238
+    glClearColor(0.0, 0.0, 0.0, 0.0);
239
+    glEnable(GL_DEPTH_TEST);
240
+    glShadeModel(GL_SMOOTH);
241
+
242
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
243
+
244
+    glBindTexture(GL_TEXTURE_2D, mTextureIds[slot]);
245
+
246
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
247
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
248
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
249
+
250
+    if (mFlags & fUseMipmaps) {
251
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
252
+                GL_NEAREST_MIPMAP_LINEAR);
253
+        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
255
+                GL_LINEAR_MIPMAP_LINEAR);
256
+
257
+        //gluBuild2DMipmaps(GL_TEXTURE_2D, bytes, width, height, glcMode, GL_UNSIGNED_BYTE, image);
258
+        // gluBuild2DMipmaps is deprecated. Replacement by xythobuz
259
+        deprecated_gluBuild2DMipmaps(GL_TEXTURE_2D, bytes, width, height, glcMode, GL_UNSIGNED_BYTE, image);
260
+    } else {
261
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
262
+
263
+        glTexImage2D(GL_TEXTURE_2D, 0, glcMode, width, height, 0,
264
+                glcMode, GL_UNSIGNED_BYTE, image);
265
+    }
266
+
267
+    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
268
+
269
+    return slot;
270
+}
271
+
272
+void Texture::bindTextureId(unsigned int n) {
273
+    if ((int)n == mTextureId || !mTextureIds || n > mTextureCount) {
274
+        return;
275
+    }
276
+
277
+    mTextureId = n;
278
+
279
+    glEnable(GL_TEXTURE_2D);
280
+    //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
281
+
282
+    glBindTexture(GL_TEXTURE_2D, mTextureIds[n]);
283
+}
284
+
285
+void Texture::glScreenShot(char *base, unsigned int width, unsigned int height) {
286
+    FILE *f;
287
+    int sz = width * height;
288
+    unsigned char *image = new unsigned char[sz * 3];
289
+    char filename[1024];
290
+    static int count = 0;
291
+    bool done = false;
292
+
293
+    if (!image || !width || !height) {
294
+        if (image)
295
+            delete [] image;
296
+
297
+        printf("glScreenShot> ERROR: Couldn't allocate image!\n");
298
+        return;
299
+    }
300
+
301
+    // Don't overwrite files
302
+    while (!done) {
303
+        snprintf(filename, 1024, "%s-%04i.tga", base, count++);
304
+
305
+        f = fopen(filename, "rb");
306
+
307
+        if (f)
308
+            fclose(f);
309
+        else
310
+            done = true;
311
+    }
312
+
313
+    // Capture frame buffer
314
+    glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, image);
315
+
316
+    tgaSaveFilename(image, width, height, 0, "%s", filename);
317
+    printf("Took screenshot '%s'.\n", filename);
318
+
319
+    delete [] image;
320
+}
321
+
322
+int Texture::loadTGA(const char *filename) {
323
+    FILE *f;
324
+    unsigned char *image = NULL;
325
+    unsigned char *image2 = NULL;
326
+    unsigned int w, h;
327
+    char type;
328
+    int id = -1;
329
+
330
+    f = fopen(filename, "rb");
331
+
332
+    if (!f) {
333
+        perror("Couldn't load file");
334
+    } else if (!tgaCheck(f)) {
335
+        tgaLoad(f, &image, &w, &h, &type);
336
+
337
+        type += 2;
338
+
339
+        image2 = scaleBuffer(image, w, h, (type == 4) ? 4 : 3);
340
+
341
+        if (image2) {
342
+            image = image2;
343
+            w = h = 256;
344
+        }
345
+
346
+        if (image) {
347
+            id = loadBuffer(image, w, h,
348
+                    (type == 4) ? RGBA : RGB,
349
+                    (type == 4) ? 32 : 24);
350
+
351
+            delete [] image;
352
+        }
353
+
354
+        fclose(f);
355
+    }
356
+
357
+    if (id == -1) {
358
+        printf("Texture::loadTGA> ERROR: Failed to load '%s'\n", filename);
359
+    }
360
+
361
+    return id;
362
+}
363
+
364
+int Texture::nextPower(int seed) {
365
+    int i;
366
+    for (i = 1; i < seed; i *= 2);
367
+    return i;
368
+}
369
+
370
+/* This code based off on gluScaleImage()  */
371
+unsigned char *Texture::scaleBuffer(unsigned char *image,
372
+        int width,  int height, int components) {
373
+    int i, j, k;
374
+    float* tempin;
375
+    float* tempout;
376
+    float sx, sy;
377
+    //int components = 3;
378
+    unsigned char *timage;
379
+    int original_height = height;
380
+    int original_width = width;
381
+
382
+    if (!image || !width || !height)
383
+        return NULL;
384
+
385
+    height = nextPower(height);
386
+    width = nextPower(width);
387
+
388
+    if (height > 256)
389
+        height = 256;
390
+
391
+    if (width > 256)
392
+        width = 256;
393
+
394
+    // Check to see if scaling is needed
395
+    if (height == original_height && width == original_width)
396
+        return NULL;
397
+
398
+    //printf("%i\n", components);
399
+
400
+    timage = new unsigned char[height * width * components];
401
+    tempin = new float[original_width * original_height * components * sizeof(float)];
402
+    tempout = new float[width * height * components * sizeof(float)];
403
+
404
+    // Copy user data to float format.
405
+    for (i = 0; i < original_height * original_width * components; ++i) {
406
+        tempin[i] = (float)image[i];
407
+    }
408
+
409
+    // Determine which filter to use by checking ratios.
410
+    if (width > 1) {
411
+        sx = (float)(original_width - 1) / (float)(width - 1);
412
+    } else {
413
+        sx = (float)(original_width - 1);
414
+    }
415
+
416
+    if (height > 1) {
417
+        sy = (float)(original_height - 1) / (float) (height - 1);
418
+    } else {
419
+        sy = (float)(original_height - 1);
420
+    }
421
+
422
+    if (sx < 1.0 && sy < 1.0) {
423
+        /* Magnify both width and height:  use weighted sample of 4 pixels */
424
+        int i0, i1, j0, j1;
425
+        float alpha, beta;
426
+        float* src00;
427
+        float* src01;
428
+        float* src10;
429
+        float* src11;
430
+        float s1, s2;
431
+        float* dst;
432
+
433
+        for (i = 0; i < height; ++i) {
434
+            i0 = (int)(i * sy);
435
+            i1 = i0 + 1;
436
+
437
+            if (i1 >= original_height) {
438
+                i1 = original_height - 1;
439
+            }
440
+
441
+            alpha = i * sy - i0;
442
+
443
+            for (j = 0; j < width; ++j) {
444
+                j0 = (int) (j * sx);
445
+                j1 = j0 + 1;
446
+
447
+                if (j1 >= original_width) {
448
+                    j1 = original_width - 1;
449
+                }
450
+
451
+                beta = j * sx - j0;
452
+
453
+                /* Compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
454
+                src00 = tempin + (i0 * original_width + j0) * components;
455
+                src01 = tempin + (i0 * original_width + j1) * components;
456
+                src10 = tempin + (i1 * original_width + j0) * components;
457
+                src11 = tempin + (i1 * original_width + j1) * components;
458
+
459
+                dst = tempout + (i * width + j) * components;
460
+
461
+                for (k = 0; k < components; ++k) {
462
+                    s1 = *src00++ * (1.0f - beta) + *src01++ * beta;
463
+                    s2 = *src10++ * (1.0f - beta) + *src11++ * beta;
464
+                    *dst++ = s1 * (1.0f - alpha) + s2 * alpha;
465
+                }
466
+            }
467
+        }
468
+    } else {
469
+        /* Shrink width and/or height:  use an unweighted box filter */
470
+        int i0, i1;
471
+        int j0, j1;
472
+        int ii, jj;
473
+        float sum;
474
+        float* dst;
475
+
476
+        for (i = 0; i < height; ++i) {
477
+            i0 = (int) (i * sy);
478
+            i1 = i0 + 1;
479
+
480
+            if (i1 >= original_height) {
481
+                i1 = original_height - 1;
482
+            }
483
+
484
+            for (j = 0; j < width; ++j) {
485
+                j0 = (int) (j * sx);
486
+                j1 = j0 + 1;
487
+
488
+                if (j1 >= original_width) {
489
+                    j1 = original_width - 1;
490
+                }
491
+
492
+                dst = tempout + (i * width + j) * components;
493
+
494
+                /* Compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
495
+                for (k = 0; k < components; ++k) {
496
+                    sum = 0.0;
497
+
498
+                    for (ii = i0; ii <= i1; ++ii) {
499
+                        for (jj = j0; jj <= j1; ++jj) {
500
+                            sum += *(tempin + (ii * original_width + jj)
501
+                                    * components + k);
502
+                        }
503
+                    }
504
+
505
+                    sum /= ( j1 - j0 + 1 ) * ( i1 - i0 + 1 );
506
+                    *dst++ = sum;
507
+                }
508
+            }
509
+        }
510
+    }
511
+
512
+    // Copy to our results.
513
+    for( i = 0; i < height * width * components; ++i) {
514
+        timage[i] = (unsigned char)tempout[i];
515
+    }
516
+
517
+    // Delete our temp buffers.
518
+    delete[] tempin;
519
+    delete[] tempout;
520
+    delete[] image;
521
+
522
+    return timage;
523
+}
524
+

Laddar…
Avbryt
Spara