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