/* --- sampled.c    ver1.0 */
/* originally coded by M. Hirasawa & T. Hasegawa 2001/04/13  (named sample.c) */
/* revised by M. Oshima for size flexibility of image data file
   and to process Expose event (named samplen.c) */
/* revised by M. Oshima to give flexibility on input file and display
   (named sampled.c) */
/*     1st release                            2001.07.23     */
/* --- last modification                      2001.07.23     */

/*  usage example sampled dome.ras */
/*  hit [enter] to continue
    press button on window to finish */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
/*          --- set image size here (chimf is helpful ) */ 
/*          if you adopt *(data + y*width + x) instead to data[y][x],
            no need to define XMAX and YMAX                         */
/*#define         XMAX     720*/ /* for dome.ras */
/*#define         YMAX     486*/

static          Window                  root, win1, win2, wins[2];
static          Display                 *disp;
static          Visual                  *vis;
static          Colormap                cmap;
static          GC                      gc;
static          int                     deptho;
static          int                     width, height, depthi, length; /* 2001.0
7.11 */
static          Status                  grayo;

typedef struct{
  int magic;
  int width;
  int height;
  int depth;
  int length;
  int type;
  int maptype;
  int maplength;
} rasterfile;

rasterfile       raster;

char names1[] = "input image";
char names2[] = "output image";

/*void user_prog(u_char input_data[][XMAX], u_char output_data[][XMAX]
               , int width, int height);*/
void user_prog2(u_char *input_data, u_char *output_data, int width, int height);
u_char *get_image(char *, XColor *colt, Status *grayi);
void set_colt(u_char *colbuf, int maplength, int maptype, XColor *colt);
int set_lud(unsigned short lutd[][256], XColor *colt, int depthi, int deptho
, Status grayi);
XImage *mk_image(u_char *data, int width, int height, int depthi, int deptho
, unsigned short lutd[][256], Status grayi, int imode, XColor *colt);
Window make_win(char *);
void graphic_intialize(void);
void evntloop(XImage *images[], Window wins[]);
u_char *decode_vdata(u_char *vdata, int width, int height, int length);
u_char
*bm_to_gray(u_char *vdataf, int width, int height, int length, int black
, int white);


int main(int argc, char **argv)
{
  int i, j, pad;
  u_char *input_data, *output_data;
  char name[50];
  XImage *image1, *image2, *images[2];
  XColor colt[256];
  unsigned short lutd[3][256];
  int imode;
  Status grayi;

  if( argc != 2 ){
    printf("Usage: %s [data_name]\n", argv[0]);
    exit(1);
  }

  name[0] = '\0';
  strcat(name, argv[1]);
                           /* width, height & depthi are set in get_image */
  input_data = get_image(name, colt, &grayi);
  graphic_intialize();

  imode = set_lud(lutd ,colt, depthi, deptho, grayi);

  win1 = make_win(names1);
  image1 = mk_image(input_data, width, height, depthi, deptho, lutd, grayi
                    , imode, colt);
  XPutImage(disp, win1, gc, image1, 0, 0, 0, 0, width, height);
  XMapWindow(disp, win1);
  XFlush(disp);

  puts("Hit [Enter]!");
  getchar();

  pad = width % 2;
  output_data = (u_char *)malloc((width + pad) * height * (depthi /8) * sizeof(u
_char));

  /* -- start ------------------------------------------------------- */

  user_prog2(input_data, output_data, width, height);

  /* -- end   ------------------------------------------------------- */

  win2 = make_win(names2);
  image2 = mk_image(output_data, width, height, depthi, deptho, lutd, grayi
                    , imode, colt);
  XPutImage(disp, win2, gc, image2, 0, 0, 0, 0, width, height);
  XMapWindow(disp, win2);
  XFlush(disp);

  XSelectInput(disp, win1, ExposureMask | ButtonPressMask );
  XSelectInput(disp, win2, ExposureMask | ButtonPressMask );
  images[0] = image1; images[1] = image2;
  wins[0] = win1; wins[1] = win2;
  fprintf(stderr, "goto event loop\n");
  evntloop(images, wins);

  puts("Finish!");  /* "finish" */
  XDestroyImage(image1);
  XDestroyImage(image2);
  return 0;
}


