Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

cmap_8bits.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "constants.h" /* XXX just to get MAXLEN */
#include "cmap_8bits.h"


Cmap8_t *
Cmap8_new()
{
  int i;
  Cmap8_t *cmap = xcalloc(1, sizeof(Cmap8_t));

  cmap->name = strdup("grey");
  cmap->id = -1;

  for (i = 0; i < 256; i++)
    cmap->colors[i].col.r =
      cmap->colors[i].col.g =
      cmap->colors[i].col.b =
      cmap->colors[i].col.a = i;

  cmap->min = 0;
  cmap->max = 255;

  return cmap;
}


void
Cmap8_delete(Cmap8_t *cmap)
{
  xfree(cmap->name);
  if (cmap->filename != NULL)
    xfree(cmap->filename);
  xfree(cmap);
}


int
Cmap8_load(Cmap8_t *cmap, const char *filename)
{
  FILE *stream;
  int i;
  char ccmap[MAXLEN];

  /* check if we have a binary version of the colormap */
  /* of course this is ugly, we should stat() the file, or whatever */
  /* well... */
  memset(ccmap, '\0', MAXLEN*sizeof(char));
  snprintf(ccmap, (MAXLEN-1)*sizeof(char), "%s.bin", filename);
  if (Cmap8_load_binary(cmap, ccmap) == 0) {
    /* printf("[i] Succeeded loading binary version of %s from %s\n", filename, ccmap); */
    cmap->filename = strdup(filename);
    return 0;
  }
  
  stream = fopen(filename, "r");
  if (stream == NULL)
    xperror("fopen");

  /* TODO: fscanf() verfsion */
  for (i = 0; i < 256; ) {
    int r = -1, g = -1, b = -1;
    int ret;
    char prout[1024];
    char *strret = NULL;

    /* try to read an RGB */
    strret = fgets(prout, 1024, stream);
    if (strret == NULL) {
      fclose(stream);
      return -1;
    }

    ret = sscanf(prout, "%d %d %d", &r, &g, &b);

    if (EOF == ret) {
      fclose(stream);
      return -1;
    }

    if (ret == 3) {
      /* success */
      cmap->colors[i].col.r = r;
      cmap->colors[i].col.g = g;
      cmap->colors[i].col.b = b;
      cmap->colors[i].col.a = 255; /* alpha channel */
      i++;
    }
  }
      
  fclose(stream);
  cmap->filename = strdup(filename);

  return 0;
}


void
Cmap8_copy(const Cmap8_t *from, Cmap8_t *to)
{
  u_short i;

  assert(from != NULL);
  assert(to != NULL);

  if (to->name != NULL)
    xfree(to->name);

  assert(from->name != NULL);
  to->name = strdup(from->name);

  to->id = from->id;

  for (i = 0; i < 256; i++)
    to->colors[i] = from->colors[i];

  to->min = from->min;
  to->max = from->max;
}


void
Cmap8_findMinMax(Cmap8_t *cmap)
{
  int i;
  short min = 256;
  short max = -1;
      
  for (i = 0; i < 256; i++) {
    long sum;
    sum =  cmap->colors[i].col.r * 0.299;
    sum += cmap->colors[i].col.g * 0.587;
    sum += cmap->colors[i].col.b * 0.114;

    if (sum < min) {
      min = sum;
      cmap->min = i;
    }
            
    /* >= is a trick so that we get as high
     * as possible in the indices */
    if (sum >= max) {
      max = sum;
      cmap->max = i;
    }
  }
}


int
Cmap8_load_binary(Cmap8_t *cmap, const char *filename)
{
  int fd;
  int r;
  size_t res;

  fd = open(filename, O_RDONLY);
  if (fd == -1)
    return -1;

#define BTR (256*sizeof(rgba_t)) /* Bytes To Read */
  res = read(fd, (void *)cmap->colors, BTR);
  if (res != BTR) {
    printf("[!] short read in Cmap8_load_binary '%s'\n", filename);
    r = close(fd);
    if (r == -1)
      xperror("close");
    return -1;
  }

  r = close(fd);
  if (r == -1)
    xperror("close");

  cmap->compressed = 1;

  return 0;
}


int
Cmap8_save(Cmap8_t *cmap)
{
  FILE *stream;
  char filename[MAXLEN];
  size_t res;

  /* don't save if we loaded from a binary version */
  if (cmap->compressed) {
    /* printf("[!] we were loaded from a binary version, faking save\n"); */
    return 0;
  }

  /* so, we take the filename, and append a ".bin" to it */
  memset(filename, '\0', MAXLEN*sizeof(char));
  snprintf(filename, (MAXLEN-1)*sizeof(char), "%s.bin", cmap->filename);

  stream = fopen(filename, "w");
  if (stream == NULL) {
    printf("[!] failed to open '%s' for writing :(\n", filename);
    return -1;
  }

  res = fwrite((const void *)cmap->colors, sizeof(rgba_t), 256, stream);
  if (res != 256) {
    printf("[!] short write in Cmap8_save\n");
    fclose(stream);
    return -1;
  } else
    fclose(stream);

  cmap->compressed = 1; /* to NOT save it again on disk if calling Cmap8_save */

  return 0;
}


void
Cmap8_shift_left(Cmap8_t *cmap)
{
  int i;
  rgba_t col0 = cmap->colors[0];

  for (i = 0; i < 255; i++)
    cmap->colors[i] = cmap->colors[i+1];
  cmap->colors[255] = col0;
}

Generated by  Doxygen 1.6.0   Back to index