/*************************************************************
*                      dump360.C                             *
*                 Auteur: GRIMBERT Jrme                    *
*                      version 3.2                           *
*                     rev. 29/09/94                          *
* Convertit les images DKB (RGB) en un fichier pour          *
* une imprimante couleurs.                                   *
* L'imprimante est une Canon BJC600 en mode LQ.              *
* Rsolution : 360 x 360 dpi                                 *
* largeur image : 360 points maxi                            *
* Matrice de mlange pour obtenir la couleur : 8x8           *
* Adressage en mode 48 bits                                  *
* Nombre de couleurs utilises : 4 (CMYK)                    *
* Modification par rapport  la version 1.0                  *
* - utilisation du noir pure au lieu du noir composite       *
*   pour essayer de restituer des gris corrects              *
* - abandon des trames prdfinies pour la gnration des    *
*   couleurs  (gnration dynamique)                         *
* - 4 passages d'encres au lieu de 3 -> segmentation de      *
*   l'image pour rester dans les 60Ko du buffer (esthetique) *
* Modification par rapport  la version 2.0                  *
* - changement de nom (cmy2paper)                            *
* - attaque directement le fichier RGB                       *
* - mise a blanc correct du bas de la zone imprimable        *
* Modification par rapport  la version 3.0                  *
* - algorithme de remplissage de la grille optimis          *
* Modification par rapport  la version 3.1                  *
* - Flush des sorties (pour les redirections)                *
*************************************************************/

#include <stdio.h>
#include <stdlib.h>

#ifdef QDOS
#include <qdos.h>
#include <string.h>
#define BAD -1
#define USAGE "Usage: EX %s;\"input_file output_file\"\n"
#define INIT
long _stack =32768L;
#else
#define BAD 1
#define USAGE "Usage: %s input_file output_file\n"
#define INIT
#endif

/* Version du programme */

char _version[] = "v3.2";

/* Nom du programme */

char _prog_name[] = "dump360";

/* Variables globales et routine d'initialisation spcifiques au QDOS */

#ifdef QDOS

char _copyright[] = "Grimbert Jrme";
char *_endmsg     = "Press Any Valid Key"; /* Let me read the screen */

/* Dimensions de la fentre */

struct WINDOWDEF _condetails = { 208, 1, 0, 7, 448, 200, 32, 16};
struct QLRECT    rect        = { 448, 186, 32, 30 };

/* excution de la routine d'ouverture de la fentre par dfaut */

char _conname[]              = "con_448x200a32x16";
void (*_consetup)()          = consetup_title;




#endif



#define REVERSE(a) ((a>>8)+((a&0xFF)<<8))

/* static unsigned map[8][256]; */
unsigned char jerome_code(c)
char *c;
{
 unsigned char r=0;
 char i;
 for(i=0;i<8;i++)
  {
  r=r<<1;
  r+=(1&&(c[i]==1));
  }

  return r;
}


void end_page(fich)
FILE *fich;
{
unsigned char c=12; /* this is Form Feed code */
fwrite(&c,1,1,fich);
}