/* -- user_prog start --------------------------------------------- */

/* void user_prog(u_char input_data[][XMAX], u_char output_data[][XMAX]
               , int width, int height)
{
  int x, y;

  for(y = 0; y < height; y++){
    for(x = 0; x < width; x++){
      output_data[y][x] = input_data[y][x];
    }
  }

}*/

/* -- user_prog end   --------------------------------------------- */

void user_prog2(u_char *input_data, u_char *output_data, int width, int height)
  /*          if you adopt *(data + y*width + x) instead to data[y][x],
            no need to define XMAX and YMAX                         */
  {
  int x, y, byte, bytel;

  bytel = depthi/8;
  for(y = 0; y < height; y++){
    for(x = 0; x < width; x++){
      for(byte = 0; byte < bytel; byte++, output_data++, input_data++){
        *output_data = *input_data;
        /* output_data[y][x] = input_data[y][x]; */
      }
    }
  }
}


u_char
*get_image(char *name, XColor *colt, Status *grayi)
{
  u_char      *colbuf;
  FILE        *fpin;
  u_char *vd;
  int maptype, maplength;

  fpin = fopen(name, "r");
  if(fpin == NULL){
    fprintf(stderr, "error: can't open %s!\n", name);
    exit(1);
  }

  fread(&raster, sizeof(raster), 1, fpin);
  width  = raster.width; /* 2001.07.03 */
  height = raster.height;
  depthi = raster.depth;
  length = raster.length;
  maplength = raster.maplength;
  maptype   = raster.maptype;
  *grayi = (depthi == 8 && maplength == 0)?  True: False;

  /* if colormap exists on rasterfile set lut */
  if(maplength > 0){
    colbuf = (u_char *)malloc(maplength * sizeof(char));
    fread(colbuf, 1, maplength, fpin ); /* read colormap */
    set_colt(colbuf, maplength, maptype, colt);
    free(colbuf);
  }

  vd = (u_char*)malloc(length *sizeof(u_char)); /* 2001.07.11 */
  fread( vd, 1, length, fpin );

  fclose(fpin);
  if(raster.type == 2) vd = decode_vdata(vd, width, height, length);
  if(depthi ==1) {
    vd = bm_to_gray( vd, width, height, length, 0, 255) ;
    depthi = 8;
  }

  return vd;
}

void
set_colt(u_char *colbuf, int maplength, int maptype, XColor *colt)
     /* if colormap exists on rasterfile set colt */
{
  XColor t;
  int i, pixs, r, g, b;

  pixs = maplength/3;
  for( i=0; i < pixs; i++ ) {
    r  = *(colbuf +         i);
    g  = *(colbuf +   pixs +i);
    b  = *(colbuf + 2*pixs +i);
    t.red = r; t.green = g; t.blue = b; t.pixel = i;
    colt[i] = t;
  }
  for( i=pixs; i < 256; i++ ) {
    t.red = 0; t.green = 0; t.blue = 0; t.pixel = i;
    colt[i] = t;
  }

}

