source: abuse/trunk/src/imlib/filter.cpp @ 682

Last change on this file since 682 was 682, checked in by Sam Hocevar, 9 years ago

core: rename vec2i to ivec2 and update matrix.h from Lol Engine.

File size: 4.1 KB
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[494]4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
[56]5 *
6 *  This software was released into the Public Domain. As with most public
[555]7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
[56]9 */
10
[555]11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
[56]14
[512]15#include "common.h"
16
[481]17#include "image.h"
18#include "filter.h"
[2]19
[579]20Filter::Filter(int colors)
[2]21{
[579]22    CONDITION(colors >= 0 && colors <= 256, "bad colors value");
23    m_size = colors;
24    m_table = (uint8_t *)malloc(m_size);
25    memset(m_table, 0, m_size * sizeof(*m_table));
[2]26}
27
[579]28// Creates a conversion filter from one palette to another
29Filter::Filter(palette *from, palette *to)
[2]30{
[579]31    m_size = Max(from->pal_size(), to->pal_size());
32    m_table = (uint8_t *)malloc(m_size);
[2]33
[579]34    uint8_t *dst = m_table;
35    uint8_t *src = (uint8_t *)from->addr();
36    int dk = to->darkest(1);
[2]37
[579]38    for (int i = 0; i < m_size; i++)
39    {
40       int r = *src++;
41       int g = *src++;
42       int b = *src++;
43       int color = to->find_closest(r, g, b);
[2]44
[579]45       // Make sure non-blacks don't get remapped to the transparency
46       if ((r || g || b) && to->red(color) == 0
47            && to->green(color) == 0 && to->blue(color) == 0)
48           color = dk;
[2]49
[579]50       *dst++ = color;
51    }
[2]52}
53
[579]54Filter::~Filter()
[2]55{
[579]56    free(m_table);
[2]57}
58
[579]59void Filter::Set(int color_num, int change_to)
[2]60{
[579]61    CONDITION(color_num >= 0 && color_num < m_size, "Bad colors_num");
62    m_table[color_num] = change_to;
[2]63}
64
[579]65void Filter::Apply(image *im)
[2]66{
[579]67    im->Lock();
68    uint8_t *dst = im->scan_line(0);
69    int npixels = im->Size().x * im->Size().y;
70    while (npixels--)
[2]71    {
[579]72        CONDITION(*dst < m_size, "not enough filter colors");
73        *dst = m_table[*dst];
74        dst++;
[2]75    }
[579]76    im->Unlock();
[2]77}
78
[579]79/* This is only ever used in the editor, when showing the toolbar. It
80 * does not look like it's very useful. */
[682]81void Filter::PutImage(image *screen, image *im, ivec2 pos)
[2]82{
[682]83    ivec2 aa = ivec2(0), bb = im->Size(), caa, cbb;
[665]84    screen->GetClip(caa, cbb);
[2]85
[579]86    // See if the image gets clipped off the screen
[665]87    if (!(pos < cbb && pos + (bb - aa) > caa))
[115]88        return;
[2]89
[665]90    aa += Max(caa - pos, 0);
91    pos = Max(pos, caa);
92    bb = Min(bb, cbb - pos + aa);
[2]93
[665]94    if (!(aa < bb))
[115]95        return;
[2]96
[682]97    ivec2 span = bb - aa;
[2]98
[670]99    screen->AddDirty(pos, pos + span);
[2]100
[515]101    screen->Lock();
102    im->Lock();
[2]103
[665]104    for (int j = 0; j < span.y; j++)
[115]105    {
[665]106        uint8_t *src = im->scan_line(aa.y + j) + aa.x;
107        uint8_t *dst = screen->scan_line(pos.y + j) + pos.x;
[579]108
[665]109        for (int i = 0; i < span.x; i++, src++, dst++)
110            if (*src)
111                *dst = m_table[*src];
[115]112    }
[2]113
[515]114    im->Unlock();
115    screen->Unlock();
[115]116}
[2]117
[579]118ColorFilter::ColorFilter(palette *pal, int color_bits)
119{
120    int max = pal->pal_size();
121    int mul = 1 << (8 - color_bits);
122    m_size = 1 << color_bits;
123    m_table = (uint8_t *)malloc(m_size * m_size * m_size);
124
125    /* For each colour in the RGB cube, find the nearest palette element. */
126    for (int r = 0; r < m_size; r++)
127    for (int g = 0; g < m_size; g++)
128    for (int b = 0; b < m_size; b++)
129    {
130        int best = 256 * 256 * 3;
131        int color = 0;
132        uint8_t *pp = (uint8_t *)pal->addr();
133
134        for (int i = 0; i < max; i++)
135        {
136            int rd = *pp++ - r * mul,
137                gd = *pp++ - g * mul,
138                bd = *pp++ - b * mul;
139
140            int dist = rd * rd + bd * bd + gd * gd;
141            if (dist < best)
142            {
143                best = dist;
144                color = i;
145            }
146        }
147        m_table[(r * m_size + g) * m_size + b] = color;
148    }
149}
150
151ColorFilter::ColorFilter(spec_entry *e, bFILE *fp)
152{
153    fp->seek(e->offset, 0);
154    m_size = fp->read_uint16();
155    m_table = (uint8_t *)malloc(m_size * m_size * m_size);
156    fp->read(m_table, m_size * m_size * m_size);
157}
158
159ColorFilter::~ColorFilter()
160{
161    free(m_table);
162}
163
164size_t ColorFilter::DiskUsage()
165{
166    return sizeof(uint16_t) + m_size * m_size * m_size;
167}
168
169int ColorFilter::Write(bFILE *fp)
170{
171    fp->write_uint16(m_size);
172    int bytes = m_size * m_size * m_size;
173    return fp->write(m_table, bytes) == bytes;
174}
175
Note: See TracBrowser for help on using the repository browser.