void generate(in,largeur,fich)
char *in;
unsigned short largeur;
FILE * fich;
{
/* the last 0 are here just in case you change for something like printf */
static char colorseparator[]={13,0};
static char nextline[]={27,'J',24,0};
static char black[]={27,'r',0,0};
static char cyan[]={27,'r',2,0};
static char magenta[]={27,'r',1,0};
static char yellow[]={27,'r',4,0};
static char graphic[]={27,'*',72,0};
static char leftmargin[]={27,'$',0,0,0};
static char middlemargin[]={27,'$',240,0,0}; /* middle of page, if in 1/60" */
unsigned short k,l,m;
unsigned char octet,r,*q;
int val,i,j,line,n;
l=k=(m=largeur)*8; /* nombre de points horizontaux */
if (k>1440) {k=1440; m=180;}/* decoupage ncessaire pour les 60K du buffer */
k=REVERSE(k); /* LSB first */
#define middle_page 1440

/* first go to the left margin */
fwrite(leftmargin,4,1,fich);
fwrite(black,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* we have now to send 6 * m * 8 bytes to define the black (6) lines */
 /* in [couleur][xpos][ypos]   {0..3}{0..l-1}{0..5}
 /* */
 fwrite(in,6*8*m,1,fich); /* memory is linear, no? HHOS */

fwrite(colorseparator,1,1,fich); /* CR doesn't print in graphic mode */
/* back to the start of the line */
fwrite(cyan,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* we have now to send 6 * m * 8 bytes to define the cyan (6) lines */
 fwrite(in+l*6,6*8*m,1,fich);

fwrite(colorseparator,1,1,fich); /* CR doesn't print in graphic mode */
fwrite(magenta,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* again, 6 * largeur * 8 bytes to define magenta (6) lines */
 fwrite(in+l*6*2,6*8*m,1,fich);

fwrite(colorseparator,1,1,fich); /* CR doesn't print in graphic mode */
fwrite(yellow,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* and last, 6 * largeur * 8 bytes for the 6 lines of yellow */
 fwrite(in+l*6*3,6*8*m,1,fich);

if (m!=largeur) /* we have cut the output to avoid printer buffer saturation */
{/* print the rest of the picture */
m=largeur-m;
k=8*m;
k=REVERSE(k);
fwrite(middlemargin,4,1,fich);
fwrite(black,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* we have now to send 6 * m * 8 bytes to define the black (6) lines */
 /* in [couleur][xpos][ypos]   {0..3}{0..l-1}{0..5}
 /* */
 fwrite(in+middle_page*6,6*8*m,1,fich); /* memory is linear, no? HHOS!! */

fwrite(middlemargin,4,1,fich); /*  */

fwrite(cyan,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* we have now to send 6 * m * 8 bytes to define the cyan (6) lines */
 fwrite(in+l*6+middle_page*6,6*8*m,1,fich);

fwrite(middlemargin,4,1,fich); /* */
fwrite(magenta,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* again, 6 * largeur * 8 bytes to define magenta (6) lines */
 fwrite(in+l*6*2+middle_page*6,6*8*m,1,fich);

fwrite(middlemargin,4,1,fich); /* */
fwrite(yellow,3,1,fich);
fwrite(graphic,3,1,fich);
fwrite(&k,2,1,fich);
/* and last, 6 * largeur * 8 bytes for the 6 lines of yellow */
 fwrite(in+l*6*3+middle_page*6,6*8*m,1,fich);

} /* this end the second part of the picture */
fwrite(nextline,3,1,fich);
}


unsigned short jerome_read(in,l,fich)
char *in;
int l;
FILE *fich;
{ unsigned short k,reponse;
  int i;
  char *curs;
  curs=in;

  fread(&k,2,1,fich);
  reponse=REVERSE(k);
  fread(in,l,1,fich);
  fread(&k,2,1,fich);
  if (feof(fich))
    {
    for(i=0,curs=in+l;i<5*l;i++) *(curs++)=0xFF;
    return reponse;
    }
   fread(in+l,l,1,fich);
   fread(&k,2,1,fich);
  if (feof(fich))
    {
    for(i=0,curs=in+l*2;i<4*l;i++) *(curs++)=0xFF;
    return reponse;
    }
  fread(in+l*2,l,1,fich);
  fread(&k,2,1,fich);
  if (feof(fich))
    {
    for(i=0,curs=in+l*3;i<3*l;i++) *(curs++)=0xFF;
    return reponse;
    }
  fread(in+l*3,l,1,fich);
  fread(&k,2,1,fich);
  if (feof(fich))
    {
    for(i=0,curs=in+l*4;i<2*l;i++) *(curs++)=0xFF;
    return reponse;

    }
  fread(in+l*4,l,1,fich);
  fread(&k,2,1,fich);
  if (feof(fich))
    {
    for(i=0,curs=in+l*5;i<l;i++) *(curs++)=0xFF;
    return reponse;

    }
  fread(in+l*5,l,1,fich);

        return reponse;
}

void codifie(tab,cyan,magenta,yellow)
unsigned char *tab,cyan,magenta,yellow;
{
 /* tab [couleur][xpos]  {0..3}{0..7}      */
 /* cyan , magenta , yellow    0..255      */
 unsigned char grid[8][8];
 unsigned char x[64],y[64],i,j,k,nb,k1,k2,k3,l;
 unsigned char c,m,yy,noir; /* normalised colours 0..64  for a 8x8 grid */
 c=(cyan+1)/4;      /* 255 -> 64, 251..254->53; 127..131->32   */
                    /*                     ; 3..6->1, 0..2 ->0 */
 m=(magenta+1)/4;
 yy=(yellow+1)/4;
 l=0;
 if (c==64) {l+=1;c=0;} /* full colour trapping */
 if (m==64) {l+=2;m=0;}
 if (yy==64) {l+=4;yy=0;}
 for(i=0;i<64;i++)  /* initialisation des listes et de la grille */
 {j=x[i]=i%8;k=y[i]=i/8;grid[j][k]=l;}
 nb=64;
 while (c|m|yy) /* encore des points  placer */
        {
        i=rand()%nb; /* temps deterministe pour un algorithme de remplissage
                        alatoire    temps = coef * nombre_de_points */
        if (c) {grid[x[i]][y[i]]+=1; c--;}
        if (m) {grid[x[i]][y[i]]+=2; m--;}
        if (yy) {grid[x[i]][y[i]]+=4; yy--;}
  /* was */
     /*   for(j=i;j<nb-1;j++)*/ /* erase the used entries from the lists */
     /*           {x[j]=x[j+1]; y[j]=y[j+1];} */
  /* but this is quicker */
        x[i]=x[nb];y[i]=y[nb];
        nb--;
        }
 /* maintenant il faut remplir la rponse */
 /* d'abord le noir */
 for(i=0;i<8;i++)
 {
 for(k=k1=k2=k3=0,j=0;j<8;j++)
 {
   k=k<<1;
   k1=k1<<1;
   k2=k2<<1;
   k3=k3<<1;
   /* l'ordre des lignes est important ! */
   if (grid[i][j]==7) /* noir */ {k++; grid[i][j]=0;}
   if (grid[i][j]>=4) /* composante jaune */ {k1++; grid[i][j]-=4;}
   if (grid[i][j]>=2) /* composante magenta */ {k2++; grid[i][j]-=2;}
   if (grid[i][j]>=1) /* composante cyan */ {k3++; grid[i][j]-=1;}
 }
 *(tab+i)=k; /* value[0][i] */
 *(tab+i+8)=k3; /* value[1][i] */
 *(tab+i+16)=k2; /* value[2][i] */
 *(tab+i+24)=k1; /* value[3][i] */
 }

}

void transforme (out, largeur,in)
unsigned char *out,*in;
unsigned short largeur;
{ /* out [couleur][xpos][ypos]  {0..3}{0..largeur*8-1}{0..5}  */
  /* in [line][couleur][xpos] {0..5}{0..2}{0..largeur-1}      */
  char *cur;
  unsigned char cyan,magenta,yellow;
  unsigned char value[4][8];
  int i,line,j,k;
  for(i=0;i<largeur;i++)
  for(line=0;line<6;line++)
   { cyan=0xFF^(*(in+line*largeur*3+i));  /* Trust me ! */
                                          /* I know what is going on */
     magenta=0xFF^(*(in+line*largeur*3+i+largeur));
     yellow=0xFF^(*(in+line*largeur*3+i+2*largeur));
     codifie(value,cyan,magenta,yellow);
     for(j=0;j<4;j++)
     for(k=0;k<8;k++)
     *(out+j*largeur*6*8+k*6+i*8*6+line)=value[j][k];
   }

}

void main (argc, argv)
int argc;
char *argv[];
{
    /* facile... fichiers source et destination */

    FILE *fsrc, *fdest;

    /* hauteur et largeur */

    unsigned short w, h, w1, h1;

    int  i, j,l;
    unsigned char *in,*current,*out;
    unsigned short linenumber,linecount;

    INIT

    printf("\n%s %s\n", _prog_name, _version);
    printf("  RGB DKB file printer for Canon BJC600 on LQ mode\n");
    printf("  written by GRIMBERT Jrme, 29/09/94\n\n");


    if (argc != 3)
    {
        printf("Bad arguments number !!!\n");
        printf(USAGE, argv[0]);
        exit(BAD);
    }

    fsrc = fopen(argv[1], "rb");
    if (fsrc == NULL)
    {
        printf("First file can't be opened !!!\n");
        exit(BAD);
    }

    fdest = fopen(argv[2], "wb");
    if (fdest == NULL)
    {
        printf("Second file can't be created !!!\n");
        exit(BAD);
    }

    fread(&w, 2, 1, fsrc);
    fread(&h, 2, 1, fsrc);

    w1 = REVERSE(w);
    h1 = REVERSE(h);

    printf("File   %s\n", argv[1]);
    printf("Format %d * %d\n\n", w1, h1);
    printf("Output to %s\n",argv[2]);
    in=malloc((l=w1*3)*6); /* 3 couleurs, 6 lignes pour 48 bits/8 */
    out=malloc(w1*6*4*8); /* 4 couleurs, 6 lignes, 8 octets par pixel */
    if ((in==NULL)||(out==NULL)) {exit (BAD);}
    h1+=5;h1/=6;
    printf("Dynamic colour level pattern generation...\n");


    /* for each pack of 6 lines, do... */

    printf("Processing lines...");

    linecount = 0;

    for(j=0;j<h1;j++)
    {

            current=in;
            linecount=jerome_read(in, l, fsrc);
            printf("%d...%d",linecount,linecount+5);
            transforme(out,w1,in);
            printf(" : ");
            generate(out,w1,fdest);
            fflush(stdout);

    } /* end for j */

    /* on libre tout */
    free(in);
    free(out);
    fclose(fsrc);
    end_page(fdest);
    fclose(fdest);

    printf("\n Done !\n");
}
