 /*
  * Khoros: $Id: lvln03.c,v 1.1 1991/05/10 15:41:54 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: lvln03.c,v 1.1 1991/05/10 15:41:54 khoros Exp $";
#endif

 /*
  * $Log: lvln03.c,v $
 * Revision 1.1  1991/05/10  15:41:54  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: lvln03.c
 >>>>
 >>>>      Program Name: vln03
 >>>>
 >>>> Date Last Updated: Thu Mar 28 00:09:23 1991 
 >>>>
 >>>>          Routines: lvln03 - the library call for vln03
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


/* -library_includes */
/* -library_includes_end */


/****************************************************************
*
* Routine Name: lvln03 - library call for vln03
*
* Purpose:
*    
*    Format a Khoros image in DEC Sixel format
*    
*    
* Input:
*    
*    file           file descriptor to write the output to
*    
*    image          pointer to xvimage structure to be processed
*    
*    photo_neg      if non-zero then generate photonegative output
*    
*    
* Output:
*    
*    Return Value:  1 on success, 0 on failure.
*    
*    
*
* Written By: Scott Wilson
*    
*    
****************************************************************/


/* -library_def */
int
lvln03(file, image, photo_neg)
FILE    *file;
struct  xvimage *image;
int     photo_neg;
/* -library_def_end */

/* -library_code */
{
  int rows,cols,srows,i,j,k,l,mask;
  unsigned char *bptr,rev[256];
  char *malloc(),*cptr;

  rows = image->col_size;
  cols = image->row_size;
  srows = ((rows+5)/6);

  /* See if we have an image of the proper type */
  if (image->data_storage_type != VFF_TYP_BIT)
    {
      fprintf(stderr,"LN03: Cannot operate on non-BIT image!\n");
      return(0);
    }

  bptr = (unsigned char *)image->imagedata;
  cptr = malloc(cols*srows);   /* Byte array to build sixel image in */
  if (cptr == NULL)
    {
      fprintf(stderr,"LN03: Not enough memory for Sixel bitarray!\n");
      return(0);
    }

  bzero(cptr,cols*srows);
  
  /* Go through and zero the pad bits at the end of the last byte
     of each row in the Bitmap.  This will make the LN03 print out
     the pad as white which is invisible, instead of black which, although
     is the correct rendition of the Bitmap, looks terrible! */
  k = (cols+7)/8;
  mask = ~0 << 8-(8*k-cols);
  for (i=k-1; i<k*rows; i += k) bptr[i] |= mask;

  /* Flip bits to get Sixel idea of pixel order */
  ln03_genrev(rev);
  for (i=0; i<k*rows; i++) bptr[i] = rev[bptr[i]];

  /* Now invert the data, since whats dark on the screen is light on
     the LN03, and vice versa */
  if (!photo_neg) for (i=0; i<k*rows; i++) bptr[i] = ~bptr[i];

  /* Set the bits in the sixel array */
  for (i=0; i<rows; i++)
    for (j=0; j<cols; j++)
      if (readpixel_Bitmap(bptr,i,j,cols)) setpixel_sixel(cptr,i,j,cols);

  /* Flip the vertically to get the right vertical order, */
  /* and add 077 to turn into sixels (see p 4-55 in VT240 manual) */
  for (i=0; i<srows*cols; i++) cptr[i] = (rev[cptr[i]] >> 2) + 077;

  /* Write sixel format header */
  (void) fprintf(file, "%cP1q",27);

  /* Write the sixel array to the standard output */
  for (i=0; i<srows; i++)
    {
      for (j=0; j<cols; j++)
        {
          l = cptr[i*cols+j]; /* Must write twice since sixels are 1:2 ! */
          (void) fprintf(file, "%c%c",l,l);
        }
      (void) fprintf(file, "-");
    }

  /* Write sixel trailer */
  (void) fprintf(file, "%c\\",27);

  free(cptr);
  return(1);
}

readpixel_Bitmap(bptr,i,j,cols)
unsigned char *bptr;
int i,j,cols;
/*
      readpixel_Bitmap :  Return the value of the Bitmap pixel at
                          location (i,j) in an Bitmap containing an
                          image of size rows by cols.
*/
  {
    int k,l,n;

    k = (cols+7)/8;
    l = i/8;
    n = bptr[j*k+l];
    if (( n & (1 << (7-(i % 8)))) == 0) return(0);
    else return(1);
  }

setpixel_sixel(cptr,i,j,cols)
char *cptr;
int i,j,cols;
/*
     setpixel_sixel : Set the pixel at location (i,j) in the sixel bitmap
                      pointed to by cptr, where the sixel bitmap contains
                      a rows by cols image.
*/
  {
    int k,n;

    k = (j+5)/6;
    n = k*cols+i;
    cptr[n] |= (1 << (k*6-j));
  }

ln03_genrev(p)
unsigned char *p;
  {
    /* Generate an array of bit-reverse characters */
    int i;
    unsigned char j,k;

    for (i=0; i<256; i++)
      {
        j = i;
        k = 0;
        k |= (j >> 7) & (1 << 0); /* Bit 7 to Bit 0 */
        k |= (j >> 5) & (1 << 1); /* Bit 6 to Bit 1 */
        k |= (j >> 3) & (1 << 2); /* Bit 5 to Bit 2 */
        k |= (j >> 1) & (1 << 3); /* Bit 4 to Bit 3 */
        k |= (j << 1) & (1 << 4); /* Bit 3 to Bit 4 */
        k |= (j << 3) & (1 << 5); /* Bit 2 to Bit 5 */
        k |= (j << 5) & (1 << 6); /* Bit 1 to Bit 6 */
        k |= (j << 7) & (1 << 7); /* Bit 0 to Bit 7 */
        p[i]=k;
      }
  }
/* -library_code_end */
