cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

palette.c (3738B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "config.h"
     21
     22#include "guacamole/mem.h"
     23#include "palette.h"
     24
     25#include <cairo/cairo.h>
     26
     27#include <stdint.h>
     28#include <stdio.h>
     29#include <stdlib.h>
     30#include <string.h>
     31
     32guac_palette* guac_palette_alloc(cairo_surface_t* surface) {
     33
     34    int x, y;
     35
     36    int width = cairo_image_surface_get_width(surface);
     37    int height = cairo_image_surface_get_height(surface);
     38    int stride = cairo_image_surface_get_stride(surface);
     39    unsigned char* data = cairo_image_surface_get_data(surface);
     40
     41    /* Allocate palette */
     42    guac_palette* palette = (guac_palette*) guac_mem_zalloc(sizeof(guac_palette));
     43
     44    for (y=0; y<height; y++) {
     45        for (x=0; x<width; x++) {
     46
     47            /* Get pixel color */
     48            int color = ((uint32_t*) data)[x] & 0xFFFFFF;
     49
     50            /* Calculate hash code */
     51            int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF);
     52
     53            guac_palette_entry* entry;
     54
     55            /* Search for open palette entry */
     56            for (;;) {
     57                
     58                entry = &(palette->entries[hash]);
     59
     60                /* If we've found a free space, use it */
     61                if (entry->index == 0) {
     62
     63                    png_color* c;
     64
     65                    /* Stop if already at capacity */
     66                    if (palette->size == 256) {
     67                        guac_palette_free(palette);
     68                        return NULL;
     69                    }
     70
     71                    /* Store in palette */
     72                    c = &(palette->colors[palette->size]);
     73                    c->blue  = (color      ) & 0xFF;
     74                    c->green = (color >> 8 ) & 0xFF;
     75                    c->red   = (color >> 16) & 0xFF;
     76
     77                    /* Add color to map */
     78                    entry->index = ++palette->size;
     79                    entry->color = color;
     80
     81                    break;
     82
     83                }
     84
     85                /* Otherwise, if already stored here, done */
     86                if (entry->color == color)
     87                    break;
     88
     89                /* Otherwise, collision. Move on to another bucket */
     90                hash = (hash+1) & 0xFFF;
     91
     92            }
     93        }
     94
     95        /* Advance to next data row */
     96        data += stride;
     97
     98    }
     99
    100    return palette;
    101
    102}
    103
    104int guac_palette_find(guac_palette* palette, int color) {
    105
    106    /* Calculate hash code */
    107    int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF);
    108
    109    guac_palette_entry* entry;
    110
    111    /* Search for palette entry */
    112    for (;;) {
    113        
    114        entry = &(palette->entries[hash]);
    115
    116        /* If we've found a free space, color not stored. */
    117        if (entry->index == 0)
    118            return -1;
    119
    120        /* Otherwise, if color indeed stored here, done */
    121        if (entry->color == color)
    122            return entry->index - 1;
    123
    124        /* Otherwise, collision. Move on to another bucket */
    125        hash = (hash+1) & 0xFFF;
    126
    127    }
    128
    129}
    130
    131void guac_palette_free(guac_palette* palette) {
    132    guac_mem_free(palette);
    133}
    134