Plan 9 from Bell Labs’s /usr/web/sources/contrib/pac/sys/src/ape/cmd/img/refocit-2.0.0/image.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * Written 2003 Lukas Kunc <Lukas.Kunc@seznam.cz>
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "xmalloc.h"
#include "image.h"

#define LINE_LEN_BORDER_PPM 56
#define LINE_LEN_BORDER_PGM 64

//++pac
#define EINVAL 1

typedef enum {
  PBM_ASCII  = 1,
  PGM_ASCII  = 2,
  PPM_ASCII  = 3,
  PBM_BINARY = 4,
  PGM_BINARY = 5,
  PPM_BINARY = 6,
  PNM_UNKNOWN
} PNMType;

image_t* image_create(image_t* image, int x, int y)
{
  image->x = x;
  image->y = y;
  image->data = (real_t*)xmalloc(sizeof(real_t) * x * y);
  return image;
}

image_t* image_create_copyparam(image_t* image, image_t* src)
{
  image->x = src->x;
  image->y = src->y;
  image->data = (real_t*)xmalloc(sizeof(real_t) * image->x * image->y);
  return image;
}

void image_init(image_t* image)
{
  image->data = NULL;
}

void image_destroy(image_t* image)
{
  xfree(image->data);
}

image_t* image_convolve_mirror(image_t* dst, image_t* src, convmask_t* filter)
{
  int i, j, k, l, r;
  real_t value;

  r = filter->radius;
  for (i = 0; i < src->x; i++)
  {
    for (j = 0; j < src->y; j++)
    {
      value = R(0.0);
      for (k = -r; k <= r; k++)
      {
	for (l = -r; l <= r; l++)
	{
	  value += convmask_get(filter, k,l) * image_get_mirror(src, i-k, j-l);
	}
      }
      image_set(dst, i, j, value);
    }
  }
  return dst;
}
	  
image_t* image_convolve_period(image_t* dst, image_t* src, convmask_t* filter)
{
  int i, j, k, l, r;
  real_t value;

  r = filter->radius;
  for (i = 0; i < src->x; i++)
  {
    for (j = 0; j < src->y; j++)
    {
      value = R(0.0);
      for (k = -r; k <= r; k++)
      {
	for (l = -r; l <= r; l++)
	{
	  value += convmask_get(filter, k,l) * image_get_period(src, i-k, j-l);
	}
      }
      image_set(dst, i, j, value);
    }
  }
  return dst;
}

