home *** CD-ROM | disk | FTP | other *** search
- #include "stdafx.h" // Access to Microsoft fundation classes
- #include "io.h"
- #include "math.h"
- #include "stdlib.h"
- #include "frac.h"
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- //////////////////////////////////////////////////////////////////////
- // CFracComp
- CFracComp::CFracComp(HWND hwnd,short id,BOOL output)
- {
-
- //Set display output device
- m_hwnd = hwnd;
- m_id = id;
- m_output = output;
- }
-
-
- CFracComp::~CFracComp()
- {
- // Delete DC context
- DeleteDC(m_MemDc);
- }
-
- void CFracComp::Reset()
- {
-
- m_hsize = -1;
- m_vsize = -1;
- m_subclass_search = 0,
- m_fullclass_search = 0,
- m_only_positive = 0;
- m_dom_step_type = 0;
- m_dom_type = 0;
- m_max_scale = 1.0;
- m_no_h_domains = NULL;
- m_domain_hstep = NULL;
- m_domain_vstep = NULL;
- m_bits_needed = NULL;
- m_output_partition=FALSE;
- m_image = NULL;
- m_imageDummy = NULL;
-
- // The class_transform gives the transforms between classification numbers for
- // negative scaling values, when brightest becomes darkest, etc...
- m_class_transform[0][0] = 23;
- m_class_transform[0][1] = 17;
- m_class_transform[0][2] = 21;
- m_class_transform[0][3] = 11;
- m_class_transform[0][4] = 15;
- m_class_transform[0][5] = 9;
- m_class_transform[0][6] = 22;
- m_class_transform[0][7] = 16;
- m_class_transform[0][8] = 19;
- m_class_transform[0][9] = 5;
- m_class_transform[0][10] = 13;
- m_class_transform[0][11] = 3;
- m_class_transform[0][12] = 20;
- m_class_transform[0][13] = 10;
- m_class_transform[0][14] = 18;
- m_class_transform[0][15] = 4;
- m_class_transform[0][16] = 7;
- m_class_transform[0][17] = 1;
- m_class_transform[0][18] = 14;
- m_class_transform[0][19] = 8;
- m_class_transform[0][20] = 12;
- m_class_transform[0][21] = 2;
- m_class_transform[0][22] = 6;
- m_class_transform[0][23] = 0;
- m_class_transform[1][0] = 16;
- m_class_transform[1][1] = 22;
- m_class_transform[1][2] = 10;
- m_class_transform[1][3] = 20;
- m_class_transform[1][4] = 8;
- m_class_transform[1][5] = 14;
- m_class_transform[1][6] = 17;
- m_class_transform[1][7] = 23;
- m_class_transform[1][8] = 4;
- m_class_transform[1][9] = 18;
- m_class_transform[1][10] = 2;
- m_class_transform[1][11] = 12;
- m_class_transform[1][12] = 11;
- m_class_transform[1][13] = 21;
- m_class_transform[1][14] = 5;
- m_class_transform[1][15] = 19;
- m_class_transform[1][16] = 0;
- m_class_transform[1][17] = 6;
- m_class_transform[1][18] = 9;
- m_class_transform[1][19] = 15;
- m_class_transform[1][20] = 3;
- m_class_transform[1][21] = 13;
- m_class_transform[1][22] = 1;
- m_class_transform[1][23] = 7;
-
- // rot_transform gives the rotations for domains with negative scalings.
- m_rot_transform[0][0] = 7;
- m_rot_transform[0][1] = 4;
- m_rot_transform[0][2] = 5;
- m_rot_transform[0][3] = 6;
- m_rot_transform[0][4] = 1;
- m_rot_transform[0][5] = 2;
- m_rot_transform[0][6] = 3;
- m_rot_transform[0][7] = 0;
- m_rot_transform[1][0] = 2;
- m_rot_transform[1][1] = 3;
- m_rot_transform[1][2] = 0;
- m_rot_transform[1][3] = 1;
- m_rot_transform[1][4] = 6;
- m_rot_transform[1][5] = 7;
- m_rot_transform[1][6] = 4;
- m_rot_transform[1][7] = 5;
-
- }
-
- void CFracComp::SetFileName(CString szfileIn, CString szfileOut)
- {
- //Set input file name
- m_szNameIn = szfileIn;
- //Set output file name
- m_szNameOut= szfileOut;
- }
-
- void CFracComp::Message(CString message)
- {
- if(!m_output)
- return;
- if(m_hwnd != NULL)
- {
- if(m_id < 0)
- {
- HDC nDC = GetDC(m_hwnd);
- TEXTMETRIC lpMetrics;
- GetTextMetrics(nDC,&lpMetrics);
- TextOut(nDC,0,abs(m_id--)*lpMetrics.tmHeight,message,message.GetLength());
- }
- else
- SetDlgItemText(m_hwnd,m_id,message);
- }
- printf("%s\n",message);
- }
-
- BOOL CFracComp::WriteRawFile(int hsz, int vsz, CString szOut)
- {
- int i,j;
- CString msg;
- // Open output file (decompression file)
- if ((m_FileOut = fopen(szOut, "wb")) == NULL)
- {
-
- Message("Error: Can't open output file");
- return FALSE;
-
- }
- // Write file to disk, a byte at a time
- // (Bug in _write function in VC 2.0)
- // force to write a byte at a time
- for(i =0; i<hsz;i++)
- for(j=0;j<vsz;j++)
- if((fputc(m_image[i][j],m_FileOut)) != m_image[i][j])
- {
- msg = "Error: Can't write byte to disk (Disk may be full)";
- Message(msg);
- return FALSE;
-
- }
-
-
- msg.Format("%d pixels written to %s.", hsz*vsz, szOut);
- Message(msg);
- fclose(m_FileOut);
- return TRUE;
- }
-
- BOOL CFracComp::ReadRawFile(int hsz, int vsz,CString szIn)
- {
- int i,handle;
- CString msg;
- if((handle= _open(szIn,_O_BINARY)) == -1)
- {
- if(handle == EACCES)
- msg = "Error: Tried to open read-only file for writing, or file's sharing mode does not allow specified operations, or given path is directory";
- if(handle == EMFILE)
- msg = "Error: No more file handles available (too many open files)";
- if(handle == ENOENT)
- msg = "Error: File or path not found";
- if(msg.IsEmpty())
- msg = "Error: Unknown Error has occured while open file";
- Message(msg);
- return FALSE;
- }
- for(i=0;i<hsz; i++)
- if((_read(handle,m_image[i],vsz)) != vsz)
- {
- msg = "Error: File is corrupted, can't read blocks";
- Message(msg);
- return FALSE;
- }
-
-
- msg.Format("%dx%d = %d pixels read from %s.", hsz,vsz,hsz*vsz,szIn);
- Message(msg);
- _close(handle);
- return TRUE;
- }
-
- HDC CFracComp::HandleDC()
- {
- // Handle to current DC context. If
- // Context is given this will have final
- // image
- return(m_MemDc);
- }
-
- HBITMAP CFracComp::HandleBitmap()
- {
- return(m_bitmap);
- }
-
- void CFracComp::Display(HWND pDest,int hsz,int vsz,CString stitle)
- {
- int color;
- SetWindowText(pDest,stitle);
- for (int dx = 0 ; dx < hsz; dx++)
- for (int cx = 0 ; cx < vsz ;cx++ )
- {
- color = m_image[dx][cx];
- SetPixelV(m_MemDc,cx,dx,m_colorTable[color]);
- }
-
- BitBlt(GetDC(pDest),0,0,hsz,vsz,m_MemDc,0,0,SRCCOPY);
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // Public Encoder and Decoder
- ///////////////////////////////////////////////////////////////////////////////////////
- void CFracComp::Compress(HWND hwndIn, double tolerance, int hsize, int vsize, int max_part, int min_part,
- int dom_step, int dom_step_type,int scaling_bit, int offset_bit, double max_scale, int divisor, BOOL positive,
- BOOL d24, BOOL d3)
- {
-
- int i,j,k;
- // Reset all values
- Reset();
- m_hsize = hsize;
- m_vsize = vsize;
- m_min_part = min_part;
- m_max_part = max_part;
- m_dom_step = dom_step;
- m_s_bits = scaling_bit;
- m_o_bits = offset_bit;
- m_max_scale = max_scale;
- m_dom_step_type = dom_step_type;
- m_dom_step_type = divisor;
- m_only_positive = positive;
- m_subclass_search = d24;
- m_fullclass_search = d3;
- CString msg;
-
- //Check for empty fileString string;
- if((m_szNameIn.IsEmpty()) || (m_szNameOut.IsEmpty()))
- {
-
- Message("Error: Input/Output name not given");
- return;
- }
- // Start wait cursor
- if(hwndIn != NULL)
- BeginWaitCursor();
-
- // allocate memory for the input image. Allocating one chunck saves
- // work and time later.
- unsigned char *row_image;
- m_image = (unsigned char **)malloc((m_vsize)*sizeof(unsigned char *));
- row_image = (unsigned char *)malloc((long)(m_hsize)*(long)(m_vsize)*sizeof(unsigned char));
- if (row_image == NULL)
- {
-
- Message("Error: Out of memory from image buffer");
- return;
- }
- for (i = 0; i<m_vsize; ++i, row_image += m_hsize)
- m_image[i] = row_image;
-
- double *row_domimage0;
- m_domimage[0] = (double **)malloc((m_vsize/2)*sizeof(double *));
- row_domimage0 = (double *)malloc((long)(m_hsize/2)*(long)(m_vsize/2)*sizeof(double));
- if (row_domimage0 == NULL)
- {
- Message("Error: Out of memory for domain buffer");
- return;
- }
- for (i = 0; i<m_vsize/2; ++i, row_domimage0 += m_hsize/2)
- m_domimage[0][i] = row_domimage0;
-
- double *row_domimage1;
- m_domimage[1] = (double **)malloc((m_vsize/2)*sizeof(double *));
- row_domimage1 = (double *)malloc((long)(m_hsize/2)*(long)(m_vsize/2)*sizeof(double));
- if (row_domimage1 == NULL)
- {
-
- msg = "Error: Out of memory for domain buffer";
- Message(msg);
- return;
- }
- for (i = 0; i<m_vsize/2; ++i, row_domimage1 += m_hsize/2)
- m_domimage[1][i] = row_domimage1;
-
- double *row_domimage2;
- m_domimage[2] = (double **)malloc((m_vsize/2)*sizeof(double *));
- row_domimage2 = (double *)malloc((long)(m_hsize/2)*(long)(m_vsize/2)*sizeof(double));
- if (row_domimage2 == NULL)
- {
- msg = "Error: Out of memory for domain buffer";
- Message(msg);
- return;
- }
- for (i = 0; i<m_vsize/2; ++i, row_domimage2 += m_hsize/2)
- m_domimage[2][i] = row_domimage2;
-
- double *row_domimage3;
- m_domimage[3] = (double **)malloc((m_vsize/2)*sizeof(double *));
- row_domimage3 = (double *)malloc((long)(m_hsize/2)*(long)(m_vsize/2)*sizeof(double));
- if (row_domimage3 == NULL)
- {
- msg = "Error: Out of memory for domain buffer";
- Message(msg);
- return;
- }
- for (i = 0; i<m_vsize/2; ++i, row_domimage3 += m_hsize/2)
- m_domimage[3][i] = row_domimage3;
-
-
- // max_ & min_ part are variable, so this must be run time allocated
- m_bits_needed = (int *)malloc(sizeof(int)*(1+m_max_part-m_min_part));
-
-
-
- if(!ReadRawFile(hsize,vsize,m_szNameIn))
- return;
-
- // allcate memory for domain data and initialize it
- if(!Compute_Sums(m_hsize,m_vsize))
- return;
-
- if ((m_FileOut = fopen(m_szNameOut, "wb")) == NULL)
- {
- msg = "Error: Can't open output file";
- Message(msg);
- return;
- }
-
- // output some data into the outputfile.
- Pack(4,(long)m_min_part);
- Pack(4,(long)m_max_part);
- Pack(4,(long)m_dom_step);
- Pack(1,(long)m_dom_step_type);
- Pack(2,(long)m_dom_type);
- Pack(12,(long)m_hsize);
- Pack(12,(long)m_vsize);
-
- // This is the quantized value of zero scaling.. needed later
- m_zero_ialpha = 0.5 + (m_max_scale)/(2.0*m_max_scale)*(1<<m_s_bits);
-
- // The following routine takes a rectangular image and calls the
- // quadtree routine to encode square sum-images in it.
- // the tolerance is a parameter since in some applications different
- // regions of the image may need to be compressed to different tol's
-
- Message("Encoding image.....");
- if(hwndIn != NULL)
- {
- // Delete old context device (just in case)
- DeleteDC(m_MemDc);
- // Create compatible with display device
- m_MemDc = CreateCompatibleDC(GetDC(hwndIn));
- CRect rect;
- GetWindowRect(hwndIn,rect);
- // Set Window size to picture size;
- SetWindowPos(hwndIn,HWND_TOP,rect.left,rect.top,m_vsize,m_hsize,SWP_SHOWWINDOW);
- m_bitmap = CreateCompatibleBitmap(GetDC(hwndIn),m_vsize,m_hsize);
- SelectObject(m_MemDc,m_bitmap);
- for (i= 0; i<255; i++)
- m_colorTable[i] = GetNearestColor(m_MemDc,RGB(i,i,i));
- ShowWindow(hwndIn,SW_SHOW);
- Display(hwndIn,m_hsize,m_hsize,CString("Loading image...."));
- MoveToEx(m_MemDc,(0+m_hsize/2),0,NULL);
- LineTo(m_MemDc,(0+m_hsize/2),m_vsize);
- MoveToEx(m_MemDc,0,(0+m_hsize/2),NULL);
- LineTo(m_MemDc,m_hsize,(0+m_vsize/2));
- SetWindowText(hwndIn,"Quadtree starting....");
- BitBlt(GetDC(hwndIn),0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
-
- Partition_Image(0, 0, m_hsize,m_vsize, tolerance, hwndIn);
-
- Message("Done");
-
- // stuff the last byte if needed
- Pack(-1,(long)0);
-
- fclose(m_FileOut);
- i = Pack(-2,(long)0);
- msg.Format("Compression = %lf from %d bytes written in %s.",
- (double)(m_hsize*m_vsize)/(double)i, i, m_szNameOut);
- Message(msg);
-
- // Free allocated memory
- free(m_bits_needed);
- free(m_domimage[0]);
- free(m_domimage[1]);
- free(m_domimage[2]);
- free(m_domimage[3]);
- free(m_domain.no_h_domains);
- free(m_domain.no_v_domains);
- free(m_domain.domain_hsize);
- free(m_domain.domain_vsize);
- free(m_domain.domain_hstep);
- free(m_domain.domain_vstep);
- for (i=0; i <= m_max_part-m_min_part; ++i)
- free(m_domain.pixel[i]);
- free(m_domain.pixel);
- free(m_image[0]);
- // free memory allocated in the list structure the_domain
- struct classified_domain *node;
- struct classified_domain *tempnode;
- for (i=0; i <= m_max_part-m_min_part; ++i)
- for (k=0; k<3; ++k)
- for (j=0; j<24; ++j)
- {
- node =m_dd_domain[k][j][i];
- while(node->next != NULL)
- {
- tempnode = node;
- node = node->next;
- free(tempnode);
- }
- free(node);
- }
- SetWindowText(hwndIn,"Done.");
- // End wait cursor
- if(hwndIn != NULL)
- EndWaitCursor();
-
- }
-
- void CFracComp::Decompress(HWND hwndOut,int scale, int iterations, BOOL process,
- double maximum_scale, int scaling_bit, int offset_bit, BOOL output_p)
- {
-
-
- //Counter variables
- int i;
- int x_exponent, y_exponent;
- int domain_size,no_domains;
- int scaledvsize,scaledhsize;
- CString msg;
- // Reset all values
- Reset();
- //Scaling factor
- m_scaledfactor = scale;
- m_min_part = 3;
- m_max_part = 4;
- m_dom_step = 4;
- m_output_partition = output_p;
- m_s_bits = scaling_bit;
- m_o_bits = offset_bit;
- m_max_scale = maximum_scale;
- //Check for empty fileString string;
- if((m_szNameIn.IsEmpty()) || (m_szNameOut.IsEmpty()))
- {
-
- Message("Error: Input/Output name not given");
- return;
- }
- // Open compression file
- if ((m_FileIn = fopen(m_szNameIn, "rb")) == NULL)
- {
-
- Message("Error: Can't open Input file");
- return;
- }
- if(hwndOut != NULL)
- BeginWaitCursor();
- Unpack(-2); // initialize the unpacking routine
-
- // read the header data from the input file. This should probably
- // be put into one read which reads a structure with the info
- m_min_part = (int)Unpack(4);
- m_max_part = (int)Unpack(4);
- m_dom_step = (int)Unpack(4);
- m_dom_step_type = (int)Unpack(1);
- m_dom_type = (int)Unpack(2);
- m_hsize = (int)Unpack(12);
- m_vsize = (int)Unpack(12);
-
- // we now compute size
- x_exponent = (int)floor(log((double)m_hsize)/log(2.0));
- y_exponent = (int)floor(log((double)m_vsize)/log(2.0));
-
- // exponent is min of x_ and y_ exponent
- m_max_exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
- // size is the size of the largest square that fits in the image
- // It is used to compute the domain and range sizes.
- m_size = 1<<m_max_exponent;
-
- // This is the quantized value of zero scaling
- m_zero_ialpha = 0.5 + (m_max_scale)/(2.0*m_max_scale)*(1<<m_s_bits);
-
- // allocate memory for the output image. Allocating one chunck saves
- // work and time later.
- scaledhsize = (int)(m_scaledfactor*m_hsize);
- scaledvsize = (int)(m_scaledfactor*m_vsize);
- if(hwndOut != NULL)
- {
- // Delete old context device (just in case)
- DeleteDC(m_MemDc);
- // Create compatible with display device
- m_MemDc = CreateCompatibleDC(GetDC(hwndOut));
- CRect rect;
- GetWindowRect(hwndOut,rect);
- // Set Window size to picture size;
- SetWindowPos(hwndOut,HWND_TOP,rect.left,rect.top,scaledvsize,scaledhsize,SWP_SHOWWINDOW);
- m_bitmap = CreateCompatibleBitmap(GetDC(hwndOut),scaledvsize,scaledhsize);
- SelectObject(m_MemDc,m_bitmap);
- // Create a valid color table for this device
- for (i= 0; i<255; i++)
- m_colorTable[i] = GetNearestColor(m_MemDc,RGB(i,i,i));
- }
- // Allocate memory for image and dummy image.
- unsigned char *row_image;
- m_image = (unsigned char **)malloc(scaledvsize*sizeof(unsigned char *));
- row_image = (unsigned char*)malloc((long)scaledhsize*(long)scaledvsize*sizeof(unsigned char));
- if (row_image == NULL)
- {
-
- Message("Error: Out of memory for image buffer");
- return;
- }
- for (i = 0; i<scaledvsize; ++i, row_image += scaledhsize)
- m_image[i] = row_image;
-
- unsigned char *row_imageDummy;
- m_imageDummy = (unsigned char **)malloc(scaledvsize*sizeof(unsigned char *));
- row_imageDummy = (unsigned char *)malloc((long)scaledhsize*(long)scaledvsize*sizeof(unsigned char));
- if (row_imageDummy == NULL)
- {
-
- Message("Error: Out of memory for image secondary buffer");
- return;
- }
- for (i = 0; i<scaledvsize; ++i, row_imageDummy += scaledhsize)
- m_imageDummy[i] = row_imageDummy;
-
-
-
- // since max_ and min_ part are variable, these must be allocated
- i = m_max_part - m_min_part + 1;
- m_bits_needed = (int *)malloc(sizeof(int)*i);
- m_no_h_domains = (int *)malloc(sizeof(int)*i);
- m_domain_hstep = (int *)malloc(sizeof(int)*i);
- m_domain_vstep = (int *)malloc(sizeof(int)*i);
-
- // compute bits needed to read each domain type
- for (i=0; i <= m_max_part-m_min_part; ++i) {
- // first compute how many domains there are horizontally
- domain_size = m_size >> (m_min_part+i-1);
- if (m_dom_type == 2)
- m_domain_hstep[i] = m_dom_step;
- else if (m_dom_type == 1)
- if (m_dom_step_type ==1)
- m_domain_hstep[i] = (m_size >> (m_max_part - i-1))*m_dom_step;
- else
- m_domain_hstep[i] = (m_size >> (m_max_part - i-1))/m_dom_step;
- else
- if (m_dom_step_type ==1)
- m_domain_hstep[i] = domain_size*m_dom_step;
- else
- m_domain_hstep[i] = domain_size/m_dom_step;
-
- m_no_h_domains[i] = 1+(m_hsize-domain_size)/m_domain_hstep[i];
-
- // now compute how many domains there are vertically
- if (m_dom_type == 2)
- m_domain_vstep[i] = m_dom_step;
- else if (m_dom_type == 1)
- if (m_dom_step_type ==1)
- m_domain_vstep[i] = (m_size >> (m_max_part - i-1))*m_dom_step;
- else
- m_domain_vstep[i] = (m_size >> (m_max_part - i-1))/m_dom_step;
- else
- if (m_dom_step_type ==1)
- m_domain_vstep[i] = domain_size*m_dom_step;
- else
- m_domain_vstep[i] = domain_size/m_dom_step;
-
- no_domains = 1+(m_vsize-domain_size)/m_domain_vstep[i];
- m_bits_needed[i] = ceil(log((double)no_domains*(double)m_no_h_domains[i])/log(2.0));
- }
- // Open output file (decompression file)
- if ((m_FileOut = fopen(m_szNameOut, "wb")) == NULL)
- {
-
- Message("Error: Can't open output file");
- return;
-
- }
-
- // Read in the transformation data
- m_trans = &m_transformations;
-
- Message("Reading transformation....");
-
- Partition_Image(0, 0, m_hsize,m_vsize );
- fclose(m_FileIn);
-
- Message("Done");
-
-
-
- // when we output the partition, we just read the transformations
- // in and write them to the outputfile
- if (m_output_partition)
- {
- // Open output file (decompression file)
- if ((m_FileOut = fopen(m_szNameOut, "wb")) == NULL)
- {
-
- Message("Error: Can't open output file");
- return;
-
- }
- fprintf(m_FileOut,"\n%d %d\n %d %d\n%d %d\n\n",
- 0, 0, scaledhsize, 0, scaledhsize, scaledvsize);
-
- msg.Format("Outputed partition data in %s.",m_szNameOut);
- Message(msg);
-
- fclose(m_FileOut);
- return;
- }
-
- if(hwndOut != NULL)
- ShowWindow(hwndOut,SW_SHOW);
- // Apply transformation
- for (i=0; i<iterations; ++i)
- if(hwndOut != NULL)
- {
- msg.Format("Processing ... [%d%%]",(i*100)/iterations);
- Apply_Transformations(hwndOut,msg);
- }
- else
- Apply_Transformations(NULL,"");
- // Fix, edges for a smoother image
- if (process)
- if(hwndOut != NULL)
- Smooth_Image(hwndOut);
- else
- Smooth_Image(NULL);
- // Write Data to file.
- if(!WriteRawFile(scaledhsize,scaledvsize,m_szNameOut))
- return;
- SetWindowText(hwndOut,"Done.");
- free(m_image);
- free(m_imageDummy);
- if(hwndOut != NULL)
- EndWaitCursor();
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // Private Decoding routines
- ///////////////////////////////////////////////////////////////////////////////////////
- void CFracComp::Smooth_Image(HWND hdcOut)
- {
- unsigned char pixel1, pixel2;
- int i,j;
- int w1,w2;
-
-
- Message("Postprocessing Image.");
-
- m_trans = &m_transformations;
- while (m_trans->next != NULL) {
- m_trans = m_trans->next;
- if (m_trans->rx == 0 || m_trans->ry == 0)
- continue;
-
- if (m_trans->depth == m_max_part)
- {
- w1 = 5;
- w2 = 1;
- } else {
- w1 = 2;
- w2 = 1;
- }
-
- for (i=m_trans->rx; i<m_trans->rrx; ++i) {
- pixel1 = m_image[(int)m_trans->ry][i];
- pixel2 = m_image[(int)m_trans->ry-1][i];
- m_image[(int)m_trans->ry][i] = (w1*pixel1 + w2*pixel2)/(w1+w2);
- m_image[(int)m_trans->ry-1][i] = (w2*pixel1 + w1*pixel2)/(w1+w2);
- }
-
- for (j=m_trans->ry; j<m_trans->rry; ++j) {
- pixel1 = m_image[j][(int)m_trans->rx];
- pixel2 = m_image[j][(int)m_trans->rx-1];
- m_image[j][(int)m_trans->rx] = (w1*pixel1 + w2*pixel2)/(w1+w2);
- m_image[j][(int)m_trans->rx-1] = (w2*pixel1 + w1*pixel2)/(w1+w2);
- }
- }
- if(hdcOut != NULL)
- Display(hdcOut,m_hsize*m_scaledfactor,m_vsize*m_scaledfactor,CString("Post Processing..."));
- }
-
- void CFracComp::Partition_Image(int atx, int aty, int hsize, int vsize )
- {
- int x_exponent, // the largest power of 2 image size that fits
- y_exponent, // horizontally or vertically the rectangle.
- exponent, // The actual size of image that's encoded.
- size,
- depth;
-
- x_exponent = (int)floor(log((double)hsize)/log(2.0));
- y_exponent = (int)floor(log((double)vsize)/log(2.0));
-
- // exponent is min of x_ and y_ exponent
- exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
- size = 1<<exponent;
- depth = m_max_exponent - exponent;
-
- Read_Transformations(atx,aty,size,size,depth);
-
- if (size != hsize)
- Partition_Image(atx+size, aty, hsize-size,vsize );
-
- if (size != vsize)
- Partition_Image(atx, aty+size, size,vsize-size );
- }
-
-
- void CFracComp::Apply_Transformations(HWND hdcOut,CString stitle)
- {
- unsigned char **tempimage;
- int i,j,i1,j1,count=0;
- double pixel;
- CString msg;
- m_trans = &m_transformations;
- while (m_trans->next != NULL)
- {
- m_trans = m_trans->next;
- ++count;
-
- // Since the inner loop is the same in each case of the switch below
- // we just define it once for easy modification.
-
- switch(m_trans->sym_op)
- {
- case 0: for (i=m_trans->rx, i1 = m_trans->dx;i<m_trans->rrx; ++i, i1 += 2)
- for (j=m_trans->ry, j1 = m_trans->dy;j<m_trans->rry; ++j, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
-
- case 1: for (j=m_trans->ry, i1 = m_trans->dx;j<m_trans->rry; ++j, i1 += 2)
- for (i=m_trans->rrx-1,j1 = m_trans->dy; i>=(int)m_trans->rx; --i, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
- case 2: for (i=m_trans->rrx-1,i1 = m_trans->dx; i>=(int)m_trans->rx; --i, i1 += 2)
- for (j=m_trans->rry-1,j1 = m_trans->dy; j>=(int)m_trans->ry; --j, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
-
- case 3: for (j=m_trans->rry-1,i1 = m_trans->dx; j>=(int)m_trans->ry; --j, i1 += 2)
- for (i=m_trans->rx, j1 = m_trans->dy;i<m_trans->rrx; ++i, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
-
- case 4: for (j=m_trans->ry, i1 = m_trans->dx;j<m_trans->rry; ++j, i1 += 2)
- for (i=m_trans->rx, j1 = m_trans->dy;i<m_trans->rrx; ++i, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
-
- case 5: for (i=m_trans->rx, i1 = m_trans->dx;i<m_trans->rrx; ++i, i1 += 2)
- for (j=m_trans->rry-1,j1 = m_trans->dy; j>=(int)m_trans->ry; --j, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
-
- case 6: for (j=m_trans->rry-1,i1 = m_trans->dx; j>=(int)m_trans->ry; --j, i1 += 2)
- for (i=m_trans->rrx-1,j1 = m_trans->dy; i>=(int)m_trans->rx; --i, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
- case 7: for (i=m_trans->rrx-1,i1 = m_trans->dx; i>=(int)m_trans->rx; --i, i1 += 2)
- for (j=m_trans->ry, j1 = m_trans->dy; j<m_trans->rry; ++j, j1 += 2)
- {
- pixel = (m_image[j1][i1]+m_image[j1][i1+1]+m_image[j1+1][i1]+m_image[j1+1][i1+1])/4.0;
- m_imageDummy[j][i] = bound(0.5 + m_trans->scale*pixel+m_trans->offset);
- }
-
- break;
- }
-
- }
- tempimage = m_image;
- m_image = m_imageDummy;
- m_imageDummy = tempimage;
-
- msg.Format("%d transformations applied.",count);
- Message(msg);
- if(hdcOut != NULL)
- Display(hdcOut,m_hsize*m_scaledfactor,m_vsize*m_scaledfactor,stitle);
-
- }
-
- void CFracComp::Read_Transformations(int atx, int aty, int xsize, int ysize, int depth)
- {
-
- // Locals in a recursive procedure
-
- int ialpha, // Intgerized scaling factor
- ibeta; // Intgerized offset
-
- long domain_ref;
-
- double alpha, beta;
-
- // keep breaking it down until we are small enough
- if (depth < m_min_part) {
- Read_Transformations(atx,aty, xsize/2, ysize/2, depth+1);
- Read_Transformations(atx+xsize/2,aty, xsize/2, ysize/2, depth+1);
- Read_Transformations(atx,aty+ysize/2,xsize/2, ysize/2, depth+1);
- Read_Transformations(atx+xsize/2,aty+ysize/2,xsize/2,ysize/2,depth+1);
- return;
- }
-
- if (depth < m_max_part && Unpack(1)) {
- // A 1 means we subdivided.. so quadtree
- Read_Transformations(atx,aty, xsize/2, ysize/2, depth+1);
- Read_Transformations(atx+xsize/2,aty, xsize/2, ysize/2, depth+1);
- Read_Transformations(atx,aty+ysize/2, xsize/2, ysize/2, depth+1);
- Read_Transformations(atx+xsize/2,aty+ysize/2,xsize/2,ysize/2,depth+1);
- } else {
- // we have a transformation to read
- m_trans->next = (struct transformation_node *)
- malloc(sizeof(struct transformation_node ));
- m_trans = m_trans->next;
- m_trans->next = NULL;
- ialpha = (int)Unpack(m_s_bits);
- ibeta = (int)Unpack(m_o_bits);
- alpha = (double)ialpha/(double)(1<<m_s_bits)*(2.0*m_max_scale)-m_max_scale;
-
- beta = (double)ibeta/(double)((1<<m_o_bits)-1)*
- ((1.0+fabs(alpha))*GREY_LEVELS);
- if (alpha > 0.0) beta -= alpha*GREY_LEVELS;
-
- m_trans->scale = alpha;
- m_trans->offset = beta;
- if (ialpha != m_zero_ialpha) {
- m_trans-> sym_op = (int)Unpack(3);
- domain_ref = Unpack(m_bits_needed[depth-m_min_part]);
- m_trans->dx = (double)(domain_ref % m_no_h_domains[depth-m_min_part])
- * m_domain_hstep[depth-m_min_part];
- m_trans->dy = (double)(domain_ref / m_no_h_domains[depth-m_min_part])
- * m_domain_vstep[depth-m_min_part];
- } else {
- m_trans-> sym_op = 0;
- m_trans-> dx = 0;
- m_trans-> dy = 0;
- }
- m_trans->rx = atx;
- m_trans->ry = aty;
- m_trans->depth = depth;
-
- m_trans->rrx = atx + xsize;
- m_trans->rry = aty + ysize;
- //Apply scaling factor
- m_trans->rrx *= m_scaledfactor;
- m_trans->rry *= m_scaledfactor;
- m_trans->rx *= m_scaledfactor;
- m_trans->ry *= m_scaledfactor;
- m_trans->dx *= m_scaledfactor;
- m_trans->dy *= m_scaledfactor;
-
- if (m_output_partition)
- fprintf(m_FileOut,"\n%d %d\n %d %d\n%d %d\n\n",
- atx, m_vsize-aty-ysize,
- atx, m_vsize-aty,
- atx+xsize, m_vsize-aty);
-
- }
-
- }
-
- long CFracComp::Unpack(int size)
- {
- int i;
- int value = 0;
- static int ptr = 1; // how many bits are packed in sum so far
- static int sum;
-
-
- // size == -2 means we initialize things
- if (size == -2) {
- sum = fgetc(m_FileIn);
- sum <<= 1;
- return((long)0);
- }
-
- // size == -1 means we want to peek at the next bit without
- // advancing the pointer
- if (size == -1)
- return((long)((sum&256)>>8));
-
- for (i=0; i<size; ++i, ++ptr, sum <<= 1) {
- if (sum & 256) value |= 1<<i;
-
- if (ptr == 8) {
- sum = getc(m_FileIn);
- ptr=0;
- }
- }
- return((long)value);
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- // Private Encoding routines
- ///////////////////////////////////////////////////////////////////////////////////////
- void CFracComp::Classify(int x, int y, int xsize, int ysize, int *pfirst, int *psecond,
- int *psym, double *psum, double *psum2, int type)
- {
-
- int order[4], i,j;
- double a[4],a2[4];
-
- // Get the average values of each quadrant
- if (type == 2)
- {
- Average(x,y,xsize/2,ysize/2,&a[0], &a2[0]);
- Average(x,y+ysize/2,xsize/2,ysize/2,&a[1], &a2[1]);
- Average(x+xsize/2,y+ysize/2, xsize/2,ysize/2, &a[2],&a2[2]);
- Average(x+xsize/2,y,xsize/2,ysize/2,&a[3],&a2[3]);
-
- }
- else
- {
- Average1(x,y,xsize/2,ysize/2,&a[0], &a2[0]);
- Average1(x,y+ysize/2,xsize/2,ysize/2,&a[1], &a2[1]);
- Average1(x+xsize/2,y+ysize/2, xsize/2,ysize/2, &a[2],&a2[2]);
- Average1(x+xsize/2,y,xsize/2,ysize/2,&a[3],&a2[3]);
-
- }
-
-
- *psum = a[0] + a[1] + a[2] + a[3];
- *psum2 = a2[0] + a2[1] + a2[2] + a2[3];
-
- for (i=0; i<4; ++i) {
- // after the sorting below order[i] is the i-th brightest quadrant.
- order[i] = i;
- // convert a2[] to store the variance of each quadrant
- a2[i] -= (double)(1<<(2*type))*a[i]*a[i]/(double)(xsize*ysize);
- }
-
- // Now order the average value and also in order[], which will
- // then tell us the indices (in a[]) of the brightest to darkest
- for (i=2; i>=0; --i)
- for (j=0; j<=i; ++j)
- if (a[j]<a[j+1]) {
- swap(order[j], order[j+1],int)
- swap(a[j], a[j+1],double)
- }
-
- // because of the way we ordered the a[] the rotation can be
- // read right off of order[]. That will make the brightest
- // quadrant be in the upper left corner. But we must still
- // decide which cannonical class the image portion belogs
- // to and whether to do a flip or just a rotation. This is
- // the following table summarizes the horrid lines below
- // order class do a rotation
- // 0,2,1,3 0 0
- // 0,2,3,1 0 1
- // 0,1,2,3 1 0
- // 0,3,2,1 1 1
- // 0,1,3,2 2 0
- // 0,3,1,2 2 1
-
- *psym = order[0];
- // rotate the values
- for (i=0; i<4; ++i)
- order[i] = (order[i] - (*psym) + 4)%4;
-
- for (i=0; order[i] != 2; ++i);
- *pfirst = i-1;
- if (order[3] == 1 || (*pfirst == 2 && order[2] == 1)) *psym += 4;
-
- //Now further classify the sub-image by the variance of its
- // quadrants. This give 24 subclasses for each of the 3 classes
- for (i=0; i<4; ++i) order[i] = i;
-
- for (i=2; i>=0; --i)
- for (j=0; j<=i; ++j)
- if (a2[j]<a2[j+1]) {
- swap(order[j], order[j+1],int)
- swap(a2[j], a2[j+1],double)
- }
-
- // Now do the symmetry operation
- for (i=0; i<4; ++i)
- order[i] = (order[i] - (*psym%4) + 4)%4;
- if (*psym > 3)
- for (i=0; i<4; ++i)
- if (order[i]%2) order[i] = (2 + order[i])%4;
-
- // We want to return a class number from 0 to 23 depending on
- // the ordering of the quadrants according to their variance
- *psecond = 0;
- for (i=2; i>=0; --i)
- for (j=0; j<=i; ++j)
- if (order[j] > order[j+1]) {
- swap(order[j],order[j+1], int);
- if (order[j] == 0 || order [j+1] == 0)
- *psecond += 6;
- else if (order[j] == 1 || order [j+1] == 1)
- *psecond += 2;
- else if (order[j] == 2 || order [j+1] == 2)
- *psecond += 1;
- }
- }
-
- BOOL CFracComp::Compute_Sums(int hsize, int vsize)
- {
- int i,j,k,l,
- domain_x,
- domain_y,
- first_class,
- second_class,
- size,
- x_exponent,
- y_exponent;
-
- struct classified_domain *node;
-
- Message("Computing domain sums... ");
-
-
- fflush(stdout);
-
- // pre-decimate the image into domimage to avoid having to
- // do repeated averaging of 2x2 pixel groups.
- // There are 4 ways to decimate the image, depending on the
- // location of the domain, odd or even address.
- for (i=0; i<2; ++i)
- for (j=0; j<2; ++j)
- for (k=i; k<hsize-i; k += 2)
- for (l=j; l<vsize-j; l += 2)
- m_domimage[(i<<1)+j][l>>1][k>>1] =
- ((double)m_image[l][k] + (double)m_image[l+1][k+1] +
- (double)m_image[l][k+1] + (double)m_image[l+1][k])*0.25;
-
-
- // Allocate memory for the sum and sum^2 of domain pixels
- // We first compute the size of the largest square that fits in
- // the image.
- x_exponent = (int)floor(log((double)hsize)/log(2.0));
- y_exponent = (int)floor(log((double)vsize)/log(2.0));
-
- // exponent is min of x_ and y_ exponent
- m_max_exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
-
- // size is the size of the largest square that fits in the image
- // It is used to compute the domain and range sizes.
- size = 1<<m_max_exponent;
-
- if (m_max_exponent < m_max_part)
- {
-
- Message("Error: Partition is absurd range");
- return FALSE;
- }
- if (m_max_exponent-2 < m_max_part)
- Message("Warning: so many quadtree partitions yield absurd ranges.");
-
-
-
- i = m_max_part - m_min_part + 1;
- m_domain.no_h_domains = (int *)malloc(sizeof(int)*i);
- m_domain.no_v_domains = (int *)malloc(sizeof(int)*i);
- m_domain.domain_hsize = (int *)malloc(sizeof(int)*i);
- m_domain.domain_vsize = (int *)malloc(sizeof(int)*i);
- m_domain.domain_hstep = (int *)malloc(sizeof(int)*i);
- m_domain.domain_vstep = (int *)malloc(sizeof(int)*i);
-
- m_domain.pixel= (struct domain_pixels ***)
- malloc(i*sizeof(struct domain_pixels **));
-
- if (m_domain.pixel == NULL)
- {
- Message("Error: Input/Output name not given");
- return FALSE;
- }
-
- for (i=0; i <= m_max_part-m_min_part; ++i) {
- // first compute how many domains there are horizontally
- m_domain.domain_hsize[i] = size >> (m_min_part+i-1);
- if (m_dom_type == 2)
- m_domain.domain_hstep[i] = m_dom_step;
- else if (m_dom_type == 1)
- if (m_dom_step_type == 1)
- m_domain.domain_hstep[i] = (size >> (m_max_part - i-1))*m_dom_step;
- else
- m_domain.domain_hstep[i] = (size >> (m_max_part - i-1))/m_dom_step;
- else
- if (m_dom_step_type == 1)
- m_domain.domain_hstep[i] = m_domain.domain_hsize[i]*m_dom_step;
- else
- m_domain.domain_hstep[i] = m_domain.domain_hsize[i]/m_dom_step;
-
- m_domain.no_h_domains[i] = 1+(hsize-m_domain.domain_hsize[i])/m_domain.domain_hstep[i];
-
- m_domain.domain_vsize[i] = size >> (m_min_part+i-1);
- if (m_dom_type == 2)
- m_domain.domain_vstep[i] = m_dom_step;
- else if (m_dom_type == 1)
- if (m_dom_step_type == 1)
- m_domain.domain_vstep[i] = (size >> (m_max_part - i-1))*m_dom_step;
- else
- m_domain.domain_vstep[i] = (size >> (m_max_part - i-1))/m_dom_step;
- else
- if (m_dom_step_type == 1)
- m_domain.domain_vstep[i] = m_domain.domain_vsize[i]*m_dom_step;
- else
- m_domain.domain_vstep[i] = m_domain.domain_vsize[i]/m_dom_step;
-
- m_domain.no_v_domains[i] = 1+(vsize-m_domain.domain_vsize[i])/m_domain.domain_vstep[i];
-
- // Now compute the number of bits needed to store the domain data
- m_bits_needed[i] = ceil(log((double)m_domain.no_h_domains[i]*
- (double)m_domain.no_v_domains[i])/log(2.0));
-
- struct domain_pixels *row_domain_pixel;
- m_domain.pixel[i]= (struct domain_pixels **)malloc((m_domain.no_v_domains[i])*sizeof(struct domain_pixels *));
- row_domain_pixel = (struct domain_pixels*)malloc((long)(m_domain.no_h_domains[i])*(long)(m_domain.no_v_domains[i])*sizeof(struct domain_pixels));
- if(row_domain_pixel == NULL)
- {
- Message("Error: Out of memory for image buffer");
- return FALSE;
- }
- for (int _i = 0; _i<m_domain.no_v_domains[i]; ++_i, row_domain_pixel += m_domain.no_h_domains[i])
- m_domain.pixel[i][_i] = row_domain_pixel;
-
-
- }
-
- // allocate and zero the list containing the classified domain data
- i = m_max_part - m_min_part + 1;
- for (first_class = 0; first_class < 3; ++first_class)
- for (second_class = 0; second_class < 24; ++second_class) {
- m_dd_domain[first_class][second_class] =
- (struct classified_domain **)
- malloc(i*sizeof(struct classified_domain *));
- for (j=0; j<i; ++j)
- m_dd_domain[first_class][second_class][j] = NULL;
- }
-
- // Precompute sum and sum of squares for domains
- // This part can get faster for overlapping domains if repeated
- // sums are avoided
- for (i=0; i <= m_max_part-m_min_part; ++i) {
- for (j=0,domain_x=0; j<m_domain.no_h_domains[i]; ++j,
- domain_x+=m_domain.domain_hstep[i])
- for (k=0,domain_y=0; k<m_domain.no_v_domains[i]; ++k,
- domain_y+=m_domain.domain_vstep[i]) {
- Classify(domain_x, domain_y,
- m_domain.domain_hsize[i],
- m_domain.domain_vsize[i],
- &first_class, &second_class,
- &m_domain.pixel[i][k][j].sym,
- &m_domain.pixel[i][k][j].sum,
- &m_domain.pixel[i][k][j].sum2, 2);
-
- // When the domain data is referenced from the list, we need to
- // know where the domain is.. so we have to store the position
- m_domain.pixel[i][k][j].dom_x = j;
- m_domain.pixel[i][k][j].dom_y = k;
- node = (struct classified_domain *)
- malloc(sizeof(struct classified_domain));
-
- // put this domain in the classified list structure
- node->dd = &m_domain.pixel[i][k][j];
- node->next = m_dd_domain[first_class][second_class][i];
- m_dd_domain[first_class][second_class][i] = node;
- }
- }
-
- // Now we make sure no domain class is actually empty.
- for (i=0; i <= m_max_part-m_min_part; ++i)
- for (first_class = 0; first_class < 3; ++first_class)
- for (second_class = 0; second_class < 24; ++second_class)
- if (m_dd_domain[first_class][second_class][i] == NULL) {
- node = (struct classified_domain *)
- malloc(sizeof(struct classified_domain));
- node->dd = &m_domain.pixel[i][0][0];
- node->next = NULL;
- m_dd_domain[first_class][second_class][i] = node;
- }
-
-
-
- Message("Done ");
- return TRUE;
-
- }
-
- int CFracComp::Pack(int size, long int value)
- {
- int i;
- static int ptr = 1, // how many bits are packed in sum so far
- sum = 0, // packed bits
- num_of_packed_bytes = 0; // total bytes written out
-
- // size == -1 means we are at the end, so write out what is left
- if (size == -1 && ptr != 1) {
- fputc(sum<<(8-ptr), m_FileOut);
- ++num_of_packed_bytes;
- return(0);
- }
-
- // size == -2 means we want to know how many bytes we have written
- if (size == -2)
- return(num_of_packed_bytes);
-
- for (i=0; i<size; ++i, ++ptr, value = value>>1, sum = sum<<1) {
- if (value & 1) sum |= 1;
-
- if (ptr == 8)
- {
- fputc(sum,m_FileOut);
- ++num_of_packed_bytes;
- sum=0;
- ptr=0;
- }
- }
- return(0);
- }
-
- double CFracComp::Compare(int atx, int aty, int xsize, int ysize, int depth, double rsum, double rsum2, int dom_x, int dom_y,
- int sym_op, int *pialpha, int *pibeta)
-
- {
- int i, j, i1, j1, k,
- domain_x,
- domain_y; // The domain position
-
- double pixel,
- det, // determinant of solution
- dsum, // sum of domain values
- rdsum = 0, // sum of range*domain values
- dsum2, // sum of domain^2 values
- w2 = 0, // total number of values tested
- rms = 0, // root means square difference
- alpha, // the scale factor
- beta; // The offset
-
-
-
-
- w2 = xsize * ysize;
- dsum = m_domain.pixel[depth-m_min_part][dom_y][dom_x].sum;
- dsum2 = m_domain.pixel[depth-m_min_part][dom_y][dom_x].sum2;
- domain_x = (dom_x * m_domain.domain_hstep[depth-m_min_part]);
- domain_y = (dom_y * m_domain.domain_vstep[depth-m_min_part]);
- k = ((domain_x%2)<<1) + domain_y%2;
- domain_x >>= 1;
- domain_y >>= 1;
-
- // The main statement in this routine is a switch statement which
- // scans through the domain and range to compare them.
- switch(sym_op) {
- case 0: for (i=atx, i1 = domain_x; i<atx+xsize; ++i, ++i1)
- for (j=aty, j1 = domain_y; j<aty+ysize; ++j, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 1: for (j=aty, i1 = domain_x; j<aty+ysize; ++j, ++i1)
- for (i=atx+xsize-1, j1 = domain_y; i>=atx; --i, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 2: for (i=atx+xsize-1, i1 = domain_x; i>=atx; --i, ++i1)
- for (j=aty+ysize-1, j1 = domain_y; j>=aty; --j, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 3: for (j=aty+ysize-1, i1 = domain_x; j>=aty; --j, ++i1)
- for (i=atx, j1 = domain_y; i<atx+xsize; ++i, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 4: for (j=aty, i1 = domain_x; j<aty+ysize; ++j, ++i1)
- for (i=atx, j1 = domain_y; i<atx+xsize; ++i, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 5: for (i=atx, i1 = domain_x; i<atx+xsize; ++i, ++i1)
- for (j=aty+ysize-1, j1 = domain_y; j>=aty; --j, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 6: for (j=aty+ysize-1, i1 = domain_x; j>=aty; --j, ++i1)
- for (i=atx+xsize-1, j1 = domain_y; i>=atx; --i, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
-
- case 7: for (i=atx+xsize-1, i1 = domain_x; i>=atx; --i, ++i1)
- for (j=aty, j1 = domain_y; j<aty+ysize; ++j, ++j1)
- {
- pixel = m_domimage[k][j1][i1];
- rdsum += m_image[j][i]*pixel;
- }
- break;
- }
-
- det = (xsize*ysize)*dsum2 - dsum*dsum;
-
- if (det == 0.0)
- alpha = 0.0;
- else
- alpha = (w2*rdsum - rsum*dsum)/det;
-
- if (m_only_positive && alpha < 0.0) alpha = 0.0;
- *pialpha = 0.5 + (alpha + m_max_scale)/(2.0*m_max_scale)*(1<<m_s_bits);
- if (*pialpha < 0) *pialpha = 0;
- if (*pialpha >= 1<<m_s_bits) *pialpha = (1<<m_s_bits)-1;
-
- // Now recompute alpha back
- alpha = (double)*pialpha/(double)(1<<m_s_bits)*(2.0*m_max_scale)-m_max_scale;
-
- //compute the offset
- beta = (rsum - alpha*dsum)/w2;
-
- // Convert beta to an integer
- // we use the sign information of alpha to pack efficiently
- if (alpha > 0.0) beta += alpha*GREY_LEVELS;
- *pibeta = 0.5 + beta/
- ((1.0+fabs(alpha))*GREY_LEVELS)*((1<<m_o_bits)-1);
- if (*pibeta< 0) *pibeta = 0;
- if (*pibeta>= 1<<m_o_bits) *pibeta = (1<<m_o_bits)-1;
-
- // Recompute beta from the integer
- beta = (double)*pibeta/(double)((1<<m_o_bits)-1)*
- ((1.0+fabs(alpha))*GREY_LEVELS);
- if (alpha > 0.0) beta -= alpha*GREY_LEVELS;
-
- // Compute the rms based on the quantized alpha and beta
- rms= sqrt((rsum2 + alpha*(alpha*dsum2 - 2.0*rdsum + 2.0*beta*dsum) +
- beta*(beta*w2 - 2.0*rsum))/w2);
-
- return(rms);
-
- }
-
- void CFracComp::Quadtree(int atx, int aty, int xsize, int ysize,double tol,int depth,HWND hdcOut)
- {
- int i,
- sym_op, // A symmetry operation of the square
- ialpha, // Intgerized scalling factor
- ibeta, // Intgerized offset
- best_ialpha, // best ialpha found
- best_ibeta,
- best_sym_op,
- best_domain_x,
- best_domain_y,
- first_class,
- the_first_class,
- first_class_start, // loop beginning and ending values
- first_class_end,
- second_class[2],
- the_second_class,
- second_class_start, // loop beginning and ending values
- second_class_end,
- range_sym_op[2], // the operations to bring square to
- domain_sym_op; // cannonical position.
-
- struct classified_domain *node; // var for domains we scan through
-
- double rms, best_rms, // rms value and min rms found so far
- sum=0, sum2=0; // sum and sum^2 of range pixels
- HDC tempDc = GetDC(hdcOut);
- CString msg;
- if (depth < m_min_part) {
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,(atx+xsize/4),aty,NULL);
- LineTo(m_MemDc,(atx+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx,(aty+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,(aty+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx,aty, xsize/2, ysize/2, tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,((atx+xsize/2)+xsize/4),aty,NULL);
- LineTo(m_MemDc,((atx+xsize/2)+xsize/4),ysize/2);
- MoveToEx(m_MemDc,(atx+xsize/2),(aty+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,(aty+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx+xsize/2,aty, xsize/2, ysize/2,tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,(atx+xsize/4),aty+ysize/2,NULL);
- LineTo(m_MemDc,(atx+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx,((aty+ysize/2)+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,((aty+ysize/2)+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx,aty+ysize/2, xsize/2, ysize/2,tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,((atx+xsize/2)+xsize/4),aty+ysize/2,NULL);
- LineTo(m_MemDc,((atx+xsize/2)+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx+xsize/2,((aty+ysize/2)+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,((aty+ysize/2)+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx+xsize/2,aty+ysize/2, xsize/2, ysize/2,tol,depth+1,hdcOut);
- return;
- }
-
- // now search for the best domain-range match and write it out
- best_rms = 10000000000.0;
-
- Classify(atx, aty, xsize,ysize,
- &the_first_class, &the_second_class,
- &range_sym_op[0], &sum, &sum2, 1);
-
-
- // sort out how much to search based on -f and -F input flags
- if (m_fullclass_search) {
- first_class_start = 0;
- first_class_end = 3;
- } else {
- first_class_start = the_first_class;
- first_class_end = the_first_class+1;
- }
-
- if (m_subclass_search) {
- second_class_start = 0;
- second_class_end = 24;
- } else {
- second_class_start = the_second_class;
- second_class_end = the_second_class+1;
- }
-
- // these for loops vary according to the optimization flags we set
- // for subclass_search and fullclass_search==1, we search all the
- // domains (except not all rotations).
- for (first_class = first_class_start;
- first_class < first_class_end; ++first_class)
- for (second_class[0] = second_class_start;
- second_class[0] < second_class_end; ++second_class[0]) {
-
- // We must check each domain twice. Once for positive scaling,
- // once for negative scaling. Each has its own class and sym_op
- if (!m_only_positive) {
- second_class[1] =
- m_class_transform[(first_class == 2 ? 1 : 0)][second_class[0]];
- range_sym_op[1] =
- m_rot_transform[(the_first_class == 2 ? 1 : 0)][range_sym_op[0]];
- }
-
- // only_positive is 0 or 1, so we may or not scan
- for (i=0; i<(2-m_only_positive); ++i)
- for (node = m_dd_domain[first_class][second_class[i]][depth-m_min_part];
- node != NULL;
- node = node->next) {
- domain_sym_op = node->dd->sym;
- // The following if statement figures out how to transform
- // the domain onto the range, given that we know how to get
- // each into cannonical position.
- if (((domain_sym_op>3 ? 4: 0) + (range_sym_op[i]>3 ? 4: 0))%8 == 0)
- sym_op = (4 + domain_sym_op%4 - range_sym_op[i]%4)%4;
- else
- sym_op = (4 + (domain_sym_op%4 + 3*(4-range_sym_op[i]%4))%4)%8;
-
- rms = Compare(atx,aty, xsize, ysize, depth, sum,sum2,
- node->dd->dom_x,
- node->dd->dom_y,
- sym_op, &ialpha,&ibeta);
-
- if (rms < best_rms) {
- best_ialpha = ialpha;
- best_ibeta = ibeta;
- best_rms = rms;
- best_sym_op = sym_op;
- best_domain_x = node->dd->dom_x;
- best_domain_y = node->dd->dom_y;
- }
- }
- }
-
- if (best_rms > tol && depth < m_max_part)
- {
- // We didn't find a good enough fit so quadtree down
- Pack(1,(long)1); // This bit means we quadtree'd down
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,(atx+xsize/4),aty,NULL);
- LineTo(m_MemDc,(atx+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx,(aty+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,(aty+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx,aty, xsize/2, ysize/2, tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,((atx+xsize/2)+xsize/4),aty,NULL);
- LineTo(m_MemDc,((atx+xsize/2)+xsize/4),ysize/2);
- MoveToEx(m_MemDc,(atx+xsize/2),(aty+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,(aty+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx+xsize/2,aty, xsize/2, ysize/2,tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,(atx+xsize/4),aty+ysize/2,NULL);
- LineTo(m_MemDc,(atx+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx,((aty+ysize/2)+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,((aty+ysize/2)+ysize/4));
- SetWindowText(hdcOut,msg);
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
-
- }
- Quadtree(atx,aty+ysize/2, xsize/2, ysize/2,tol,depth+1,hdcOut);
- if(hdcOut != NULL)
- {
- msg.Format("Quadtree is at depth %d",depth+1);
- SetWindowText(hdcOut,msg);
- MoveToEx(m_MemDc,((atx+xsize/2)+xsize/4),aty+ysize/2,NULL);
- LineTo(m_MemDc,((atx+xsize/2)+xsize/4),ysize/2);
- MoveToEx(m_MemDc,atx+xsize/2,((aty+ysize/2)+ysize/4),NULL);
- LineTo(m_MemDc,xsize/2,((aty+ysize/2)+ysize/4));
- BitBlt(tempDc,0,0,m_hsize,m_vsize,m_MemDc,0,0,SRCCOPY);
- }
- Quadtree(atx+xsize/2,aty+ysize/2, xsize/2, ysize/2,tol,depth+1,hdcOut);
- }
- else
- {
- // The fit was good enough or we just can't get smaller ranges
- // So write out the data
- if (depth < m_max_part) // if we are not at the smallest range
- Pack(1,(long)0); // then we must tell the decoder we
- // stopped quadtreeing
- Pack(m_s_bits, (long)best_ialpha);
- Pack(m_o_bits, (long)best_ibeta);
- // When the scaling is zero, there is no need to store the domain
- if (best_ialpha != m_zero_ialpha)
- {
- Pack(3, (long)best_sym_op);
- Pack(m_bits_needed[depth-m_min_part], (long)(best_domain_y*
- m_domain.no_h_domains[depth-m_min_part]+best_domain_x));
- }
- }
-
- }
-
- void CFracComp::Partition_Image(int atx, int aty,int hsize, int vsize,double tol,HWND hdcOut)
- {
- int x_exponent, // the largest power of 2 image size that fits
- y_exponent, // horizontally or vertically the rectangle.
- exponent, // The actual size of image that's encoded.
- size,
- depth;
-
- x_exponent = (int)floor(log((double)hsize)/log(2.0));
- y_exponent = (int)floor(log((double)vsize)/log(2.0));
-
- // exponent is min of x_ and y_ exponent
- exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
- size = 1<<exponent;
- depth = m_max_exponent - exponent;
- Quadtree(atx,aty,size,size,tol,depth,hdcOut);
- if (size != hsize)
- Partition_Image(atx+size, aty, hsize-size,vsize, tol,hdcOut);
-
- if (size != vsize)
- Partition_Image(atx, aty+size, size,vsize-size, tol,hdcOut);
- }
-
- void CFracComp::Average(int x, int y, int xsize, int ysize, double *psum, double *psum2)
- {
- register int i,j,k;
- register double pixel;
- *psum = *psum2 = 0.0;
- k = ((x%2)<<1) + y%2;
- x >>= 1; y >>= 1;
- xsize >>= 1; ysize >>= 1;
- for (i=x; i<x+xsize; ++i)
- for (j=y; j<y+ysize; ++j)
- {
- pixel = m_domimage[k][j][i];
- *psum += pixel;
- *psum2 += pixel*pixel;
- }
- }
-
- void CFracComp::Average1(int x, int y, int xsize, int ysize, double *psum, double *psum2)
- {
- register int i,j;
- register double pixel;
- *psum = *psum2 = 0.0;
-
- for (i=x; i<x+xsize; ++i)
- for (j=y; j<y+ysize; ++j) {
- pixel = (double)m_image[j][i];
- *psum += pixel;
- *psum2 += pixel*pixel;
- }
- }
-
-
-