int
set_lud(unsigned short lutd[][256], XColor *colt, int depthi, int deptho
, Status grayi)
     /* to set lut for depth= 8 display.  variations per color supposed to be 6.
 */
  /* --- set color pixel number on lut (coded by equal spaced number) */
  /* lutd 0: for gray input, 1 for pseud color input , 2 full color input*/
     /* 6 * 6 * 6 = 216 < 256 */
     /* lut entry is coded by 6 * 6 * 6 for color*/
     /* lut entry is coded by 256 for gray */
{
  int imode, rc, gc, bc, dpc = 6, maxo, keisu;
  unsigned short r, g, b, i;
  unsigned long pixel, white, black;
  XColor t;
  Status status;

  imode = 3; /* imode = 3 means direct both in and out */
  if(depthi == 8 || deptho == 8) {
    if(depthi == 16 || depthi == 24 || depthi == 32){
      imode = 2;
    } else {
      imode = (grayi)? 0 : 1;
    }
  } else {
    return imode;
  }

  white = WhitePixel(disp, 0);
  t.pixel = white;
  XQueryColor(disp, cmap, &t);
  maxo = t.green + 1;

  switch(imode){
  case 0:
    keisu  = maxo /256;
    for(i = 0; i < 256; i++){ /* for gray data input*/
      t.red   = (unsigned)i * keisu;
      t.green = (unsigned)i * keisu;
      t.blue  = (unsigned)i * keisu;
      XAllocColor(disp, cmap, &t);
      lutd[0][i] = t.pixel;
    }
    break;
  case 1:
    keisu  = maxo /256;
    for(i = 0; i < 256; i++){ /* for pseud color input */
      t.red   = colt[i].red    * keisu;
      t.green = colt[i].green  * keisu;
      t.blue  = colt[i].blue   * keisu;
      XAllocColor(disp, cmap, &t);
      lutd[1][i] = t.pixel;
    }
    lutd[1][255] = white;
    break;
  case 2:
    keisu = maxo / 6; /* for full color input */
    for(rc=0; rc < dpc; rc++){ /* rc: red code 0-5 */
      r = rc * keisu; t.red = r;
      for(gc=0; gc < dpc; gc++){
        g =gc * keisu; t.green = g;
        for(bc=0; bc < dpc; bc++){
          b = bc * keisu; t.blue = b;
          status = XAllocColor(disp, cmap, &t);
          if(status != True) goto err;
          lutd[2][(rc * 6 + gc) * 6 + bc] = t.pixel;
        }
      }
    }
    /*white = WhitePixel(disp, 0);
      black = BlackPixel(disp, 0);
      lut[255] = white; lut[0] = black;*/
    break;
  default:
    fprintf(stderr,"unexpected imode %d is received in set_lud\n",imode);
    exit(1);
  }
  return imode;

err: fprintf(stderr,"alloc error in set_lud");
  exit(1);
}


XImage
*mk_image(u_char *data, int width, int height, int depthi, int deptho
, unsigned short lutd[][256], Status grayi, int imode, XColor *colt)
/* make Ximage data for display from normalized (24 bit for color 8 bit for gray
 ) video data */