int image_load_pnm_file(image_t* imageR, image_t* imageG, image_t* imageB, int* bpp, FILE* file)
{
  char buff[2];
  unsigned char bytesRGB[3];
  int c;
  int i, x, y, Y, valueR, valueG, valueB;
  unsigned char byte;
  PNMType type;
  real_t scale;

  if (imageR) image_init(imageR);
  if (imageG) image_init(imageG);
  if (imageB) image_init(imageB);

  if (fread(buff, sizeof(buff), 1, file) != 1)
  {
    return -1;
  }

  if (buff[0] != 'P')
  {
    errno = EINVAL;
    return -1;
  }

  switch (buff[1])
  {
    case '1':
      /* PBM, ascii */
      type = PBM_ASCII;
      break;
    case '2':
      /* PGM, ascii */
      type = PGM_ASCII;
      break;
    case '3':
      /* PPM, ascii */
      type = PPM_ASCII;
      break;
    case '4':
      /* PBM, binary */
      type = PBM_BINARY;
      break;
    case '5':
      /* PGM binary */
      type = PGM_BINARY;
      break;
    case '6':
      /* PPM, binary */
      type = PPM_BINARY;
      break;
    default:
      /* Unsupported */
      type = PNM_UNKNOWN;
      break;
  }
  if (type == PNM_UNKNOWN)
  {
    errno = EINVAL;
    return -1;
  }

  do
  {
    c = getc(file);
  }
  while (c == '\t' || c == ' ');
  if (c == '\r') c = getc(file);
  if (c != '\n')
  {
    errno = EINVAL;
    return -1;
  }
  c = getc(file);
  while (c == '#')
  {
    while (((c = getc(file)) != '\n') && (c != EOF));
    if (c != EOF) c = getc(file);
  }

  if (c == EOF)
  {
    errno = EINVAL;
    return -1;
  }
  ungetc(c, file);

  if (fscanf(file, "%d %d %d", &x, &y, &c) != 3)
  {
    errno = EINVAL;
    return -1;
  }
  scale = R(255.0) / (real_t)c;
  c = getc(file);
  if (c == '\r') c = getc(file);
  if (c != '\n')
  {
    errno = EINVAL;
    return -1;
  }

  Y = y;

  switch (type)
  {
    case PGM_ASCII:
      if (bpp) *bpp = 1;
      image_create(imageR, x, y);
      y = 0; i = 0;
      while (y < Y && fscanf(file, "%d", &valueR) == 1) {
        image_set(imageR, i, y, scale * (real_t)valueR);
        i++;
        if (i >= x) {
          i = 0;
          y++;
        }
      }
      break;
    case PGM_BINARY:
      if (bpp) *bpp = 1;
      image_create(imageR, x, y);
      y = 0; i = 0;
      while (y < Y && fread(&byte, sizeof(byte), 1, file) == 1) {
        image_set(imageR, i, y, scale * (real_t)byte);
        i++;
        if (i >= x) {
          i = 0;
          y++;
        }
      }
      break;
    case PPM_ASCII:
      if (bpp) *bpp = 3;
      image_create(imageR, x, y);
      if (!imageG || !imageR)
      {
        errno = EINVAL;
        return -1;
      }
      image_create(imageG, x, y);
      image_create(imageB, x, y);
      y = 0; i = 0;
      while (y < Y && fscanf(file, "%d %d %d", &valueR, &valueG, &valueB) == 3) {
        image_set(imageR, i, y, scale * (real_t)valueR);
        image_set(imageG, i, y, scale * (real_t)valueG);
        image_set(imageB, i, y, scale * (real_t)valueB);
        i++;
        if (i >= x) {
          i = 0;
          y++;
        }
      }
      break;
    case PPM_BINARY:
      if (bpp) *bpp = 3;
      image_create(imageR, x, y);
      if (!imageG || !imageR)
      {
        errno = EINVAL;
        return -1;
      }
      image_create(imageG, x, y);
      image_create(imageB, x, y);
      y = 0; i = 0;
      while (y < Y && fread(&bytesRGB, sizeof(bytesRGB), 1, file) == 1) {
        image_set(imageR, i, y, scale * (real_t)bytesRGB[0]);
        image_set(imageG, i, y, scale * (real_t)bytesRGB[1]);
        image_set(imageB, i, y, scale * (real_t)bytesRGB[2]);
        i++;
        if (i >= x) {
          i = 0;
          y++;
        }
      }
      break;
    default:
      errno = EINVAL;
      return -1;
  }

  return 0;
}


