#include #include #include #include #include #include #include #include /*#include "assgn1.h"*/ #include extern "C" { #include "myform.h" #include "jpeglib.h" } #include "canvas.h" #include "window.h" #include "geo.h" #include "dojpeg.h" #include "ppm_gl_io.h" #include "findblocks.h" #include ".cad.C" #include "jpegform.h" #include "FImage.h" #include "GLCanvasFImage.h" /* some windows... global */ long forms_win_id; long mainwin; long g_orig_file_size; long viewwin1, viewwin2, viewwin3; FImage *fi=NULL; /*************************************************************************** F O R M I N I T ***************************************************************************/ void forminit(void) { fl_qdevice(ESCKEY); fl_qdevice(ENDKEY); fl_qdevice(LEFTMOUSE); } /*************************************************************************** D R A W M A I N W I N D O W ***************************************************************************/ void drawmainwindow(GLCanvas *canvas1) { double pt[2]; double pt2[2]; Matrix tmp; long oldmode; pt[0]=10; pt[1]=10; pt2[0]=100; pt2[1]=100; reshapeviewport(); cpack(0x0); clear(); cpack(0xFFF000); pushProjectionStack(); pushmatrix(); perspective(900,1,0.1,100); lookat(0,0,0,10,10,10,0); /*drawbox(POLYGON,0,0,0,2,3,4);*/ drawCanvas(canvas1); popmatrix(); popProjectionStack(); } /*************************************************************************** D O M O U S E ***************************************************************************/ void domouse(long dir, GLCanvas *canvas) { static long xdown; static long ydown; long xup; long yup; long xori,yori; getorigin(&xori,&yori); if (dir==1) { xdown=getvaluator(MOUSEX)-xori; ydown=getvaluator(MOUSEY)-yori; } else { xup=getvaluator(MOUSEX)-xori; yup=getvaluator(MOUSEY)-yori; printf("mouse : %d %d %d %d \n",xdown,ydown,xup,yup); line2D(xdown,ydown,xup,yup); } } /*************************************************************************** I N I T M Y W I N D O W S ***************************************************************************/ void initmywindows (void) { viewwin1=openRGBSWindow(forms_win_id,(short)pictbox1->x+3,(short)pictbox1->y+3,(short)pictbox1->w-7,(short)pictbox1->h-7); viewwin2=openRGBSWindow(forms_win_id,(short)pictbox2->x+3,(short)pictbox1->y+3,(short)pictbox1->w-7,(short)pictbox1->h-7); fl_set_slider_step(smoothingslider,1.0); fl_set_slider_bounds(smoothingslider,0.0,100.00); fl_set_slider_value(smoothingslider,0.00); fl_set_slider_step(compressionslider,1.0); fl_set_slider_bounds(compressionslider,1.0,100.00); fl_set_slider_value(compressionslider,20.00); fl_set_menu(viewsize1,"X 1|X 2|X 3|X 4"); fl_set_menu(viewsize2,"X 1|X 2|X 3|X 4"); fl_addto_choice(quantchoice,"Luminance"); fl_addto_choice(quantchoice,"Chrominance"); fl_addto_choice(quantchoice,"Both"); /*viewwin1=openRGBSWindow(forms_win_id,viewwindow1->x+3,viewwindow1->y+3,viewwindow1->w-7,viewwindow1->h-7);*/ /*ortho(-5,5,-5,5,0,100);*/ /*lookat(0,0,0,0,1,0,0);*/ /*viewwin2=openRGBSWindow(forms_win_id,viewwindow2->x+3,viewwindow2->y+3,viewwindow2->w-7,viewwindow2->h-7);*/ /*viewwin3=openRGBSWindow(forms_win_id,viewwindow3->x+3,viewwindow3->y+3,viewwindow3->w-7,viewwindow3->h-7);*/ } void math_lib_fodder (void) { double i; i=sqrt(sqrt(2*3)); } /*************************************************************************** C H E C K _ F O R _ R E C O M P R E S S ***************************************************************************/ void check_for_recompress(GLCanvas *gl_canvas,GLCanvas *gl_canvas2, unsigned int lumtab[], unsigned int chromtab[]) /*!*/ { if ((fl_get_slider_value(compressionslider)!=gl_canvas2->lastcompression) || (fl_get_slider_value(smoothingslider)!=gl_canvas2->lastsmoothing)) { do_recompress(gl_canvas,gl_canvas2,lumtab,chromtab); } } /*************************************************************************** D O _ R E C O M P R E S S ***************************************************************************/ void do_recompress(GLCanvas *gl_canvas,GLCanvas *gl_canvas2, unsigned int lumtab[], unsigned int chromtab[]) /*!*/ { char buf[300]; char tmpfilename[200]; int filesize=0; showfilesize(0,g_orig_file_size); gl_canvas2->lastcompression=(int)fl_get_slider_value(compressionslider); gl_canvas2->lastsmoothing=(int)fl_get_slider_value(smoothingslider); sprintf(buf,"Slider set to %f ",fl_get_slider_value(compressionslider)); /* set_message(buf);*/ tmpnam(tmpfilename); /* set_message ("Writing jpeg file");*/ write_JPEG_file(tmpfilename,gl_canvas,(int) fl_get_slider_value(compressionslider),(int) fl_get_slider_value(smoothingslider),lumtab, chromtab); /* set_message ("Reading jpeg");*/ read_JPEG_file(tmpfilename,gl_canvas2); /* set_message ("Viewing");*/ filesize=getfilesize(tmpfilename); unlink(tmpfilename); showfilesize(filesize,g_orig_file_size); winset(viewwin2); // tmp code for blocks //CopyGLCanvasIntoFImage(gl_canvas2,fi); //FindBlocks(fi); //CopyFImageIntoGLCanvas(fi,gl_canvas2); // drawmainwindow(gl_canvas2); } /*************************************************************************** S H O W F I L E S I Z E pass a zero (0) in compressedsize to blank the field ***************************************************************************/ void showfilesize(int compressedsize, int origsize) /*!*/ { char mess[250]; if (compressedsize==0) strcpy(mess," "); else sprintf(mess,"%d%% : %d / %d",(int)(100*compressedsize/origsize),compressedsize,origsize); fl_set_object_label(imagesizebox,mess); fl_redraw_object(imagesizebox); } /*************************************************************************** S E T _ M E S S A G E ***************************************************************************/ void set_message(char *mess) /*!*/ { fl_set_object_label(messagebox,mess); fl_redraw_object(messagebox); } /*************************************************************************** S E T U P V I E W S I Z E ***************************************************************************/ void setupviewsize(FL_OBJECT *obj,GLCanvas *gl_canvas) /*!*/ { float size; size=fl_get_menu(obj); gl_canvas->sizemultiplier=size; } /*************************************************************************** G E T F I L E S I Z E ***************************************************************************/ long getfilesize(char *name) /*!*/ { FILE *fp; fp=fopen(name,"r"); if (fp==NULL) return 0; fseek(fp,0,2); return ftell(fp); } /*************************************************************************** M A I N ***************************************************************************/ main(int argc , char **argv) { long dev; short val; GLCanvas *gl_canvas; GLCanvas gcs; FL_OBJECT *obj; FL_OBJECT *lastobject; GLCanvas *gl_canvas2; GLCanvas gcs2; char *filename; char tmpfilename[250]; unsigned int lum_tab[64]; unsigned int chrom_tab[64]; /* filename to process */ if (argc<2) { puts ("Usage: xjpeg filename.ppm"); exit(2); } filename=argv[1]; /* Create the form stuff */ fl_init(); create_the_forms(); forminit(); forms_win_id=fl_show_form(mainformwindow,FL_PLACE_MOUSE,TRUE,NULL); /* Open my sub window for the picmap */ initmywindows(); /* Load the canvas image */ gl_canvas= &gcs; gl_canvas2= &gcs2; gl_canvas2->pixels=NULL; gl_canvas->sizemultiplier=1.0; gl_canvas2->sizemultiplier=1.0; set_message ("Loading ppm..."); ppmLoadCanvas(filename, gl_canvas); g_orig_file_size=getfilesize(filename); set_message ("Inverting canvas"); invertcanvas(gl_canvas); //findBlocks(gl_canvas); set_message ("Converting to JSAMPLE"); jsamplebuff(gl_canvas); tmpnam(tmpfilename); set_message ("Writing jpeg file"); write_JPEG_file(tmpfilename,gl_canvas,20,0, NULL, NULL); gl_canvas2->lastcompression=20; set_message ("Reading jpeg"); read_JPEG_file(tmpfilename,gl_canvas2); set_message ("Viewing iamges..."); showfilesize(getfilesize(tmpfilename),g_orig_file_size); unlink(tmpfilename); drawCanvas(gl_canvas); fi=new FImage(gl_canvas->width,gl_canvas->height); CopyGLCanvasIntoFImage(gl_canvas2,fi); FindBlocks(fi); CopyFImageIntoGLCanvas(fi,gl_canvas2); winset(viewwin2); drawCanvas(gl_canvas2); /* Handle Events */ get_def_chrom_tab(chrom_tab); get_def_lum_tab(lum_tab); set_form_from_tab(lum_tab); set_message("Use ESC to exit\nUse the right mouse button for menus\n"); while (1) { obj = fl_check_forms(); if (obj==FL_EVENT) { dev = fl_qread(&val); if (dev == ESCKEY || dev == ENDKEY) exit(0); else if (dev ==LEFTMOUSE) { domouse(val, gl_canvas); } else if (dev == REDRAW) { winset(viewwin1); drawmainwindow(gl_canvas); winset(viewwin2); drawmainwindow(gl_canvas2); } } else if (obj==smoothingslider) { lastobject=smoothingslider; } else if (obj==compressionslider) { lastobject=compressionslider; } else if (obj==NULL && (lastobject==compressionslider || lastobject==smoothingslider)) { if (!getbutton(LEFTMOUSE)) { if (lastobject==smoothingslider) set_message( "Some images such as those from the GIF format do not JPEG compress well \n\ due to the dithering (high frequencies). The smoothing allows some of\n\ this to be corrected. To see what effect the smoothing alone is having\n\ on an image, set the quality slider to 100. "); else if (lastobject==compressionslider) set_message( "This slider sets the compression scaling factor applied to the quantization table.\n\ For settings 50..100, Q=200 - 2*quality. For settings 1..50, Q=5000/quality.\n\ The quantization table is then multiplied on a per term basis by Q/100.\n\ You'll notice that a setting of 50 passes the quantization table through unchanged. "); lastobject=NULL; check_for_recompress(gl_canvas,gl_canvas2,lum_tab,chrom_tab); } } else if (obj==viewsize1) { setupviewsize(obj,gl_canvas); winset(viewwin1); drawmainwindow(gl_canvas); } else if (obj==viewsize2) { setupviewsize(obj,gl_canvas2); winset(viewwin2); drawmainwindow(gl_canvas2); } else if (obj==quantchoice) { puts ("set quant choice"); if (fl_get_choice(quantchoice)==1) set_form_from_tab(lum_tab); else if (fl_get_choice(quantchoice)==2) set_form_from_tab(chrom_tab); set_message( "Choosing which quantization table to edit. JPEG compression occurs in a YUV color space. (Y) Luminance \n\ and (UV) Chrominance can have different quantization tables. Chrominance channels (U & V) share a \n\ quantization table. Changes are applied when the 'Set this quant tbl' button is pressed."); } else if (obj==defaultquantbutton) { puts ("set default quant "); if (fl_get_choice(quantchoice)==1) { get_def_lum_tab(lum_tab); set_form_from_tab(lum_tab); } else if (fl_get_choice(quantchoice)==2) { get_def_chrom_tab(chrom_tab); set_form_from_tab(chrom_tab); } else if (fl_get_choice(quantchoice)==3) { get_def_lum_tab(lum_tab); get_def_chrom_tab(chrom_tab); set_form_from_tab(lum_tab); fl_set_choice(quantchoice,1); } set_message("Default quantization table has been reset. Re-calcing image..."); do_recompress(gl_canvas,gl_canvas2,lum_tab,chrom_tab); } else if (obj==thisquantbutton) { puts ("set this quant "); if (fl_get_choice(quantchoice)==1) { get_tab_from_form(lum_tab); set_message("Luminance table set.\n\ Note that the quality slider will further modify the quantization table.\n\ To pass this table through unchanged, set the quality to 50."); } else if (fl_get_choice(quantchoice)==2) { get_tab_from_form(chrom_tab); set_message("Chrominance table set.\n\ Note that the quality slider will further modify the quantization table.\n\ To pass this table through unchanged, set the quality to 50."); } else if (fl_get_choice(quantchoice)==3) { get_tab_from_form(lum_tab); get_tab_from_form(chrom_tab); set_message("Luminance and chrominance tables set.\n\ Note that the quality slider will further modify the quantization table.\n\ To pass this table through unchanged, set the quality to 50."); } do_recompress(gl_canvas,gl_canvas2,lum_tab,chrom_tab); } else if (obj==peekbutton) { unsigned int tmp_tab[64]; unsigned int mod_tab[64]; int i; int qual; int temp; get_tab_from_form(tmp_tab); for (i=0;i<64;i++) { qual=jpeg_quality_scaling((int)(fl_get_slider_value(compressionslider))); mod_tab[i]=((long)tmp_tab[i] * qual + 50L) / 100L; if (mod_tab[i] <=0 ) mod_tab[i]=1; if (mod_tab[i] > 255 ) mod_tab[i]=255; } if (getbutton(LEFTMOUSE)) set_form_from_tab(mod_tab); set_message("\n\ Hold down to peek at the quantization table values after they have been modifed by the compression\n\ factor. This is the table that is actually handed to the JPEG quantization routines. You'll note\n\ that a compression setting of 100, results in a quantization table with all ones. i.e. No\n\ quantization, other than integer rounding. The quantization table values are clamped to 255."); while (getbutton(LEFTMOUSE)) ; set_form_from_tab(tmp_tab); } /* else if (obj==something);*/ } }