1/**
2* @example pnmshow.c
3*/
4#include <stdio.h>
5#include <rfb/rfb.h>
6#include <rfb/keysym.h>
7
8#ifndef HAVE_HANDLEKEY
9static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl)
10{
11  if(down && (key==XK_Escape || key=='q' || key=='Q'))
12    rfbCloseClient(cl);
13}
14#endif
15
16int main(int argc,char** argv)
17{
18  FILE* in=stdin;
19  int i,j,k,l,width,height,paddedWidth;
20  char buffer[1024];
21  rfbScreenInfoPtr rfbScreen;
22  enum { BW, GRAY, TRUECOLOUR } picType=TRUECOLOUR;
23  int bytesPerPixel,bitsPerPixelInFile;
24
25  if(argc>1) {
26    in=fopen(argv[1],"rb");
27    if(!in) {
28      printf("Couldn't find file %s.\n",argv[1]);
29      exit(1);
30    }
31  }
32
33  fgets(buffer,1024,in);
34  if(!strncmp(buffer,"P6",2)) {
35	  picType=TRUECOLOUR;
36	  bytesPerPixel=4; bitsPerPixelInFile=3*8;
37  } else if(!strncmp(buffer,"P5",2)) {
38	  picType=GRAY;
39	  bytesPerPixel=1; bitsPerPixelInFile=1*8;
40  } else if(!strncmp(buffer,"P4",2)) {
41	  picType=BW;
42	  bytesPerPixel=1; bitsPerPixelInFile=1;
43  } else {
44    printf("Not a ppm.\n");
45    exit(2);
46  }
47
48  /* skip comments */
49  do {
50    fgets(buffer,1024,in);
51  } while(buffer[0]=='#');
52
53  /* get width & height */
54  sscanf(buffer,"%d %d",&width,&height);
55  rfbLog("Got width %d and height %d.\n",width,height);
56  if(picType!=BW)
57	fgets(buffer,1024,in);
58  else
59	  width=1+((width-1)|7);
60
61  /* vncviewers have problems with widths which are no multiple of 4. */
62  paddedWidth = width;
63  if(width&3)
64    paddedWidth+=4-(width&3);
65
66  /* initialize data for vnc server */
67  rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,(bitsPerPixelInFile+7)/8,bytesPerPixel);
68  if(!rfbScreen)
69    return 0;
70  if(argc>1)
71    rfbScreen->desktopName = argv[1];
72  else
73    rfbScreen->desktopName = "Picture";
74  rfbScreen->alwaysShared = TRUE;
75  rfbScreen->kbdAddEvent = HandleKey;
76
77  /* enable http */
78  rfbScreen->httpDir = "../webclients";
79
80  /* allocate picture and read it */
81  rfbScreen->frameBuffer = (char*)malloc(paddedWidth*bytesPerPixel*height);
82  fread(rfbScreen->frameBuffer,width*bitsPerPixelInFile/8,height,in);
83  fclose(in);
84
85  if(picType!=TRUECOLOUR) {
86	  rfbScreen->serverFormat.trueColour=FALSE;
87	  rfbScreen->colourMap.count=256;
88	  rfbScreen->colourMap.is16=FALSE;
89	  rfbScreen->colourMap.data.bytes=malloc(256*3);
90	  for(i=0;i<256;i++)
91		  memset(rfbScreen->colourMap.data.bytes+3*i,i,3);
92  }
93
94  switch(picType) {
95	case TRUECOLOUR:
96		  /* correct the format to 4 bytes instead of 3 (and pad to paddedWidth) */
97		  for(j=height-1;j>=0;j--) {
98		    for(i=width-1;i>=0;i--)
99		      for(k=2;k>=0;k--)
100			rfbScreen->frameBuffer[(j*paddedWidth+i)*4+k]=
101			  rfbScreen->frameBuffer[(j*width+i)*3+k];
102		    for(i=width*4;i<paddedWidth*4;i++)
103		      rfbScreen->frameBuffer[j*paddedWidth*4+i]=0;
104		  }
105		  break;
106	case GRAY:
107		  break;
108	case BW:
109		  /* correct the format from 1 bit to 8 bits */
110		  for(j=height-1;j>=0;j--)
111			  for(i=width-1;i>=0;i-=8) {
112				  l=(unsigned char)rfbScreen->frameBuffer[(j*width+i)/8];
113				  for(k=7;k>=0;k--)
114					  rfbScreen->frameBuffer[j*paddedWidth+i+7-k]=(l&(1<<k))?0:255;
115			  }
116		  break;
117  }
118
119  /* initialize server */
120  rfbInitServer(rfbScreen);
121
122  /* run event loop */
123  rfbRunEventLoop(rfbScreen,40000,FALSE);
124
125  return(0);
126}
127