~ubuntu-branches/ubuntu/hardy/videolink/hardy

« back to all changes in this revision

Viewing changes to pixbufs.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings
  • Date: 2006-10-15 02:05:46 UTC
  • Revision ID: james.westby@ubuntu.com-20061015020546-0t2uoscwlmwyrp5q
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
 
2
// See the file "COPYING" for licence details.
 
3
 
 
4
#include "pixbufs.hpp"
 
5
 
 
6
#include <cassert>
 
7
 
 
8
#include <gdkmm/pixbuf.h>
 
9
 
 
10
#include "auto_array.hpp"
 
11
#include "jquant2.h"
 
12
 
 
13
// Find pixel differences between an "old" and "new" RGB Pixbuf
 
14
// (or RGBA, but the alpha component will be ignored) and copy the
 
15
// differing pixels from the new one to a third RGBA Pixbuf at the
 
16
// specified offset with full opacity.
 
17
// The width and height of the new Pixbufs must be equal and match
 
18
// the specified dimensions.  The width and height of the old and
 
19
// third Pixbuf must be large enough to store a rectangle of
 
20
// those dimensions at the specified offset.
 
21
void diff_rgb_pixbufs(Glib::RefPtr<Gdk::Pixbuf> old_buf,
 
22
                      Glib::RefPtr<Gdk::Pixbuf> new_buf,
 
23
                      Glib::RefPtr<Gdk::Pixbuf> diff_buf,
 
24
                      int offset_x, int offset_y,
 
25
                      int width, int height)
 
26
{
 
27
    assert(old_buf->get_colorspace() == Gdk::COLORSPACE_RGB);
 
28
    assert(new_buf->get_colorspace() == Gdk::COLORSPACE_RGB);
 
29
    assert(diff_buf->get_colorspace() == Gdk::COLORSPACE_RGB
 
30
           && diff_buf->get_has_alpha());
 
31
    int old_bpr = old_buf->get_rowstride();
 
32
    int old_bpp = old_buf->get_n_channels();
 
33
    assert(old_bpp >= 3);
 
34
    assert(old_buf->get_width() >= offset_x + width);
 
35
    assert(old_buf->get_height() >= offset_y + height);
 
36
    int new_bpr = new_buf->get_rowstride();
 
37
    int new_bpp = new_buf->get_n_channels();
 
38
    assert(new_bpp >= 3);
 
39
    assert(new_buf->get_width() == width);
 
40
    assert(new_buf->get_height() == height);
 
41
    int diff_bpr = diff_buf->get_rowstride();
 
42
    int diff_bpp = diff_buf->get_n_channels();
 
43
    assert(diff_bpp == 4);
 
44
    assert(diff_buf->get_width() >= offset_x + width);
 
45
    assert(diff_buf->get_height() >= offset_y + height);
 
46
 
 
47
    const guint8 * old_p = (old_buf->get_pixels()
 
48
                            + old_bpr * offset_y
 
49
                            + old_bpp * offset_x);
 
50
    const guint8 * new_p = new_buf->get_pixels();
 
51
    guint8 * diff_p = (diff_buf->get_pixels()
 
52
                       + diff_bpr * offset_y
 
53
                       + diff_bpp * offset_x);
 
54
 
 
55
    for (int y = 0; y != height; ++y)
 
56
    {
 
57
        for (int x = 0; x != width; ++x)
 
58
        {
 
59
            if (old_p[0] != new_p[0]
 
60
                || old_p[1] != new_p[1]
 
61
                || old_p[2] != new_p[2])
 
62
            {
 
63
                diff_p[0] = new_p[0];
 
64
                diff_p[1] = new_p[1];
 
65
                diff_p[2] = new_p[2];
 
66
                diff_p[3] = 0xFF; // fully opaque
 
67
            }
 
68
            old_p += old_bpp;
 
69
            new_p += new_bpp;
 
70
            diff_p += diff_bpp;
 
71
        }
 
72
        old_p += old_bpr - old_bpp * width;
 
73
        new_p += new_bpr - new_bpp * width;
 
74
        diff_p += diff_bpr - diff_bpp * width;
 
75
    }
 
76
}
 
77
 
 
78
// Quantise an RGBA Pixbuf to the specified number of colours, including
 
79
// one transparent colour.  Currently uses Floyd-Steinberg dithering.
 
80
void quantise_rgba_pixbuf(Glib::RefPtr<Gdk::Pixbuf> buf, int n_colours)
 
81
{
 
82
    assert(buf->get_colorspace() == Gdk::COLORSPACE_RGB
 
83
           && buf->get_has_alpha());
 
84
    int bpr = buf->get_rowstride();
 
85
    assert(buf->get_n_channels() == 4);
 
86
    int width = buf->get_width();
 
87
    int height = buf->get_height();
 
88
 
 
89
    unsigned char * buf_p = buf->get_pixels();
 
90
    auto_array<unsigned char *> rows(new unsigned char *[height]);
 
91
    for (int y = 0; y != height; ++y)
 
92
        rows[y] = &buf_p[y * bpr];
 
93
    auto_array<unsigned char> quant_buf_p(
 
94
        new unsigned char[width * height]);
 
95
    auto_array<unsigned char *> quant_rows(
 
96
        new unsigned char *[height]);
 
97
    for (int y = 0; y != height; ++y)
 
98
        quant_rows[y] = &quant_buf_p[y * width];
 
99
    auto_array<unsigned int> colours(new unsigned int[n_colours]);
 
100
 
 
101
    quantize(rows.get(), quant_rows.get(), width, height,
 
102
             JDITHER_FS, n_colours, colours.get());
 
103
 
 
104
    // Pixbuf doesn't support quantised images, so convert back to RGBA.
 
105
    for (int y = 0; y != height; ++y)
 
106
        for (int x = 0; x != width; ++x)
 
107
        {
 
108
            unsigned int colour = colours[quant_rows[y][x]];
 
109
            rows[y][4*x]   = colour;
 
110
            rows[y][4*x+1] = colour >> 8;
 
111
            rows[y][4*x+2] = colour >> 16;
 
112
            rows[y][4*x+3] = colour >> 24;
 
113
        }
 
114
}