int image_save_pnm_file(image_t* imageR, image_t* imageG, image_t* imageB, int binary, FILE* file)
{
  int type;
  int i, j, rv, R, G, B;
  unsigned char c;
  int chars_cnt;

  if (imageG && imageG->data && imageB && imageB->data) type = 3;
  else type = 2;
  if (binary) type+=3;

  if (fprintf(file, "P%d\n# Deblur output\n%d %d\n255", type, imageR->x, imageR->y) < 0) return -1;

  switch (type)
  {
    case PGM_ASCII:
      chars_cnt = LINE_LEN_BORDER_PGM + 1;
      for (j = 0; j < imageR->y; j++)
      {
        for (i = 0; i < imageR->x; i++)
        {
          R = (int)(image_get(imageR, i, j) + R(0.5));
          if (chars_cnt > LINE_LEN_BORDER_PGM)
          {
            if (fprintf(file, "\n") < 0) return -1;
            chars_cnt = 0;
            rv = fprintf(file, "%d", R);
          }
          else
          {
            rv = fprintf(file, " %d", R);
          }
          if (rv < 0) return -1;
          chars_cnt += rv;
        }
      }
      break;
    case PGM_BINARY:
      if (fprintf(file, "\n") < 0) return -1;
      for (j = 0; j < imageR->y; j++)
      {
        for (i = 0; i < imageR->x; i++)
        {
          c = (unsigned char)(image_get(imageR, i, j) + R(0.5));
          if (fwrite(&c, sizeof(c), 1, file) != 1) return -1;
        }
      }
      break;
    case PPM_ASCII:
      chars_cnt = LINE_LEN_BORDER_PPM + 1;
      for (j = 0; j < imageR->y; j++)
      {
        for (i = 0; i < imageR->x; i++)
        {
          R = (int)(image_get(imageR, i, j) + R(0.5));
          G = (int)(image_get(imageG, i, j) + R(0.5));
          B = (int)(image_get(imageB, i, j) + R(0.5));
          if (chars_cnt > LINE_LEN_BORDER_PPM)
          {
            if (fprintf(file, "\n") < 0) return -1;
            chars_cnt = 0;
            rv = fprintf(file, "%d %d %d", R, G, B);
          }
          else
          {
            rv = fprintf(file, " %d %d %d", R, G, B);
          }
          if (rv < 0) return -1;
          chars_cnt += rv;
        }
      }
      break;
    case PPM_BINARY:
      if (fprintf(file, "\n") < 0) return -1;
      for (j = 0; j < imageR->y; j++)
      {
        for (i = 0; i < imageR->x; i++)
        {
          c = (unsigned char)(image_get(imageR, i, j) + R(0.5));
          if (fwrite(&c, sizeof(c), 1, file) != 1) return -1;
          c = (unsigned char)(image_get(imageG, i, j) + R(0.5));
          if (fwrite(&c, sizeof(c), 1, file) != 1) return -1;
          c = (unsigned char)(image_get(imageB, i, j) + R(0.5));
          if (fwrite(&c, sizeof(c), 1, file) != 1) return -1;
        }
      }
      break;
    default:
      errno = EINVAL;
      return -1;
  }

  return 0;
}

int image_save_pnm(image_t* imageR, image_t* imageG, image_t* imageB, int binary, const char* name)
{
  int retval;
  FILE *file;
  file = fopen(name, "wb");
  if (file) {
    retval = image_save_pnm_file(imageR, imageG, imageB, binary, file);
    fclose(file);
  }
  else {
	retval = -1;
  }
  return retval;
}

int image_load_pnm(image_t* imageR, image_t* imageG, image_t* imageB, int* bpp, const char* name)
{
  FILE *file;
  int retval;
  file = fopen(name, "rb");
  if (file) {
    retval = image_load_pnm_file(imageR, imageG, imageB, bpp, file);
    fclose(file);
  }
  else {
	retval = -1;
  }
  return retval;
}

void image_load_bytes_gray(image_t* image, unsigned char* src)
{
	int size, i;
	real_t *dst;
	size = image->x * image->y;

	dst = image->data;
	for (i = 0; i < size; i++)
	{
		*dst = *src;
		src++;
		dst++;
	}
}

void image_load_bytes_rgb(image_t* image, unsigned char* bytes, unsigned int channel)
{
	int size, i;
	unsigned char *src;
	real_t *dst;
	size = image->x * image->y;

	dst = image->data;
	src = bytes + channel;
	for (i = 0; i < size; i++)
	{
		*dst = *src;
		src += 3;
		dst++;
	}
}


/*
 * GET / SET
 */

#if !defined(INLINE) && !defined(INLINE_MACRO)

real_t image_get_mirror(image_t* image, int x, int y)
{
  return MACRO_IMAGE_GET_MIRROR(image, x, y);
}

real_t image_get_period(image_t* image, int x, int y)
{
  return MACRO_IMAGE_GET_PERIOD(image, x, y);
}

void image_set(image_t* image, int x, int y, real_t value)
{
  MACRO_IMAGE_SET(image, x, y, value);
}

real_t image_get(image_t* image, int x, int y)
{
  return MACRO_IMAGE_GET(image, x, y);
}

#endif

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.