/*                                            last modification 2001.07.20 */
{
  int x, y, i, countx, pad;
  u_char *data0;
  static unsigned long r, g, b, rc, gc, bc, rcs[3], r_mul, g_mul, b_mul
    , mask, pixel;
  static char *pix_byte = (u_char *) &pixel;
  static unsigned long masks[3]; static unsigned int shifts[3];
  u_char *dto, *dto0;
  XImage *image;
  int vpci; /* variations per color for input */
  int vpco, dci, dco, shift, byte, boffset;
  int vpcis[5] = {0, 6, 32, 256, 256}; /* for 8,16,24,(32) depthi     */
  int vpcos[5] = {0, 6, 32, 256, 256}; /* for 8,16,24,(32) deptho     */
  static int vpcosc[3];
  int muls[5][3] =         /* 0-2 correspond to r-b                   */
    {        0,   0, 0     /* multiplier to compose pixel for display */
      ,    6*6,   6, 1     /* for  8 bit display */
      ,  32*32,  32, 1     /* for 16 bit */
      ,256*256, 256, 1     /* for 24 bit */
      ,256*256, 256, 1};   /* for 32 bit */
  static int mulsc[3];
  static int initted = 0;

  dci = depthi / 8;
  dco = deptho / 8;
/* --------- initial setting for display environment ---------- */
  if(initted == 0) {
    initted = 1;
    for(i = 0; i < 3; i++){
      mulsc[i]  = muls[dco][i];
      vpcosc[i] = vpcos[dco];
    }
    if(dco > 1){
      masks[0] = vis->red_mask; masks[1] = vis->green_mask;
      masks[2] = vis->blue_mask;
      for(i = 0; i < 3; i++){
        mask = masks[i]; shift = 0;
        while( !((1 << shift) & mask) && shift < 32)
          shift++;
        shifts[i] = shift;
      }
      for(i = 0; i < 3; i++){
        vpcosc[i] = (masks[i] >> shifts[i]) + 1;
      }
      mulsc[2] = 1; mulsc[1] = vpcosc[0]; mulsc[0] = vpcosc[1] * mulsc[1];
    }
  }

  data0 = data;
  dto = dto0 = (u_char *)malloc((unsigned)width*height*dco*sizeof(char));
  if(dto == NULL)
    exit(1);

  if(dci == 1 && dco == 1){
    for(y = 0; y < height; y++){
      for(x = 0; x < width; x++, data ++, dto++){
        pixel = lutd[imode][*data];
        *dto   = (u_char)pixel;
      }
    }
    goto xcr;
  }

  vpci  = vpcis[dci]; /* variations per color for input   */
  vpco  = vpcos[dco]; /* variations per color for display */
  if(dco == 1) { mulsc[0] = muls[dco][0]; mulsc[1] = muls[dco][1]; mulsc[2] = mu
ls[dco][2];}
  pix_byte = (unsigned char*) &pixel;
  pixel = lutd[imode][*data];
  boffset = (dci == 4) ? 1 : 0;

  for(y = 0; y < height; y++){
    countx = 0; /* to treat pad */
    for(x = 0; x < width; x++, data += dci, countx += dci){
/* -----------  to read data  ------------ */
      switch(dci){
      case 1: /* here depthi =8, while deptho > 8 */
        pixel = *data;
        if(grayi){
          pixel = lutd[imode][pixel];
        } else {
          r = colt[pixel].red; g = colt[pixel].green; b = colt[pixel].blue;
          rc = (r * vpcosc[0])/256; gc = (g * vpcosc[1])/256; bc = (b * vpcosc[2
])/256;
          pixel = rc * mulsc[0] + gc * mulsc[1] + bc * mulsc[2];
        }
        break;
      case 3:
      case 4:
        b  = *(data+boffset); g =*(data+1+boffset); r = *(data+2+boffset);
        rc = (r * vpcosc[0])/vpci; gc = (g * vpcosc[1])/vpci; bc = (b * vpcosc[2
])/vpci;
        pixel = rc * mulsc[0] + gc * mulsc[1] + bc * mulsc[2];
      }
/* ----------- to write data for display ------------ */
      if(dco == 1) { /* if display is 8 bit special treatment */
        pixel = lutd[imode][pixel];
        *dto = (u_char)pixel;
        dto++;
        continue;
      } else {
        for(byte =0; byte < dco; byte++, dto++)
          *dto = pix_byte[4-dco+byte];
      }
    } /* x loop */
    pad = countx % 2;
    if(pad != 0 ) data += pad;
  }   /* y loop */

xcr:
  dto  = dto0;
  data = data0;
  image = XCreateImage(disp, vis, deptho, ZPixmap, 0, 0,
                       width, height, 32, width*dco);
  image->data = (char *)dto;
  image->bits_per_pixel = 8*dco;
  image->byte_order = MSBFirst;
  image->bitmap_unit = 32;
  image->red_mask   = vis->red_mask;
  image->green_mask = vis->green_mask;
  image->blue_mask  = vis->blue_mask;

  return image;
}

Window make_win(char *name)
{
  Window win;
  win = XCreateSimpleWindow(disp, root, 100, 100, width, height, 2, 0, 0);
  XStoreName(disp, win, name);
  XMapWindow(disp, win);
  XFlush(disp);

  return win;
}

void graphic_intialize(void)
{
  unsigned short r, g, b;
  XColor xc;
  XStandardColormap *cmap2;

  disp  = XOpenDisplay(NULL);
  root  = RootWindow(disp, 0);
  vis   = DefaultVisual(disp, 0);
  deptho= DefaultDepth(disp, 0);

  gc    = XCreateGC(disp, root, 0, 0);
  cmap  = DefaultColormap(disp, 0);
  XGetStandardColormap(disp, root, cmap2, XInternAtom(disp, "RGB_TEST_MAP", 0));
}

void evntloop(XImage *images[], Window wins[])
{
  XEvent event;
  Window win;
  XImage *image;
  int i, status;

  status = 1;
  while(status){
    XNextEvent( disp, &event );
    switch( event.type ){
    case Expose :
      fprintf(stderr, "Expose event\n");
      win = event.xany.window;
      for(i=0; i < 2; i++){
        if(win == wins[i]){
          image = images[i];
          break;
        }
      }
      XPutImage(disp,win,gc,image,0,0,0,0,
                width,height);
      XFlush(disp);
      break;
    case ButtonPress :
      fprintf(stderr, "ButtonPress event\n");
      status =0;
      break;
    }
  }

}

/* ---------- decode_vdata ---------- */
/* this is dedicated process for byte_encoded data */
/*                             coded by M. Oshima    1999.10.27  */
/*                             last modification     2001.07.21  */
/*     data example: sh080400.ras */
u_char
*decode_vdata(u_char *vdata, int width, int height, int length){
  int i, j, k, M, N, Nsum, pad;
  u_char *vdata2;

  pad = width % 2;
  vdata2=(u_char *)malloc((width + pad) * height * 3);
  if(vdata2 == NULL) goto alcer;
  j = 0; Nsum =0;
  for(i=0; i < length; i++){
    M = N =0;
    if((unsigned int)vdata[i] != 128){
      vdata2[j++] = vdata[i];
      continue;
    } else{ /* vdata[i] = 128 */
      N = (unsigned int)vdata[i+1];
      if(N == 0){
        vdata2[j++] = vdata[i]; i++;
      }else{
        Nsum += N;
        M = (unsigned int)vdata[i+2];
        for(k=0; k <= N; k++){
          vdata2[j++] =(u_char)M;
        } /* end of k loop */
        i += 2;
      } /* end of else */
    } /* end of else */
  } /* end of for */
  if(j != width * height * 3) goto err2;
  return vdata2;
 alcer: printf("allocation error in decode_vdata\n");
  return(u_char *)NULL;
 err2:  printf("length error in decode_vdata  points*3 j = %d %d \n",
              width * height *3, j);
  return(u_char *)NULL;
}

/* ---------- bm_to_gray ---------- */
/* ビットマップデータ(depth=1)から8bビット濃淡画像形式のファイルを
   作る */ /* vdatafからvdataiデータを生成 */
/*                         coded by M. Oshima        2001.07.20  */
/*                         last modification         2001.07.21  */
/*     data example: clock0.ras */
u_char
*bm_to_gray(u_char *vdataf, int width, int height, int length, int black, int wh
ite)
{
  u_char *vdatai, *vdatai0;
  int l, x, y, i, byte, counthf, counthi, padi, bp, bmdata;

  /* vdatai: data for internal (this is supposed to be normalized) */
  padi = width % 2;
  vdatai = vdatai0 = (u_char *)malloc((width + padi) * height * sizeof(char));
  if(vdatai == NULL) goto alcer;

  counthf =0; counthi = 0;
  for(l =0; l < length; l++, vdataf++){
    byte = *vdataf;
    for(bp=7; bp >= 0; bp--, counthi++){
      bmdata = (byte & (1 << bp)) >> bp; /* get bitmap data */
      /* write w or b pixel on vdatai */
      *vdatai++ = (bmdata == 1) ? white: black;
      if(counthi == width-1){ /* end of horizontal line */
        /* pad in vdataf is simply ignored */
        padi = width % 2;
        vdataf += padi; /* output pad (rounfed to 2 bytes) */
        counthi =0;
        break; /* go to next byte */
      }
    }
  }
  return vdatai0;
 alcer:
  fprintf(stderr, "alloc error in bm_to_gray\n");
  exit(1);
}

}


戻る