"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "f.comb.cc" between
fotoxx-23.0.tar.gz and fotoxx-23.1.tar.gz

About: fotoxx is a program for photo editing and collection management.

f.comb.cc  (fotoxx-23.0):f.comb.cc  (fotoxx-23.1)
/******************************************************************************* * /******************************************************************************* *
Fotoxx edit photos and manage collections Fotoxx - edit photos and manage collections
Copyright 2007-2023 Michael Cornelison Copyright 2007-2023 Michael Cornelison
source code URL: https://kornelix.net source code URL: https://kornelix.net
contact: mkornelix@gmail.com contact: mkornelix@gmail.com
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. See https://www.gnu.org/licenses (at your option) any later version. See https://www.gnu.org/licenses
skipping to change at line 46 skipping to change at line 46
#define EX extern // enable extern declarations #define EX extern // enable extern declarations
#include "fotoxx.h" // (variables in fotoxx.h are refs) #include "fotoxx.h" // (variables in fotoxx.h are refs)
/******************************************************************************* */ /******************************************************************************* */
// File scope variables and functions for combine images // File scope variables and functions for combine images
// used by HDR, HDF, STP, STN, Panorama. // used by HDR, HDF, STP, STN, Panorama.
int cimNF; // image coun t, <= 10 int cimNF; // image coun t, <= 10
int cimLF; // index of a lphabetically last input file int cimLF; // index of a lphabetically last input file
char *cimFile[10]; // input imag e files ch *cimFile[10]; // input imag e files
PXM *cimPXMf[10]; // original i mage pixmaps PXM *cimPXMf[10]; // original i mage pixmaps
PXM *cimPXMs[10]; // alignment images, scaled and curved (pano) PXM *cimPXMs[10]; // alignment images, scaled and curved (pano)
PXM *cimPXMw[10]; // alignment images, warped PXM *cimPXMw[10]; // alignment images, warped
struct cimoffs { // image alig nment offsets struct cimoffs { // image alig nment offsets
float xf, yf, tf; // x, y, thet a offsets float xf, yf, tf; // x, y, thet a offsets
float wx[4], wy[4]; // x/y corner warps, 0=NW, 1=NE, 2=SE, 3=SW float wx[4], wy[4]; // x/y corner warps, 0=NW, 1=NE, 2=SE, 3=SW
}; };
cimoffs cimOffs[10]; // image alig nment data in E3 output image cimoffs cimOffs[10]; // image alig nment data in E3 output image
skipping to change at line 72 skipping to change at line 72
float cimSearchStep; // alignment search step, vpixels float cimSearchStep; // alignment search step, vpixels
int cim_manualwarp; // alignment manual warping instead of auto int cim_manualwarp; // alignment manual warping instead of auto
int cim_manualalign; // alignment is manual instead of auto int cim_manualalign; // alignment is manual instead of auto
float cimWarpRange; // alignment corner warp range, pixels float cimWarpRange; // alignment corner warp range, pixels
float cimWarpStep; // alignment corner warp step, vpixels float cimWarpStep; // alignment corner warp step, vpixels
float cimSampSize; // pixel samp le size float cimSampSize; // pixel samp le size
int cimOv1xlo, cimOv1xhi, cimOv1ylo, cimOv1yhi; // rectangle enclosing overlap area, int cimOv1xlo, cimOv1xhi, cimOv1ylo, cimOv1yhi; // rectangle enclosing overlap area,
int cimOv2xlo, cimOv2xhi, cimOv2ylo, cimOv2yhi; // image 1 and image2 coordinates int cimOv2xlo, cimOv2xhi, cimOv2ylo, cimOv2yhi; // image 1 and image2 coordinates
float cimRGBmf1[3][256]; // RGB matchi ng factors for image 1/2 compare: float cimRGBmf1[3][256]; // RGB matchi ng factors for image 1/2 compare:
float cimRGBmf2[3][256]; // cimRGBmf1[ *][pix1[*]] == cimRGBmf2[*][pix2[*]] float cimRGBmf2[3][256]; // cimRGBmf1[ *][pix1[*]] == cimRGBmf2[*][pix2[*]]
char *cimRedpix = 0; // maps high- contrast pixels for alignment ch *cimRedpix = 0; // maps high- contrast pixels for alignment
int cimRedImage; // which imag e has red pixels int cimRedImage; // which imag e has red pixels
int cimNsearch; // alignment search counter int cimNsearch; // alignment search counter
int cimShowIm1, cimShowIm2; // two images for cim_show_images() int cimShowIm1, cimShowIm2; // two images for cim_show_images()
int cimShowAll; // if > 0, sh ow all images int cimShowAll; // if > 0, sh ow all images
int cimPano; // pano mode flag for cim_align_image() int cimPano; // pano mode flag for cim_align_image()
int cimPanoV; // vertical p ano flag int cimPanoV; // vertical p ano flag
int cimPanoNC; // pano no-cu rve flag (scanned image) int cimPanoNC; // pano no-cu rve flag (scanned image)
float cimPanoFL; // pano lens focal length at image scale float cimPanoFL; // pano lens focal length at image scale
int cim_get_files(int min, int max); // get list o f input files, load PXM images int cim_get_files(int min, int max); // get list o f input files, load PXM images
skipping to change at line 105 skipping to change at line 105
void cim_warp_image(int im); // warp image corners: cimPXMs[im] >> cimPXMw[im] void cim_warp_image(int im); // warp image corners: cimPXMs[im] >> cimPXMw[im]
void cim_warp_image_pano(int im, int fblend); // pano versi on, all / left side / blend stripe void cim_warp_image_pano(int im, int fblend); // pano versi on, all / left side / blend stripe
void cim_warp_image_Vpano(int im, int fblend); // vertical p ans version: bottom side corners void cim_warp_image_Vpano(int im, int fblend); // vertical p ans version: bottom side corners
int cim_sigdiff(float d1, float d2, float signf); // test 2 val ues for significant difference int cim_sigdiff(float d1, float d2, float signf); // test 2 val ues for significant difference
void cim_align_image(int im1, int im2); // align imag e im2 to im1, modify im2 offsets void cim_align_image(int im1, int im2); // align imag e im2 to im1, modify im2 offsets
float cim_match_images(int im1, int im2); // compute ma tch for overlapped images float cim_match_images(int im1, int im2); // compute ma tch for overlapped images
void cim_show_images(int fnew, int fblend); // combine im ages >> E3pxm >> main window void cim_show_images(int fnew, int fblend); // combine im ages >> E3pxm >> main window
void cim_show_Vimages(int fnew, int fblend); // vertical p ano version void cim_show_Vimages(int fnew, int fblend); // vertical p ano version
void cim_trim(); // cut-off ed ges where all images do not overlap void cim_trim(); // cut-off ed ges where all images do not overlap
void cim_trim_margins(); // cut-off ex cess margins (panorama) void cim_trim_margins(); // cut-off ex cess margins (panorama)
void cim_dump_offsets(cchar *label); // diagnostic tool void cim_dump_offsets(ch *label); // diagnostic tool
void cim_flatten_image(float F); // flatten pa norama image void cim_flatten_image(float F); // flatten pa norama image
void cim_flatten_Vimage(float F); // flatten ve rt. panorama image void cim_flatten_Vimage(float F); // flatten ve rt. panorama image
/******************************************************************************* * /******************************************************************************* *
Make an HDR (high dynamic range) image from several images of the same Make an HDR (high dynamic range) image from several images of the same
subject with different exposure levels. The combined image has better subject with different exposure levels. The combined image has better
visibility of detail in both the brightest and darkest areas. visibility of detail in both the brightest and darkest areas.
******************************************************************************** */ ******************************************************************************** */
skipping to change at line 145 skipping to change at line 145
void * HDR_align(void *); // align 2 images void * HDR_align(void *); // align 2 images
void HDR_brightness(); // compute pixel brightness levels void HDR_brightness(); // compute pixel brightness levels
void HDR_adjust_dialog(); // adjust image contribution curves void HDR_adjust_dialog(); // adjust image contribution curves
void * HDR_adjust_weights(void *); // combine images per contribution curves void * HDR_adjust_weights(void *); // combine images per contribution curves
editfunc EFhdr; // edit function data editfunc EFhdr; // edit function data
// menu function // menu function
void m_HDR(GtkWidget *, cchar *menu) void m_HDR(GtkWidget *, ch *menu)
{ {
char *ftemp; ch *ftemp;
int imx, jj, err, px, py, ww, hh; int imx, jj, err, px, py, ww, hh;
float fbright[10], btemp; float fbright[10], btemp;
float pixsum, fnorm = 1.0 / 256.0; float pixsum, fnorm = 1.0 / 256.0;
float *pixel; float *pixel;
PXM *pxmtemp; PXM *pxmtemp;
F1_help_topic = "HDR"; F1_help_topic = "HDR";
Plog(1,"m_HDR \n"); Plog(1,"m_HDR \n");
skipping to change at line 211 skipping to change at line 211
fbright[imx] = btemp; fbright[imx] = btemp;
ftemp = cimFile[jj]; ftemp = cimFile[jj];
cimFile[jj] = cimFile[imx]; cimFile[jj] = cimFile[imx];
cimFile[imx] = ftemp; cimFile[imx] = ftemp;
pxmtemp = cimPXMf[jj]; pxmtemp = cimPXMf[jj];
cimPXMf[jj] = cimPXMf[imx]; cimPXMf[jj] = cimPXMf[imx];
cimPXMf[imx] = pxmtemp; cimPXMf[imx] = pxmtemp;
} }
} }
Fescape = 1; Fwatchescape = 1;
// killable with escape // killable with escape
Fescape = 0;
HDR_align(0); HDR_align(0);
if (HDR_stat != 1) goto cancel; if (HDR_stat != 1) goto cancel;
if (Fescape > 1) { // user cancel if (Fescape) { // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
goto cancel; goto cancel;
} }
HDR_brightness(); // compute pixel brightness levels HDR_brightness(); // compute pixel brightness levels
if (HDR_stat != 1) goto cancel; if (HDR_stat != 1) goto cancel;
HDR_adjust_dialog(); // combine images based on user inputs HDR_adjust_dialog(); // combine images based on user inputs
if (HDR_stat != 1) goto cancel; if (HDR_stat != 1) goto cancel;
skipping to change at line 239 skipping to change at line 241
goto cleanup; goto cleanup;
cancel: cancel:
edit_cancel(0); edit_cancel(0);
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
if (HDR_bright) zfree(HDR_bright); if (HDR_bright) zfree(HDR_bright);
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// HDR align each pair of input images, output combined image to E3pxm // HDR align each pair of input images, output combined image to E3pxm
// cimPXMf[*] original image // cimPXMf[*] original image
// cimPXMs[*] scaled and color adjusted for pixel comparisons // cimPXMs[*] scaled and color adjusted for pixel comparisons
// cimPXMw[*] warped for display // cimPXMw[*] warped for display
void * HDR_align(void *) void * HDR_align(void *)
{ {
skipping to change at line 306 skipping to change at line 308
cim_get_overlap(im1,im2,cimPXMs); // get overlap area cim_get_overlap(im1,im2,cimPXMs); // get overlap area
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cimShowIm1 = im1; // show two images with 50/50 blend cimShowIm1 = im1; // show two images with 50/50 blend
cimShowIm2 = im2; cimShowIm2 = im2;
cimShowAll = 0; cimShowAll = 0;
cim_show_images(1,0); // (x/y offsets can change) cim_show_images(1,0); // (x/y offsets can change)
cim_align_image(im1,im2); // align im2 to im1 cim_align_image(im1,im2); // align im2 to im1
if (Fescape > 1) goto finish; // user kill if (Fescape) goto finish; // user kill
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (cimScale == 1.0) break; // done if (cimScale == 1.0) break; // done
R = HDR_imageIncrease; // next larger image size R = HDR_imageIncrease; // next larger image size
cimScale = cimScale * R; cimScale = cimScale * R;
if (cimScale > 0.85) { // if close to end, jump to end if (cimScale > 0.85) { // if close to end, jump to end
R = R / cimScale; R = R / cimScale;
skipping to change at line 492 skipping to change at line 494
zadd_locked(Ffuncbusy,-1); zadd_locked(Ffuncbusy,-1);
Fpaint2(); // update window Fpaint2(); // update window
return; return;
} }
// Dialog for user to control the contributions of each input image // Dialog for user to control the contributions of each input image
// while watching the output image which is updated in real time. // while watching the output image which is updated in real time.
void HDR_adjust_dialog() void HDR_adjust_dialog()
{ {
int HDR_adjust_dialog_event(zdialog *zd, cchar *event); int HDR_adjust_dialog_event(zdialog *zd, ch *event);
void HDR_curvedit(int); void HDR_curvedit(int);
int imx; int imx;
float cww = 1.0 / (cimNF-1); float cww = 1.0 / (cimNF-1);
/*** /***
_____________________________________________________ _____________________________________________________
| Adjust Image Contributions | | Adjust Image Contributions |
| _________________________________________________ | | _________________________________________________ |
| | | | | | | |
skipping to change at line 560 skipping to change at line 562
zdialog_resize(zd,300,250); zdialog_resize(zd,300,250);
zdialog_run(zd,HDR_adjust_dialog_event,"save"); // run dialog zdialog_run(zd,HDR_adjust_dialog_event,"save"); // run dialog
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int HDR_adjust_dialog_event(zdialog *zd, cchar *event) // add file open dialog int HDR_adjust_dialog_event(zdialog *zd, ch *event) // add file open dialog
{ {
char *file, *pp; ch *file, *pp;
FILE *fid; FILE *fid;
spldat *sd = EFhdr.sd; spldat *sd = EFhdr.sd;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"load")) // load saved curve if (strmatch(event,"load")) // load saved curve
{ {
file = zgetfile("load curve from a file",MWIN,"file",saved_curves_folder); file = zgetfile("load curve from a file",MWIN,"file",saved_curves_folder);
if (! file) return 1; if (! file) return 1;
fid = fopen(file,"r"); fid = fopen(file,"r");
skipping to change at line 762 skipping to change at line 764
void * HDF_align(void *); void * HDF_align(void *);
void HDF_adjust_dialog(); void HDF_adjust_dialog();
void HDF_mousefunc(); void HDF_mousefunc();
void * HDF_map_pixels(void *); void * HDF_map_pixels(void *);
editfunc EFhdf; // edit function data editfunc EFhdf; // edit function data
// menu function // menu function
void m_HDF(GtkWidget *, cchar *menu) void m_HDF(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "HDF"; F1_help_topic = "HDF";
Plog(1,"m_HDF \n"); Plog(1,"m_HDF \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 793 skipping to change at line 795
cim_manualwarp = 0; cim_manualwarp = 0;
err = f_open(cimFile[cimLF]); // curr_file = alphabetically last err = f_open(cimFile[cimLF]); // curr_file = alphabetically last
if (err) goto cleanup; if (err) goto cleanup;
EFhdf.menufunc = m_HDF; EFhdf.menufunc = m_HDF;
EFhdf.menuname = "HDF"; EFhdf.menuname = "HDF";
EFhdf.mousefunc = HDF_mousefunc; EFhdf.mousefunc = HDF_mousefunc;
if (! edit_setup(EFhdf)) goto cleanup; // setup edit (will lock) if (! edit_setup(EFhdf)) goto cleanup; // setup edit (will lock)
Fescape = 1; Fwatchescape = 1;
// killable with escape // killable with escape
Fescape = 0;
HDF_align(0); // align each pair of images HDF_align(0); // align each pair of images
if (HDF_stat != 1) goto cancel; if (HDF_stat != 1) goto cancel;
if (Fescape > 1) { // user cancel if (Fescape) { // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
goto cancel; goto cancel;
} }
HDF_adjust_dialog(); // combine images based on user inputs HDF_adjust_dialog(); // combine images based on user inputs
if (HDF_stat != 1) goto cancel; if (HDF_stat != 1) goto cancel;
CEF->Fmods++; // done CEF->Fmods++; // done
CEF->Fsaved = 0; CEF->Fsaved = 0;
edit_done(0); edit_done(0);
goto cleanup; goto cleanup;
cancel: cancel:
edit_cancel(0); edit_cancel(0);
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// align each image 2nd-last to 1st image // align each image 2nd-last to 1st image
// cimPXMf[*] original image // cimPXMf[*] original image
// cimPXMs[*] scaled and color adjusted for pixel comparisons // cimPXMs[*] scaled and color adjusted for pixel comparisons
// cimPXMw[*] warped for display // cimPXMw[*] warped for display
void * HDF_align(void *) void * HDF_align(void *)
{ {
skipping to change at line 881 skipping to change at line 885
cim_get_overlap(im1,im2,cimPXMs); // get overlap area cim_get_overlap(im1,im2,cimPXMs); // get overlap area
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cimShowIm1 = im1; // show these two images cimShowIm1 = im1; // show these two images
cimShowIm2 = im2; // with 50/50 blend cimShowIm2 = im2; // with 50/50 blend
cimShowAll = 0; cimShowAll = 0;
cim_show_images(1,0); // (x/y offsets can change) cim_show_images(1,0); // (x/y offsets can change)
cim_align_image(im1,im2); // align im2 to im1 cim_align_image(im1,im2); // align im2 to im1
if (Fescape > 1) goto finish; // user kill if (Fescape) goto finish; // user kill
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (cimScale == 1.0) break; // done if (cimScale == 1.0) break; // done
R = HDF_imageIncrease; // next larger image size R = HDF_imageIncrease; // next larger image size
cimScale = cimScale * R; cimScale = cimScale * R;
if (cimScale > 0.85) { // if close to end, jump to end if (cimScale > 0.85) { // if close to end, jump to end
R = R / cimScale; R = R / cimScale;
skipping to change at line 932 skipping to change at line 936
HDF_stat = 1; HDF_stat = 1;
return 0; return 0;
} }
// paint and warp output image // paint and warp output image
zdialog *HDF_adjustzd = 0; // paint/warp dialog zdialog *HDF_adjustzd = 0; // paint/warp dialog
int HDF_mode; // mode: paint or warp int HDF_mode; // mode: paint or warp
int HDF_image; // current image (0 based) int HDF_image; // current image (0 based)
int HDF_radius; // paint mode radius int HDF_radius; // paint mode radius
char *HDF_pixmap = 0; // map input image per output pixel ch *HDF_pixmap = 0; // map input image per output pixel
float *HDF_warpx[10], *HDF_warpy[10]; // warp memory, pixel displacements float *HDF_warpx[10], *HDF_warpy[10]; // warp memory, pixel displacements
void HDF_adjust_dialog() void HDF_adjust_dialog()
{ {
char imageN[8] = "imageN", labN[4] = "0"; ch imageN[8] = "imageN", labN[4] = "0";
int cc, imx, ww, hh; int cc, imx, ww, hh;
int HDF_adjust_dialog_event(zdialog *zd, cchar *event); int HDF_adjust_dialog_event(zdialog *zd, ch *event);
/*** /***
______________________________________ ______________________________________
| Paint and Warp Image | | Paint and Warp Image |
| | | |
| Image (o) 1 (o) 2 (o) 3 ... | | Image (o) 1 (o) 2 (o) 3 ... |
| (o) paint Radius [____] | | (o) paint Radius [____] |
| (o) warp | | (o) warp |
| [ OK ] [Cancel] | | [ OK ] [Cancel] |
|______________________________________| |______________________________________|
skipping to change at line 988 skipping to change at line 992
zdialog_stuff(zd,"warp",0); // warp button off zdialog_stuff(zd,"warp",0); // warp button off
zdialog_stuff(zd,"image1",1); // initial image = 1st zdialog_stuff(zd,"image1",1); // initial image = 1st
HDF_mode = 0; // start in paint mode HDF_mode = 0; // start in paint mode
HDF_image = 0; // initial image HDF_image = 0; // initial image
HDF_radius = 100; // paint radius HDF_radius = 100; // paint radius
takeMouse(HDF_mousefunc,0); // connect mouse function takeMouse(HDF_mousefunc,0); // connect mouse function
cc = E3pxm->ww * E3pxm->hh; // allocate pixel map cc = E3pxm->ww * E3pxm->hh; // allocate pixel map
HDF_pixmap = (char *) zmalloc(cc,"cim HDF"); HDF_pixmap = (ch *) zmalloc(cc,"cim HDF");
memset(HDF_pixmap,cimNF,cc); // initial state, blend all images memset(HDF_pixmap,cimNF,cc); // initial state, blend all images
for (imx = 0; imx < cimNF; imx++) { // allocate warp memory for (imx = 0; imx < cimNF; imx++) { // allocate warp memory
ww = cimPXMw[imx]->ww; ww = cimPXMw[imx]->ww;
hh = cimPXMw[imx]->hh; hh = cimPXMw[imx]->hh;
HDF_warpx[imx] = (float *) zmalloc(ww * hh * sizeof(float),"cim HDF"); HDF_warpx[imx] = (float *) zmalloc(ww * hh * sizeof(float),"cim HDF");
HDF_warpy[imx] = (float *) zmalloc(ww * hh * sizeof(float),"cim HDF"); HDF_warpy[imx] = (float *) zmalloc(ww * hh * sizeof(float),"cim HDF");
} }
zdialog_resize(zd,250,0); // stretch a bit zdialog_resize(zd,250,0); // stretch a bit
zdialog_run(zd,HDF_adjust_dialog_event,"save"); // run dialog, parallel zdialog_run(zd,HDF_adjust_dialog_event,"save"); // run dialog, parallel
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int HDF_adjust_dialog_event(zdialog *zd, cchar *event) int HDF_adjust_dialog_event(zdialog *zd, ch *event)
{ {
int imx, nn; int imx, nn;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog finish if (zd->zstat) // dialog finish
{ {
freeMouse(); // disconnect mouse function freeMouse(); // disconnect mouse function
if (zd->zstat == 1) HDF_stat = 1; if (zd->zstat == 1) HDF_stat = 1;
else HDF_stat = 0; else HDF_stat = 0;
skipping to change at line 1071 skipping to change at line 1075
// HDF dialog mouse function // HDF dialog mouse function
// paint: during drag, selected image >> HDF_pixmap (within paint radius) >> E 3 // paint: during drag, selected image >> HDF_pixmap (within paint radius) >> E 3
// warp: for selected image, cimPXMs >> warp >> cimPXMw >> E3 // warp: for selected image, cimPXMs >> warp >> cimPXMw >> E3
void HDF_mousefunc() void HDF_mousefunc()
{ {
float vpix1[4], *pix2, *pix3; float vpix1[4], *pix2, *pix3;
int imx, radius, rect, radius2, vstat1; int imx, radius, rect, radius2, vstat1;
int mx, my, dx, dy, px3, py3; int mx, my, dx, dy, px3, py3;
char imageN[8] = "imageN"; ch imageN[8] = "imageN";
float px1, py1; float px1, py1;
float xoff, yoff, sintf[10], costf[10]; float xoff, yoff, sintf[10], costf[10];
int ii, px, py, ww, hh; int ii, px, py, ww, hh;
float mag, dispx, dispy, d1, d2; float mag, dispx, dispy, d1, d2;
PXM *pxm1, *pxm2; PXM *pxm1, *pxm2;
if (LMclick || RMclick) // mouse click if (LMclick || RMclick) // mouse click
return; // process zooms normally return; // process zooms normally
if (HDF_mode == 0) goto paint; if (HDF_mode == 0) goto paint;
skipping to change at line 1310 skipping to change at line 1314
void * STP_align(void *); void * STP_align(void *);
void STP_adjust_dialog(); void STP_adjust_dialog();
void STP_mousefunc(); void STP_mousefunc();
void * STP_map_pixels(void *); void * STP_map_pixels(void *);
void STP_setpixel(int px, int py, int source); void STP_setpixel(int px, int py, int source);
editfunc EFstp; // edit function data editfunc EFstp; // edit function data
// menu function // menu function
void m_stack_paint(GtkWidget *, cchar *menu) void m_stack_paint(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "stack/paint"; F1_help_topic = "stack/paint";
Plog(1,"m_stack_paint \n"); Plog(1,"m_stack_paint \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 1341 skipping to change at line 1345
cim_manualwarp = 0; cim_manualwarp = 0;
err = f_open(cimFile[cimLF]); // curr_file = alphabetically last err = f_open(cimFile[cimLF]); // curr_file = alphabetically last
if (err) goto cleanup; if (err) goto cleanup;
EFstp.menufunc = m_stack_paint; EFstp.menufunc = m_stack_paint;
EFstp.menuname = "Stack/Paint"; EFstp.menuname = "Stack/Paint";
EFstp.mousefunc = STP_mousefunc; EFstp.mousefunc = STP_mousefunc;
if (! edit_setup(EFstp)) goto cleanup; // setup edit (will lock) if (! edit_setup(EFstp)) goto cleanup; // setup edit (will lock)
Fescape = 1; Fwatchescape = 1;
// killable with escape // killable with escape
Fescape = 0;
STP_align(0); // align each pair of images STP_align(0); // align each pair of images
if (STP_stat != 1) goto cancel; if (STP_stat != 1) goto cancel;
if (Fescape > 1) { // user cancel if (Fescape) { // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
goto cancel; goto cancel;
} }
STP_adjust_dialog(); // combine images based on user inputs STP_adjust_dialog(); // combine images based on user inputs
if (STP_stat != 1) goto cancel; if (STP_stat != 1) goto cancel;
CEF->Fmods++; // done CEF->Fmods++; // done
CEF->Fsaved = 0; CEF->Fsaved = 0;
edit_done(0); edit_done(0);
goto cleanup; goto cleanup;
cancel: cancel:
edit_cancel(0); edit_cancel(0);
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// align each image 2nd-last to 1st image // align each image 2nd-last to 1st image
// cimPXMf[*] original image // cimPXMf[*] original image
// cimPXMs[*] scaled and color adjusted for pixel comparisons // cimPXMs[*] scaled and color adjusted for pixel comparisons
// cimPXMw[*] warped for display // cimPXMw[*] warped for display
void * STP_align(void *) void * STP_align(void *)
{ {
skipping to change at line 1429 skipping to change at line 1435
cim_get_overlap(im1,im2,cimPXMs); // get overlap area cim_get_overlap(im1,im2,cimPXMs); // get overlap area
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cimShowIm1 = im1; // show these two images cimShowIm1 = im1; // show these two images
cimShowIm2 = im2; // with 50/50 blend cimShowIm2 = im2; // with 50/50 blend
cimShowAll = 0; cimShowAll = 0;
cim_show_images(1,0); // (x/y offsets can change) cim_show_images(1,0); // (x/y offsets can change)
cim_align_image(im1,im2); // align im2 to im1 cim_align_image(im1,im2); // align im2 to im1
if (Fescape > 1) goto finish; // user kill if (Fescape) goto finish; // user kill
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (cimScale == 1.0) break; // done if (cimScale == 1.0) break; // done
R = STP_imageIncrease; // next larger image size R = STP_imageIncrease; // next larger image size
cimScale = cimScale * R; cimScale = cimScale * R;
if (cimScale > 0.85) { // if close to end, jump to end if (cimScale > 0.85) { // if close to end, jump to end
R = R / cimScale; R = R / cimScale;
skipping to change at line 1485 skipping to change at line 1491
int STP_image; // current image (0 based) int STP_image; // current image (0 based)
int STP_radius; // paint mode radius int STP_radius; // paint mode radius
int STP_mode; // 1/2 = show/hide int STP_mode; // 1/2 = show/hide
float STP_show_adjust; // contrast adjustment float STP_show_adjust; // contrast adjustment
float STP_hide_adjust; // contrast adjustment float STP_hide_adjust; // contrast adjustment
void STP_adjust_dialog() void STP_adjust_dialog()
{ {
zdialog *zd; zdialog *zd;
char imageN[8] = "imageN", labN[4] = "0"; ch imageN[8] = "imageN", labN[4] = "0";
int imx; int imx;
int STP_adjust_dialog_event(zdialog *zd, cchar *event); int STP_adjust_dialog_event(zdialog *zd, ch *event);
/*** /***
_________________________________________ _________________________________________
| Select and Paint Image | | Select and Paint Image |
| | | |
| image (o) 1 (o) 2 (o) 3 ... | | image (o) 1 (o) 2 (o) 3 ... |
| paint radius [___] | | paint radius [___] |
| | | |
| transient objects | | transient objects |
| show (o) =========[]================= | | show (o) =========[]================= |
skipping to change at line 1557 skipping to change at line 1563
zdialog_resize(zd,250,0); zdialog_resize(zd,250,0);
zdialog_run(zd,STP_adjust_dialog_event,"save"); // run dialog, parallel zdialog_run(zd,STP_adjust_dialog_event,"save"); // run dialog, parallel
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int STP_adjust_dialog_event(zdialog *zd, cchar *event) int STP_adjust_dialog_event(zdialog *zd, ch *event)
{ {
int nn; int nn;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog finish if (zd->zstat) // dialog finish
{ {
freeMouse(); freeMouse();
if (zd->zstat == 1) STP_stat = 1; if (zd->zstat == 1) STP_stat = 1;
else STP_stat = 0; else STP_stat = 0;
skipping to change at line 1883 skipping to change at line 1889
int STN_exlow = 0, STN_exhigh = 0; // exclude low/high pixel int STN_exlow = 0, STN_exhigh = 0; // exclude low/high pixel
void * STN_align(void *); void * STN_align(void *);
void STN_adjust_dialog(); void STN_adjust_dialog();
void * STN_combine(void *); void * STN_combine(void *);
editfunc EFstn; // edit function data editfunc EFstn; // edit function data
// menu function // menu function
void m_stack_noise(GtkWidget *, cchar *menu) void m_stack_noise(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "stack/noise"; F1_help_topic = "stack/noise";
Plog(1,"m_stack_noise \n"); Plog(1,"m_stack_noise \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 1913 skipping to change at line 1919
cim_manualwarp = 0; cim_manualwarp = 0;
err = f_open(cimFile[cimLF]); // curr_file = alphabetically last err = f_open(cimFile[cimLF]); // curr_file = alphabetically last
if (err) goto cleanup; if (err) goto cleanup;
EFstn.menufunc = m_stack_noise; EFstn.menufunc = m_stack_noise;
EFstn.menuname = "Stack/Noise"; EFstn.menuname = "Stack/Noise";
if (! edit_setup(EFstn)) goto cleanup; // setup edit (will lock) if (! edit_setup(EFstn)) goto cleanup; // setup edit (will lock)
Fescape = 1; Fwatchescape = 1;
// killable with escape // killable with escape
Fescape = 0;
STN_align(0); // align each pair of images STN_align(0); // align each pair of images
if (STN_stat != 1) goto cancel; if (STN_stat != 1) goto cancel;
if (Fescape > 1) { // user cancel if (Fescape) { // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
goto cancel; goto cancel;
} }
STN_adjust_dialog(); // combine images based on user inputs STN_adjust_dialog(); // combine images based on user inputs
if (STN_stat != 1) goto cancel; if (STN_stat != 1) goto cancel;
CEF->Fmods++; // done CEF->Fmods++; // done
CEF->Fsaved = 0; CEF->Fsaved = 0;
edit_done(0); edit_done(0);
goto cleanup; goto cleanup;
cancel: cancel:
edit_cancel(0); edit_cancel(0);
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// align each image 2nd-last to 1st image // align each image 2nd-last to 1st image
// cimPXMf[*] original image // cimPXMf[*] original image
// cimPXMs[*] scaled and color adjusted for pixel comparisons // cimPXMs[*] scaled and color adjusted for pixel comparisons
// cimPXMw[*] warped for display // cimPXMw[*] warped for display
void * STN_align(void *) void * STN_align(void *)
{ {
skipping to change at line 2001 skipping to change at line 2009
cim_get_overlap(im1,im2,cimPXMs); // get overlap area cim_get_overlap(im1,im2,cimPXMs); // get overlap area
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cimShowIm1 = im1; // show these two images cimShowIm1 = im1; // show these two images
cimShowIm2 = im2; // with 50/50 blend cimShowIm2 = im2; // with 50/50 blend
cimShowAll = 0; cimShowAll = 0;
cim_show_images(1,0); // (x/y offsets can change) cim_show_images(1,0); // (x/y offsets can change)
cim_align_image(im1,im2); // align im2 to im1 cim_align_image(im1,im2); // align im2 to im1
if (Fescape > 1) goto finish; // user kill if (Fescape) goto finish; // user kill
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (cimScale == 1.0) break; // done if (cimScale == 1.0) break; // done
R = STN_imageIncrease; // next larger image size R = STN_imageIncrease; // next larger image size
cimScale = cimScale * R; cimScale = cimScale * R;
if (cimScale > 0.85) { // if close to end, jump to end if (cimScale > 0.85) { // if close to end, jump to end
R = R / cimScale; R = R / cimScale;
skipping to change at line 2052 skipping to change at line 2060
STN_stat = 1; STN_stat = 1;
return 0; return 0;
} }
// change pixel combination according to user input // change pixel combination according to user input
void STN_adjust_dialog() void STN_adjust_dialog()
{ {
zdialog *zd; zdialog *zd;
int STN_adjust_dialog_event(zdialog *zd, cchar *event); int STN_adjust_dialog_event(zdialog *zd, ch *event);
/*** /***
_________________________________________ _________________________________________
| Adjust Pixel Composition | | Adjust Pixel Composition |
| | | |
| (o) use average (o) use median | | (o) use average (o) use median |
| [x] omit low pixel [x] omit high pixel | | [x] omit low pixel [x] omit high pixel |
| | | |
| [ OK ] [Cancel] | | [ OK ] [Cancel] |
|_________________________________________| |_________________________________________|
skipping to change at line 2096 skipping to change at line 2104
zdialog_resize(zd,250,0); zdialog_resize(zd,250,0);
zdialog_run(zd,STN_adjust_dialog_event,"save"); // run dialog, parallel zdialog_run(zd,STN_adjust_dialog_event,"save"); // run dialog, parallel
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int STN_adjust_dialog_event(zdialog *zd, cchar *event) int STN_adjust_dialog_event(zdialog *zd, ch *event)
{ {
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) { // dialog finish if (zd->zstat) { // dialog finish
if (zd->zstat == 1) STN_stat = 1; if (zd->zstat == 1) STN_stat = 1;
else STN_stat = 0; else STN_stat = 0;
if (STN_stat == 1) cim_trim(); // trim edges if (STN_stat == 1) cim_trim(); // trim edges
return 1; return 1;
} }
skipping to change at line 2272 skipping to change at line 2280
int STL_mode; int STL_mode;
int STL_image; // current image (0 based) int STL_image; // current image (0 based)
int STL_radius; // mouse paint radius int STL_radius; // mouse paint radius
int STL_center, STL_edge; // mouse center and edge opacity int STL_center, STL_edge; // mouse center and edge opacity
int STL_stat; int STL_stat;
editfunc EFstl; // edit function data editfunc EFstl; // edit function data
// menu function // menu function
void m_stack_layer(GtkWidget *, cchar *menu) void m_stack_layer(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "stack/layer"; F1_help_topic = "stack/layer";
Plog(1,"m_stack_layer \n"); Plog(1,"m_stack_layer \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 2325 skipping to change at line 2333
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
return; return;
} }
// dialog to paint output image areas with selected input image // dialog to paint output image areas with selected input image
void STL_paint() void STL_paint()
{ {
zdialog *zd; zdialog *zd;
char imageN[8] = "imageN", labN[4] = "0"; ch imageN[8] = "imageN", labN[4] = "0";
int imx, px, py; int imx, px, py;
int STL_paint_dialog_event(zdialog *zd, cchar *event); int STL_paint_dialog_event(zdialog *zd, ch *event);
/*** /***
______________________________________ ______________________________________
| Select and Paint Image | | Select and Paint Image |
| | | |
| Image (o) 1 (o) 2 (o) 3 ... | | Image (o) 1 (o) 2 (o) 3 ... |
| | | |
| [ fill ] using selected image | | [ fill ] using selected image |
| Paint Radius [___] | | Paint Radius [___] |
| opacity center [___] edge [___] | | opacity center [___] edge [___] |
skipping to change at line 2398 skipping to change at line 2406
zdialog_resize(zd,250,0); zdialog_resize(zd,250,0);
zdialog_run(zd,STL_paint_dialog_event,"save"); // run dialog, parallel zdialog_run(zd,STL_paint_dialog_event,"save"); // run dialog, parallel
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int STL_paint_dialog_event(zdialog *zd, cchar *event) int STL_paint_dialog_event(zdialog *zd, ch *event)
{ {
int nn, px, py; int nn, px, py;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog finish if (zd->zstat) // dialog finish
{ {
freeMouse(); freeMouse();
if (zd->zstat == 1) STL_stat = 1; // user OK or cancel if (zd->zstat == 1) STL_stat = 1; // user OK or cancel
else STL_stat = 0; else STL_stat = 0;
skipping to change at line 2555 skipping to change at line 2563
void STS_mousefunc(); void STS_mousefunc();
void STS_split(); void STS_split();
int STS_stat; int STS_stat;
int Eww, Ehh, P, PP; int Eww, Ehh, P, PP;
int Finit; int Finit;
editfunc EFsts; // edit function data editfunc EFsts; // edit function data
// menu function // menu function
void m_stack_split(GtkWidget *, cchar *menu) void m_stack_split(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "stack/split"; F1_help_topic = "stack/split";
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
Plog(1,"m_stack_split \n"); Plog(1,"m_stack_split \n");
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 2610 skipping to change at line 2618
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
return; return;
} }
// dialog to paint output image areas with selected input image // dialog to paint output image areas with selected input image
void STS_start() void STS_start()
{ {
int STS_start_dialog_event(zdialog *zd, cchar *event); int STS_start_dialog_event(zdialog *zd, ch *event);
zdialog *zd; zdialog *zd;
/*** /***
_____________________________ _____________________________
| Split two Images | | Split two Images |
| | | |
| drag image boundary | | drag image boundary |
| | | |
| [ OK ] [Cancel] | | [ OK ] [Cancel] |
skipping to change at line 2642 skipping to change at line 2650
takeMouse(STS_mousefunc,0); // connect mouse function takeMouse(STS_mousefunc,0); // connect mouse function
zdialog_run(zd,STS_start_dialog_event,"save"); // run dialog, parallel zdialog_run(zd,STS_start_dialog_event,"save"); // run dialog, parallel
zdialog_wait(zd); // wait for completion zdialog_wait(zd); // wait for completion
zdialog_free(zd); zdialog_free(zd);
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int STS_start_dialog_event(zdialog *zd, cchar *event) int STS_start_dialog_event(zdialog *zd, ch *event)
{ {
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog finish if (zd->zstat) // dialog finish
{ {
freeMouse(); freeMouse();
if (zd->zstat == 1) STS_stat = 1; // user OK or cancel if (zd->zstat == 1) STS_stat = 1; // user OK or cancel
else STS_stat = 0; else STS_stat = 0;
return 1; return 1;
} }
skipping to change at line 2776 skipping to change at line 2784
Fpaint3(px,0,cc,Ehh,0); // paint new exposed area Fpaint3(px,0,cc,Ehh,0); // paint new exposed area
return; return;
} }
/******************************************************************************* */ /******************************************************************************* */
// show the differences between two images // show the differences between two images
namespace imagediffs_names namespace imagediffs_names
{ {
char *imagefile1, *imagefile2; ch *imagefile1, *imagefile2;
PXB *pxb1, *pxb2, *pxbdiffs; PXB *pxb1, *pxb2, *pxbdiffs;
int xalign, yalign; int xalign, yalign;
} }
// menu function // menu function
void m_image_diffs(GtkWidget *, const char *menu) void m_image_diffs(GtkWidget *, ch *menu)
{ {
using namespace imagediffs_names; using namespace imagediffs_names;
int imagediffs_dialog_event(zdialog* zd, const char *event); int imagediffs_dialog_event(zdialog* zd, ch *event);
F1_help_topic = "image diffs"; F1_help_topic = "image diffs";
Plog(1,"m_image_diffs \n"); Plog(1,"m_image_diffs \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
imagefile1 = imagefile2 = 0; imagefile1 = imagefile2 = 0;
pxb1 = pxb2 = pxbdiffs = 0; pxb1 = pxb2 = pxbdiffs = 0;
skipping to change at line 2844 skipping to change at line 2852
zdialog_add_widget(zd,"label","space","hbalign",0,"space=5"); zdialog_add_widget(zd,"label","space","hbalign",0,"space=5");
zdialog_add_widget(zd,"label","labyalign","hbalign","Y-align","space=3"); zdialog_add_widget(zd,"label","labyalign","hbalign","Y-align","space=3");
zdialog_add_widget(zd,"zspin","yalign","hbalign","-999|999|1|0","space=3"); zdialog_add_widget(zd,"zspin","yalign","hbalign","-999|999|1|0","space=3");
zdialog_run(zd,imagediffs_dialog_event,"save"); // run dialog - parallel zdialog_run(zd,imagediffs_dialog_event,"save"); // run dialog - parallel
return; return;
} }
// imagediffs dialog event and completion function // imagediffs dialog event and completion function
int imagediffs_dialog_event(zdialog *zd, const char *event) int imagediffs_dialog_event(zdialog *zd, ch *event)
{ {
using namespace imagediffs_names; using namespace imagediffs_names;
void imagediffs_thread(); void imagediffs_thread();
int err; int err;
char *pp; ch *pp;
GError *gerror = 0; GError *gerror = 0;
char *outfile; ch *outfile;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"done")) zd->zstat = 1; // from edit_setup() or f_save() if (strmatch(event,"done")) zd->zstat = 1; // from edit_setup() or f_save()
if (strmatch(event,"cancel")) zd->zstat = 2; // from f_open() if (strmatch(event,"cancel")) zd->zstat = 2; // from f_open()
if (zd->zstat) // done or cancel if (zd->zstat) // done or cancel
{ {
Fpxb = 0; Fpxb = 0;
if (zd->zstat == 1) { // done if (zd->zstat == 1) { // done
if (pxbdiffs) { if (pxbdiffs) {
skipping to change at line 2897 skipping to change at line 2905
if (pxb1) PXB_free(pxb1); if (pxb1) PXB_free(pxb1);
if (pxb2) PXB_free(pxb2); if (pxb2) PXB_free(pxb2);
if (pxbdiffs) PXB_free(pxbdiffs); if (pxbdiffs) PXB_free(pxbdiffs);
zdialog_free(zd); zdialog_free(zd);
return 1; return 1;
} }
if (strmatch(event,"select")) // select 2 input files if (strmatch(event,"select")) // select 2 input files
{ {
///gallery_select_clear(); // remove 22.40
err = gallery_select(); // choose thumbnails err = gallery_select(); // choose thumbnails
if (err) return 1; if (err) return 1;
if (GScount != 2) { if (GScount != 2) {
zmessageACK(Mwin,"select exactly 2 files"); zmessageACK(Mwin,"select exactly 2 files");
return 1; return 1;
} }
if (imagefile1) zfree(imagefile1); // get chosen files if (imagefile1) zfree(imagefile1); // get chosen files
imagefile1 = zstrdup(GSfiles[0],"cim image diffs"); imagefile1 = zstrdup(GSfiles[0],"cim image diffs");
if (imagefile2) zfree(imagefile2); if (imagefile2) zfree(imagefile2);
skipping to change at line 3101 skipping to change at line 3108
void pano_align(); // auto fine-align void pano_align(); // auto fine-align
void pano_adjust(); // user color adjust void pano_adjust(); // user color adjust
void panowarp_mousefunc(); // image warp mouse function void panowarp_mousefunc(); // image warp mouse function
void panowarp_dowarps(int imx); void panowarp_dowarps(int imx);
editfunc EFpano; // edit function data editfunc EFpano; // edit function data
// menu function // menu function
void m_pano_horz(GtkWidget *, cchar *menu) void m_pano_horz(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "panorama"; F1_help_topic = "panorama";
Plog(1,"m_pano_horz \n"); Plog(1,"m_pano_horz \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 3136 skipping to change at line 3143
EFpano.menufunc = m_pano_horz; EFpano.menufunc = m_pano_horz;
EFpano.menuname = "Panorama"; EFpano.menuname = "Panorama";
EFpano.mousefunc = panowarp_mousefunc; EFpano.mousefunc = panowarp_mousefunc;
if (! edit_setup(EFpano)) goto cleanup; // setup edit (will lock) if (! edit_setup(EFpano)) goto cleanup; // setup edit (will lock)
cimShowAll = 1; // for cim_show_images(), show all cimShowAll = 1; // for cim_show_images(), show all
cimPano = 1; // horizontal pano mode cimPano = 1; // horizontal pano mode
cimPanoV = 0; cimPanoV = 0;
Fescape = 1; Fwatchescape = 1;
// killable with escape // killable with escape
Fescape = 0;
pano_prealign(); // manual pre-alignment pano_prealign(); // manual pre-alignment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
pano_align(); // auto full alignment pano_align(); // auto full alignment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
pano_adjust(); // manual color adjustment pano_adjust(); // manual color adjustment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
CEF->Fmods++; // done CEF->Fmods++; // done
CEF->Fsaved = 0; CEF->Fsaved = 0;
edit_done(0); edit_done(0);
goto cleanup; goto cleanup;
cancel: // failed or canceled cancel: // failed or canceled
edit_cancel(0); edit_cancel(0);
if (Fescape > 1) // user cancel if (Fescape) // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// perform manual pre-align of all images // perform manual pre-align of all images
// returns alignment data in cimOffs[*] // returns alignment data in cimOffs[*]
// lens_mm may also be altered // lens_mm may also be altered
void pano_prealign() void pano_prealign()
{ {
int pano_prealign_event(zdialog *zd, cchar *event); // dialog event function int pano_prealign_event(zdialog *zd, ch *event); // dialog event function
void pano_prealign_mousefunc(); void pano_prealign_mousefunc();
int imx, ww, err = 0; int imx, ww, err = 0;
cchar *exifkey[2] = { exif_focal_length_35_key, exif_focal_length_key } ch *metakey[2] = { meta_focal_length_35_key, meta_focal_length_key }
; ;
char *pp[2] = { 0, 0 }; ch *pp[2] = { 0, 0 };
cchar *lens_source; ch *lens_source;
float temp; float temp;
cchar *align_mess = "Drag images into rough alignment.\n" ch *align_mess = "Drag images into rough alignment.\n"
"To rotate, drag from lower edge."; "To rotate, drag from lower edge.";
cchar *scan_mess = "no curve (scanned image)"; ch *scan_mess = "no curve (scanned image)";
cchar *search_mess = "Search for lens mm"; ch *search_mess = "Search for lens mm";
cchar *save_mess = "Save lens mm → image EXIF"; ch *save_mess = "Save lens mm → image metadata";
err = 1; err = 1;
lens_source = "NO EXIF"; lens_source = "no metadata";
exif_get(curr_file,exifkey,pp,2); meta_get1(curr_file,(ch **) metakey,pp,2);
// get lens mm from EXIF if available // get lens mm from metadata if available
if (pp[0]) err = convSF(pp[0], temp, 20, 1000); // try both keys if (pp[0]) err = convSF(pp[0], temp, 20, 1000); // try both keys
else if (pp[1]) err = convSF(pp[1], temp, 20, 1000); else if (pp[1]) err = convSF(pp[1], temp, 20, 1000);
if (! err) { if (! err) {
lens_mm = temp; lens_mm = temp;
lens_source = "(EXIF)"; lens_source = "(metadata)";
} }
for (imx = 0; imx < 10; imx++) // set all alignment offsets = 0 for (imx = 0; imx < 10; imx++) // set all alignment offsets = 0
memset(&cimOffs[imx],0,sizeof(cimoffs)); memset(&cimOffs[imx],0,sizeof(cimoffs));
for (imx = ww = 0; imx < cimNF; imx++) // sum image widths for (imx = ww = 0; imx < cimNF; imx++) // sum image widths
ww += cimPXMf[imx]->ww; ww += cimPXMf[imx]->ww;
cimScale = 1.4 * panPreAlignSize / ww; // set alignment image scale cimScale = 1.4 * panPreAlignSize / ww; // set alignment image scale
if (cimScale > 1.0) cimScale = 1.0; // (* 0.7 after overlaps) if (cimScale > 1.0) cimScale = 1.0; // (* 0.7 after overlaps)
skipping to change at line 3231 skipping to change at line 3239
cimBlend = panPreAlignBlend * cimPXMw[1]->ww; // overlap in align window cimBlend = panPreAlignBlend * cimPXMw[1]->ww; // overlap in align window
cim_show_images(1,0); // combine and show images in main window cim_show_images(1,0); // combine and show images in main window
/* /*
_________________________________________ _________________________________________
| Pre-align Images | | Pre-align Images |
| | | |
| Drag images into rough alignment. | | Drag images into rough alignment. |
| To rotate, drag from lower edge. | | To rotate, drag from lower edge. |
| | | |
| [ 35.5 ] lens mm (EXIF) | | [ 35.5 ] lens mm (metadata) |
| [x] no curve (scanned image) | | [x] no curve (scanned image) |
| [x] no auto warp | | [x] no auto warp |
| [x] manual align | | [x] manual align |
| [Resize] resize window | | [Resize] resize window |
| [Search] Search for lens mm | | [Search] Search for lens mm |
| [Save] Save lens mm -> image EXIF | | [Save] Save lens mm -> image metadata |
| | | |
| [Proceed] [Cancel] | | [Proceed] [Cancel] |
|_________________________________________| |_________________________________________|
*/ */
panozd = zdialog_new("Pre-align Images",Mwin,"Proceed","Cancel",null); // start pre-align dialog panozd = zdialog_new("Pre-align Images",Mwin,"Proceed","Cancel",null); // start pre-align dialog
zdialog_add_widget(panozd,"label","lab1","dialog",align_mess,"space=3"); zdialog_add_widget(panozd,"label","lab1","dialog",align_mess,"space=3");
zdialog_add_widget(panozd,"hbox","hb1","dialog",0); zdialog_add_widget(panozd,"hbox","hb1","dialog",0);
zdialog_add_widget(panozd,"zspin","spmm","hb1","20|999|0.1|35","space=5"); zdialog_add_widget(panozd,"zspin","spmm","hb1","20|999|0.1|35","space=5");
skipping to change at line 3286 skipping to change at line 3294
zdialog_run(panozd,pano_prealign_event,"save"); // start dialog zdialog_run(panozd,pano_prealign_event,"save"); // start dialog
takeMouse(pano_prealign_mousefunc,dragcursor); // connect mouse takeMouse(pano_prealign_mousefunc,dragcursor); // connect mouse
zdialog_wait(panozd); // wait for dialog completion zdialog_wait(panozd); // wait for dialog completion
zdialog_free(panozd); // free dialog zdialog_free(panozd); // free dialog
freeMouse(); freeMouse();
return; return;
} }
// pre-align dialog event function // pre-align dialog event function
int pano_prealign_event(zdialog *zd, cchar *event) int pano_prealign_event(zdialog *zd, ch *event)
{ {
void pano_autolens(); void pano_autolens();
int imx, fchange = 0; int imx, fchange = 0;
float overlap; float overlap;
cchar *exifkey[1] = { exif_focal_length_35_key }; ch *metakey[1] = { meta_focal_length_35_key };
cchar *exifdata[1]; ch *metadata[1];
char lensdata[8]; ch lensdata[8];
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"spmm")) { if (strmatch(event,"spmm")) {
zdialog_fetch(zd,"spmm",lens_mm); // get revised lens data zdialog_fetch(zd,"spmm",lens_mm); // get revised lens data
fchange = 1; fchange = 1;
} }
if (strmatch(event,"nocurve")) { if (strmatch(event,"nocurve")) {
zdialog_fetch(zd,"nocurve",cimPanoNC); // get "no-curve" option zdialog_fetch(zd,"nocurve",cimPanoNC); // get "no-curve" option
skipping to change at line 3339 skipping to change at line 3347
if (strmatch(event,"search")) { // search for optimal lens parms if (strmatch(event,"search")) { // search for optimal lens parms
if (cimNF != 2) zmessageACK(Mwin,"use two images only"); if (cimNF != 2) zmessageACK(Mwin,"use two images only");
else pano_autolens(); else pano_autolens();
return 1; return 1;
} }
if (strmatch(event,"save")) { // put lens data into dialog if (strmatch(event,"save")) { // put lens data into dialog
zdialog_stuff(zd,"spmm",lens_mm); zdialog_stuff(zd,"spmm",lens_mm);
snprintf(lensdata,8,"%d",int(lens_mm)); snprintf(lensdata,8,"%d",int(lens_mm));
exifdata[0] = lensdata; metadata[0] = lensdata;
for (imx = 0; imx < cimNF; imx++) for (imx = 0; imx < cimNF; imx++)
// save lens mm in EXIF data // save lens mm in metadata
exif_put(cimFile[imx],exifkey,exifdata,1); meta_put(cimFile[imx],(ch **) metakey,metadata,1);
} }
if (zd->zstat) // dialog complete if (zd->zstat) // dialog complete
{ {
if (zd->zstat != 1) { // cancel or other if (zd->zstat != 1) { // cancel or other
panStat = 0; panStat = 0;
return 1; return 1;
} }
m_zoom(0,"fit"); // reset poss. user zoom-in m_zoom(0,"fit"); // reset poss. user zoom-in
skipping to change at line 3376 skipping to change at line 3384
return 1; return 1;
} }
// pre-align mouse function // pre-align mouse function
// convert mouse and KB events into image movements // convert mouse and KB events into image movements
void pano_prealign_mousefunc() void pano_prealign_mousefunc()
{ {
cimoffs offstemp; cimoffs offstemp;
PXM *pxmtemp; PXM *pxmtemp;
char *ftemp; ch *ftemp;
static int im1, im2, imm, imx; static int im1, im2, imm, imx;
static int mx0, my0, mx, my; // mouse drag origin, position static int mx0, my0, mx, my; // mouse drag origin, position
static int xoff, yoff, lox, hix; static int xoff, yoff, lox, hix;
static int hh, rotate, midx; static int hh, rotate, midx;
int sepx, minsep = 9999; int sepx, minsep = 9999;
float dx, dy, t1, t2, dt; float dx, dy, t1, t2, dt;
cimBlend = 0; // full blend during pre-align cimBlend = 0; // full blend during pre-align
if (! Mxdrag && ! Mydrag) // no drag underway if (! Mxdrag && ! Mydrag) // no drag underway
skipping to change at line 3512 skipping to change at line 3520
zmessageACK(Mwin,"Too little overlap, cannot align"); zmessageACK(Mwin,"Too little overlap, cannot align");
return; return;
} }
if (cimNF != 2) { if (cimNF != 2) {
zmessageACK(Mwin,"use 2 images only"); zmessageACK(Mwin,"use 2 images only");
return; return;
} }
zadd_locked(Ffuncbusy,+1); zadd_locked(Ffuncbusy,+1);
Fwatchescape = 1;
// killable with escape key
Fescape = 0;
cimSampSize = 5000; cimSampSize = 5000;
cimNsearch = 0; cimNsearch = 0;
mm_range = 0.1 * lens_mm; // set initial search ranges mm_range = 0.1 * lens_mm; // set initial search ranges
xf_range = 7; xf_range = 7;
yf_range = 7; yf_range = 7;
tf_range = 0.01; tf_range = 0.01;
xf_rfinal = 0.3; // final xf range - when to quit xf_rfinal = 0.3; // final xf range - when to quit
skipping to change at line 3576 skipping to change at line 3586
if (cim_sigdiff(matchlev,matchB,0.00001) > 0) { if (cim_sigdiff(matchlev,matchB,0.00001) > 0) {
matchB = matchlev; // save new best fit matchB = matchlev; // save new best fit
lens_mmB = lens_mm; // alignment is better lens_mmB = lens_mm; // alignment is better
offsetsB = cimOffs[1]; offsetsB = cimOffs[1];
cim_show_images(0,0); cim_show_images(0,0);
squeeze = 1; // keep same search range as long squeeze = 1; // keep same search range as long
break; // as improvements are found break; // as improvements are found
} }
if (panStat != -1) goto done; // user kill if (panStat != -1) goto done; // user kill
if (Fescape > 1) goto done; // escape key kill if (Fescape) goto done; // escape key kill
zmainloop(); zmainloop();
} }
if (xf_range < xf_rfinal) goto done; // finished if (xf_range < xf_rfinal) goto done; // finished
snprintf(paneltext,200,"align: %d match: %.5f lens: %.1f", snprintf(paneltext,200,"align: %d match: %.5f lens: %.1f",
cimNsearch, matchB, lens_mmB); cimNsearch, matchB, lens_mmB);
mm_range = squeeze * mm_range; // reduce search range if no mm_range = squeeze * mm_range; // reduce search range if no
if (mm_range < 0.02 * lens_mmB) mm_range = 0.02 * lens_mmB; // improvements were found if (mm_range < 0.02 * lens_mmB) mm_range = 0.02 * lens_mmB; // improvements were found
xf_range = squeeze * xf_range; xf_range = squeeze * xf_range;
yf_range = squeeze * yf_range; yf_range = squeeze * yf_range;
tf_range = squeeze * tf_range; tf_range = squeeze * tf_range;
zmainloop(); zmainloop();
} }
done: done:
Fescape = 0; // keep Fwatchescape
zfree(cimRedpix); zfree(cimRedpix);
cimRedpix = 0; cimRedpix = 0;
lens_mm = lens_mmB; // save best lens param found lens_mm = lens_mmB; // save best lens param found
cimSampSize = panSampSize; // restore cimSampSize = panSampSize; // restore
zadd_locked(Ffuncbusy,-1); zadd_locked(Ffuncbusy,-1);
cim_show_images(1,0); // images are left color-matched cim_show_images(1,0); // images are left color-matched
return; return;
} }
skipping to change at line 3729 skipping to change at line 3740
goto fail; goto fail;
} }
if (cim_manualalign) cim_show_images(0,0); if (cim_manualalign) cim_show_images(0,0);
else { else {
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cim_show_images(0,0); // show with 50/50 blend in overlaps cim_show_images(0,0); // show with 50/50 blend in overlaps
cim_align_image(im1,im2); // search for best offsets and warps cim_align_image(im1,im2); // search for best offsets and warps
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (Fescape > 1) goto fail; // user kill if (Fescape) goto fail; // user kill
} }
dx = cimOffs[im2].xf - offsets0.xf; // changes from initial offsets dx = cimOffs[im2].xf - offsets0.xf; // changes from initial offsets
dy = cimOffs[im2].yf - offsets0.yf; dy = cimOffs[im2].yf - offsets0.yf;
dt = cimOffs[im2].tf - offsets0.tf; dt = cimOffs[im2].tf - offsets0.tf;
for (imx = im2+1; imx < cimNF; imx++) // propagate to following images for (imx = im2+1; imx < cimNF; imx++) // propagate to following images
{ {
cimOffs[imx].xf += dx; cimOffs[imx].xf += dx;
cimOffs[imx].yf += dy; cimOffs[imx].yf += dy;
skipping to change at line 3793 skipping to change at line 3804
cimBlend = 1; // tiny blend (increase in adjust) cimBlend = 1; // tiny blend (increase in adjust)
zadd_locked(Ffuncbusy,-1); zadd_locked(Ffuncbusy,-1);
cim_show_images(0,0); cim_show_images(0,0);
return; return;
} }
// get user inputs for RGB changes and blend width, update cimPXMw[*] // get user inputs for RGB changes and blend width, update cimPXMw[*]
void pano_adjust() void pano_adjust()
{ {
int pano_adjust_event(zdialog *zd, cchar *event); // dialog event function int pano_adjust_event(zdialog *zd, ch *event); // dialog event function
cchar *adjusttitle = "Match Brightness and Color"; ch *adjusttitle = "Match Brightness and Color";
char imageN[8] = "imageN"; ch imageN[8] = "imageN";
int ww, hh, cc, imx; int ww, hh, cc, imx;
for (imx = 0; imx < cimNF; imx++) { // neutral color adjustments for (imx = 0; imx < cimNF; imx++) { // neutral color adjustments
pano_adjust_RGB[imx][0] = 100; pano_adjust_RGB[imx][0] = 100;
pano_adjust_RGB[imx][1] = 100; pano_adjust_RGB[imx][1] = 100;
pano_adjust_RGB[imx][2] = 100; pano_adjust_RGB[imx][2] = 100;
} }
for (imx = 0; imx < cimNF; imx++) { // allocate warp memory for (imx = 0; imx < cimNF; imx++) { // allocate warp memory
ww = cimPXMw[imx]->ww; ww = cimPXMw[imx]->ww;
skipping to change at line 3886 skipping to change at line 3897
panStat = -1; // busy status panStat = -1; // busy status
zdialog_run(panozd,pano_adjust_event,"save"); // run dialog, parallel zdialog_run(panozd,pano_adjust_event,"save"); // run dialog, parallel
zdialog_wait(panozd); // wait for dialog completion zdialog_wait(panozd); // wait for dialog completion
zdialog_free(panozd); // free dialog zdialog_free(panozd); // free dialog
return; return;
} }
// dialog event function // dialog event function
int pano_adjust_event(zdialog *zd, cchar *event) int pano_adjust_event(zdialog *zd, ch *event)
{ {
char imageN[8] = "imageN"; ch imageN[8] = "imageN";
float R, G, B, R1, G1, B1, F; float R, G, B, R1, G1, B1, F;
float max$; float max$;
int imS, imx, im1, im2; int imS, imx, im1, im2;
int ww, hh, px, py, nn; int ww, hh, px, py, nn;
float bright, bright2, *pixel; float bright, bright2, *pixel;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog complete if (zd->zstat) // dialog complete
{ {
skipping to change at line 4211 skipping to change at line 4222
******************************************************************************** */ ******************************************************************************** */
void vpano_prealign(); // manual pre-align void vpano_prealign(); // manual pre-align
void vpano_align(); // auto fine-align void vpano_align(); // auto fine-align
void vpano_adjust(); // user color adjust void vpano_adjust(); // user color adjust
editfunc EFvpano; // edit function data editfunc EFvpano; // edit function data
// menu function // menu function
void m_pano_vert(GtkWidget *, cchar *menu) void m_pano_vert(GtkWidget *, ch *menu)
{ {
int err; int err;
F1_help_topic = "vert. panorama"; F1_help_topic = "vert. panorama";
Plog(1,"m_pano_vert \n"); Plog(1,"m_pano_vert \n");
if (FGWM != 'F' && FGWM != 'G') return; if (FGWM != 'F' && FGWM != 'G') return;
if (Fblock(0,"blocked edits")) return; // check nothing pending if (Fblock(0,"blocked edits")) return; // check nothing pending
skipping to change at line 4246 skipping to change at line 4257
EFvpano.menufunc = m_pano_vert; EFvpano.menufunc = m_pano_vert;
EFvpano.menuname = "V. Panorama"; EFvpano.menuname = "V. Panorama";
EFvpano.mousefunc = panowarp_mousefunc; EFvpano.mousefunc = panowarp_mousefunc;
if (! edit_setup(EFvpano)) goto cleanup; // setup edit (will lock) if (! edit_setup(EFvpano)) goto cleanup; // setup edit (will lock)
cimShowAll = 1; // for cim_show_images(), show all cimShowAll = 1; // for cim_show_images(), show all
cimPano = 0; // vertical pano mode cimPano = 0; // vertical pano mode
cimPanoV = 1; cimPanoV = 1;
Fescape = 1; Fwatchescape = 1;
// killable with escape key // killable with escape key
Fescape = 0;
vpano_prealign(); // manual pre-alignment vpano_prealign(); // manual pre-alignment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
vpano_align(); // auto full alignment vpano_align(); // auto full alignment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
vpano_adjust(); // manual color adjustment vpano_adjust(); // manual color adjustment
if (panStat != 1) goto cancel; if (panStat != 1) goto cancel;
CEF->Fmods++; // done CEF->Fmods++; // done
CEF->Fsaved = 0; CEF->Fsaved = 0;
edit_done(0); edit_done(0);
goto cleanup; goto cleanup;
cancel: // failed or canceled cancel: // failed or canceled
edit_cancel(0); edit_cancel(0);
if (Fescape > 1) // user cancel if (Fescape) // user cancel
zmessage_post_bold(Mwin,"parent",3,"function canceled"); zmessage_post_bold(Mwin,"parent",3,"function canceled");
cleanup: cleanup:
cim_free_memory(); // free memory for input files cim_free_memory(); // free memory for input files
*paneltext = 0; *paneltext = 0;
Fescape = 0; Fwatchescape = Fescape = 0;
return; return;
} }
// perform manual pre-align of all images // perform manual pre-align of all images
// returns alignment data in cimOffs[*] // returns alignment data in cimOffs[*]
// lens_mm may also be altered // lens_mm may also be altered
void vpano_prealign() void vpano_prealign()
{ {
int vpano_prealign_event(zdialog *zd, cchar *event); // dialog event function int vpano_prealign_event(zdialog *zd, ch *event); // dialog event function
void vpano_prealign_mousefunc(); void vpano_prealign_mousefunc();
int imx, hh, err = 0; int imx, hh, err = 0;
cchar *exifkey[2] = { exif_focal_length_35_key, exif_focal_length_key } ch *metakey[2] = { meta_focal_length_35_key, meta_focal_length_key }
; ;
char *pp[2] = { 0, 0 }; ch *pp[2] = { 0, 0 };
cchar *lens_source; ch *lens_source;
float temp; float temp;
cchar *align_mess = "Drag images into rough alignment.\n" ch *align_mess = "Drag images into rough alignment.\n"
"To rotate, drag from right edge."; "To rotate, drag from right edge.";
cchar *scan_mess = "no curve (scanned image)"; ch *scan_mess = "no curve (scanned image)";
cchar *search_mess = "Search for lens mm"; ch *search_mess = "Search for lens mm";
cchar *save_mess = "Save lens mm → image EXIF"; ch *save_mess = "Save lens mm → image metadata";
err = 1; err = 1;
lens_source = "NO EXIF"; lens_source = "no metadata";
exif_get(curr_file,exifkey,pp,2); meta_get1(curr_file,(ch **) metakey,pp,2);
// get lens mm from EXIF if available // get lens mm from metadata if available
if (pp[0]) err = convSF(pp[0], temp, 20, 1000); // try both keys if (pp[0]) err = convSF(pp[0], temp, 20, 1000); // try both keys
else if (pp[1]) err = convSF(pp[1], temp, 20, 1000); else if (pp[1]) err = convSF(pp[1], temp, 20, 1000);
if (! err) { if (! err) {
lens_mm = temp; lens_mm = temp;
lens_source = "(EXIF)"; lens_source = "(metadata)";
} }
for (imx = 0; imx < 10; imx++) // set all alignment offsets = 0 for (imx = 0; imx < 10; imx++) // set all alignment offsets = 0
memset(&cimOffs[imx],0,sizeof(cimoffs)); memset(&cimOffs[imx],0,sizeof(cimoffs));
for (imx = hh = 0; imx < cimNF; imx++) // sum image heights for (imx = hh = 0; imx < cimNF; imx++) // sum image heights
hh += cimPXMf[imx]->hh; hh += cimPXMf[imx]->hh;
cimScale = 1.4 * panPreAlignSize / hh; // set alignment image scale cimScale = 1.4 * panPreAlignSize / hh; // set alignment image scale
if (cimScale > 1.0) cimScale = 1.0; // (* 0.7 after overlaps) if (cimScale > 1.0) cimScale = 1.0; // (* 0.7 after overlaps)
skipping to change at line 4341 skipping to change at line 4353
cimBlend = panPreAlignBlend * cimPXMw[1]->hh; // overlap in align window cimBlend = panPreAlignBlend * cimPXMw[1]->hh; // overlap in align window
cim_show_Vimages(1,0); // combine and show images in main window cim_show_Vimages(1,0); // combine and show images in main window
/* /*
_________________________________________ _________________________________________
| Pre-align Images | | Pre-align Images |
| | | |
| Drag images into rough alignment. | | Drag images into rough alignment. |
| To rotate, drag from right edge. | | To rotate, drag from right edge. |
| | | |
| [ 35.5 ] lens mm (EXIF) | | [ 35.5 ] lens mm (metadata) |
| [x] no curve (scanned image) | | [x] no curve (scanned image) |
| [x] no auto warp | | [x] no auto warp |
| [x] manual align | | [x] manual align |
| [Resize] resize window | | [Resize] resize window |
| [Search] Search for lens mm | | [Search] Search for lens mm |
| [Save] Save lens mm -> image EXIF | | [Save] Save lens mm -> image metadata |
| | | |
| [Proceed] [Cancel] | | [Proceed] [Cancel] |
|_________________________________________| |_________________________________________|
*/ */
panozd = zdialog_new("Pre-align Images",Mwin,"Proceed","Cancel",null); // start pre-align dialog panozd = zdialog_new("Pre-align Images",Mwin,"Proceed","Cancel",null); // start pre-align dialog
zdialog_add_widget(panozd,"label","lab1","dialog",align_mess,"space=3"); zdialog_add_widget(panozd,"label","lab1","dialog",align_mess,"space=3");
zdialog_add_widget(panozd,"hbox","hb1","dialog",0); zdialog_add_widget(panozd,"hbox","hb1","dialog",0);
zdialog_add_widget(panozd,"zspin","spmm","hb1","20|999|0.1|35","space=5"); zdialog_add_widget(panozd,"zspin","spmm","hb1","20|999|0.1|35","space=5");
skipping to change at line 4396 skipping to change at line 4408
zdialog_run(panozd,vpano_prealign_event,"save"); // start dialog zdialog_run(panozd,vpano_prealign_event,"save"); // start dialog
takeMouse(vpano_prealign_mousefunc,dragcursor); // connect mouse takeMouse(vpano_prealign_mousefunc,dragcursor); // connect mouse
zdialog_wait(panozd); // wait for dialog completion zdialog_wait(panozd); // wait for dialog completion
zdialog_free(panozd); // free dialog zdialog_free(panozd); // free dialog
freeMouse(); freeMouse();
return; return;
} }
// pre-align dialog event function // pre-align dialog event function
int vpano_prealign_event(zdialog *zd, cchar *event) int vpano_prealign_event(zdialog *zd, ch *event)
{ {
void vpano_autolens(); void vpano_autolens();
int imx, fchange = 0; int imx, fchange = 0;
float overlap; float overlap;
cchar *exifkey[1] = { exif_focal_length_35_key }; ch *metakey[1] = { meta_focal_length_35_key };
cchar *exifdata[1]; ch *metadata[1];
char lensdata[8]; ch lensdata[8];
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"spmm")) { if (strmatch(event,"spmm")) {
zdialog_fetch(zd,"spmm",lens_mm); // get revised lens data zdialog_fetch(zd,"spmm",lens_mm); // get revised lens data
fchange = 1; fchange = 1;
} }
if (strmatch(event,"nocurve")) { if (strmatch(event,"nocurve")) {
zdialog_fetch(zd,"nocurve",cimPanoNC); // get "no-curve" option zdialog_fetch(zd,"nocurve",cimPanoNC); // get "no-curve" option
skipping to change at line 4449 skipping to change at line 4461
if (strmatch(event,"search")) { // search for optimal lens parms if (strmatch(event,"search")) { // search for optimal lens parms
if (cimNF != 2) zmessageACK(Mwin,"use two images only"); if (cimNF != 2) zmessageACK(Mwin,"use two images only");
else vpano_autolens(); else vpano_autolens();
return 1; return 1;
} }
if (strmatch(event,"save")) { // put lens data into dialog if (strmatch(event,"save")) { // put lens data into dialog
zdialog_stuff(zd,"spmm",lens_mm); zdialog_stuff(zd,"spmm",lens_mm);
snprintf(lensdata,8,"%d",int(lens_mm)); snprintf(lensdata,8,"%d",int(lens_mm));
exifdata[0] = lensdata; metadata[0] = lensdata;
for (imx = 0; imx < cimNF; imx++) for (imx = 0; imx < cimNF; imx++)
// save lens mm in EXIF data // save lens mm in metadata
exif_put(cimFile[imx],exifkey,exifdata,1); meta_put(cimFile[imx],(ch **) metakey,metadata,1);
} }
if (zd->zstat) // dialog complete if (zd->zstat) // dialog complete
{ {
if (zd->zstat != 1) { // cancel or other if (zd->zstat != 1) { // cancel or other
panStat = 0; panStat = 0;
return 1; return 1;
} }
m_zoom(0,"fit"); // reset poss. user zoom-in m_zoom(0,"fit"); // reset poss. user zoom-in
skipping to change at line 4486 skipping to change at line 4498
return 1; return 1;
} }
// pre-align mouse function // pre-align mouse function
// convert mouse and KB events into image movements // convert mouse and KB events into image movements
void vpano_prealign_mousefunc() void vpano_prealign_mousefunc()
{ {
cimoffs offstemp; cimoffs offstemp;
PXM *pxmtemp; PXM *pxmtemp;
char *ftemp; ch *ftemp;
static int im1, im2, imm, imx; static int im1, im2, imm, imx;
static int mx0, my0, mx, my; // mouse drag origin, position static int mx0, my0, mx, my; // mouse drag origin, position
static int xoff, yoff, loy, hiy; static int xoff, yoff, loy, hiy;
static int ww, rotate, midy; static int ww, rotate, midy;
int sepy, minsep = 9999; int sepy, minsep = 9999;
float dx, dy, t1, t2, dt; float dx, dy, t1, t2, dt;
cimBlend = 0; // full blend during pre-align cimBlend = 0; // full blend during pre-align
if (! Mxdrag && ! Mydrag) // no drag underway if (! Mxdrag && ! Mydrag) // no drag underway
skipping to change at line 4622 skipping to change at line 4634
zmessageACK(Mwin,"Too little overlap, cannot align"); zmessageACK(Mwin,"Too little overlap, cannot align");
return; return;
} }
if (cimNF != 2) { if (cimNF != 2) {
zmessageACK(Mwin,"use 2 images only"); zmessageACK(Mwin,"use 2 images only");
return; return;
} }
zadd_locked(Ffuncbusy,+1); zadd_locked(Ffuncbusy,+1);
Fwatchescape = 1;
Fescape = 0;
cimSampSize = 5000; cimSampSize = 5000;
cimNsearch = 0; cimNsearch = 0;
mm_range = 0.1 * lens_mm; // set initial search ranges mm_range = 0.1 * lens_mm; // set initial search ranges
xf_range = 7; xf_range = 7;
yf_range = 7; yf_range = 7;
tf_range = 0.01; tf_range = 0.01;
xf_rfinal = 0.3; // final xf range - when to quit xf_rfinal = 0.3; // final xf range - when to quit
skipping to change at line 4686 skipping to change at line 4700
if (cim_sigdiff(matchlev,matchB,0.00001) > 0) { if (cim_sigdiff(matchlev,matchB,0.00001) > 0) {
matchB = matchlev; // save new best fit matchB = matchlev; // save new best fit
lens_mmB = lens_mm; // alignment is better lens_mmB = lens_mm; // alignment is better
offsetsB = cimOffs[1]; offsetsB = cimOffs[1];
cim_show_Vimages(0,0); cim_show_Vimages(0,0);
squeeze = 1; // keep same search range as long squeeze = 1; // keep same search range as long
break; // as improvements are found break; // as improvements are found
} }
if (panStat != -1) goto done; // user kill if (panStat != -1) goto done; // user kill
if (Fescape > 1) goto done; // kill via escape key if (Fescape) goto done; // kill via escape key
zmainloop(); zmainloop();
} }
if (xf_range < xf_rfinal) goto done; // finished if (xf_range < xf_rfinal) goto done; // finished
snprintf(paneltext,200,"align: %d match: %.5f lens: %.1f", snprintf(paneltext,200,"align: %d match: %.5f lens: %.1f",
cimNsearch, matchB, lens_mmB); cimNsearch, matchB, lens_mmB);
mm_range = squeeze * mm_range; // reduce search range if no mm_range = squeeze * mm_range; // reduce search range if no
if (mm_range < 0.02 * lens_mmB) mm_range = 0.02 * lens_mmB; // improvements were found if (mm_range < 0.02 * lens_mmB) mm_range = 0.02 * lens_mmB; // improvements were found
xf_range = squeeze * xf_range; xf_range = squeeze * xf_range;
yf_range = squeeze * yf_range; yf_range = squeeze * yf_range;
tf_range = squeeze * tf_range; tf_range = squeeze * tf_range;
zmainloop(); zmainloop();
} }
done: done:
Fescape = 0; // keep Fwatchchescape
zfree(cimRedpix); zfree(cimRedpix);
cimRedpix = 0; cimRedpix = 0;
lens_mm = lens_mmB; // save best lens params found lens_mm = lens_mmB; // save best lens params found
cimSampSize = panSampSize; // restore cimSampSize = panSampSize; // restore
zadd_locked(Ffuncbusy,-1); zadd_locked(Ffuncbusy,-1);
cim_show_Vimages(1,0); // images are left color-matched cim_show_Vimages(1,0); // images are left color-matched
return; return;
} }
skipping to change at line 4816 skipping to change at line 4831
goto fail; goto fail;
} }
if (cim_manualalign) cim_show_Vimages(0,0); if (cim_manualalign) cim_show_Vimages(0,0);
else { else {
cim_get_redpix(im1); // get high-contrast pixels cim_get_redpix(im1); // get high-contrast pixels
cim_show_Vimages(0,0); // show with 50/50 blend in overlaps cim_show_Vimages(0,0); // show with 50/50 blend in overlaps
cim_align_image(im1,im2); // search for best offsets and warps cim_align_image(im1,im2); // search for best offsets and warps
zfree(cimRedpix); // clear red pixels zfree(cimRedpix); // clear red pixels
cimRedpix = 0; cimRedpix = 0;
if (Fescape > 1) goto fail; // user kill if (Fescape) goto fail; // user kill
} }
dx = cimOffs[im2].xf - offsets0.xf; // changes from initial offsets dx = cimOffs[im2].xf - offsets0.xf; // changes from initial offsets
dy = cimOffs[im2].yf - offsets0.yf; dy = cimOffs[im2].yf - offsets0.yf;
dt = cimOffs[im2].tf - offsets0.tf; dt = cimOffs[im2].tf - offsets0.tf;
for (imx = im2+1; imx < cimNF; imx++) // propagate to following images for (imx = im2+1; imx < cimNF; imx++) // propagate to following images
{ {
cimOffs[imx].xf += dx; cimOffs[imx].xf += dx;
cimOffs[imx].yf += dy; cimOffs[imx].yf += dy;
skipping to change at line 4880 skipping to change at line 4895
zadd_locked(Ffuncbusy,-1); zadd_locked(Ffuncbusy,-1);
cimBlend = 1; // tiny blend (increase in adjust if wanted) cimBlend = 1; // tiny blend (increase in adjust if wanted)
cim_show_Vimages(0,0); cim_show_Vimages(0,0);
return; return;
} }
// get user inputs for RGB changes and blend width, update cimPXMw[*] // get user inputs for RGB changes and blend width, update cimPXMw[*]
void vpano_adjust() void vpano_adjust()
{ {
int vpano_adjust_event(zdialog *zd, cchar *event); // dialog event function int vpano_adjust_event(zdialog *zd, ch *event); // dialog event function
cchar *adjusttitle = "Match Brightness and Color"; ch *adjusttitle = "Match Brightness and Color";
char imageN[8] = "imageN"; ch imageN[8] = "imageN";
int ww, hh, cc, imx; int ww, hh, cc, imx;
for (imx = 0; imx < cimNF; imx++) { // neutral color adjustments for (imx = 0; imx < cimNF; imx++) { // neutral color adjustments
pano_adjust_RGB[imx][0] = 100; pano_adjust_RGB[imx][0] = 100;
pano_adjust_RGB[imx][1] = 100; pano_adjust_RGB[imx][1] = 100;
pano_adjust_RGB[imx][2] = 100; pano_adjust_RGB[imx][2] = 100;
} }
for (imx = 0; imx < cimNF; imx++) { // allocate warp memory for (imx = 0; imx < cimNF; imx++) { // allocate warp memory
ww = cimPXMw[imx]->ww; ww = cimPXMw[imx]->ww;
skipping to change at line 4973 skipping to change at line 4988
panStat = -1; // busy status panStat = -1; // busy status
zdialog_run(panozd,vpano_adjust_event,"save"); // run dialog, parallel zdialog_run(panozd,vpano_adjust_event,"save"); // run dialog, parallel
zdialog_wait(panozd); // wait for dialog completion zdialog_wait(panozd); // wait for dialog completion
zdialog_free(panozd); // free dialog zdialog_free(panozd); // free dialog
return; return;
} }
// dialog event function // dialog event function
int vpano_adjust_event(zdialog *zd, cchar *event) int vpano_adjust_event(zdialog *zd, ch *event)
{ {
char imageN[8] = "imageN"; ch imageN[8] = "imageN";
float R, G, B, R1, G1, B1, F; float R, G, B, R1, G1, B1, F;
float max$; float max$;
int imS, imx, im1, im2; int imS, imx, im1, im2;
int ww, hh, px, py, nn; int ww, hh, px, py, nn;
float bright, bright2, *pixel; float bright, bright2, *pixel;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (zd->zstat) // dialog complete if (zd->zstat) // dialog complete
{ {
skipping to change at line 5193 skipping to change at line 5208
Fpaint2(); Fpaint2();
} }
return 1; return 1;
} }
/******************************************************************************* */ /******************************************************************************* */
// show files selected for present or last combine edit function // show files selected for present or last combine edit function
void m_cim_show_files(GtkWidget *, cchar *) void m_cim_show_files(GtkWidget *, ch *)
{ {
F1_help_topic = "show CIM files"; F1_help_topic = "show CIM files";
zdialog *zd; zdialog *zd;
if (! cimNF) { if (! cimNF) {
zmessageACK(Mwin,"no input files available"); zmessageACK(Mwin,"no input files available");
return; return;
} }
skipping to change at line 5229 skipping to change at line 5244
int im; int im;
cimNF = 0; cimNF = 0;
for (im = 0; im < 10; im++) // clear previous file list for (im = 0; im < 10; im++) // clear previous file list
{ {
if (cimFile[im]) zfree(cimFile[im]); if (cimFile[im]) zfree(cimFile[im]);
cimFile[im] = 0; cimFile[im] = 0;
} }
///gallery_select_clear(); // clear selected file list remove 22.40
gallery_select(); // get new list gallery_select(); // get new list
if (GScount == 0) return 0; if (GScount == 0) return 0;
if (GScount < min || GScount > max) { if (GScount < min || GScount > max) {
zmessageACK(Mwin,"Select %d to %d files",min,max); zmessageACK(Mwin,"Select %d to %d files",min,max);
return 0; return 0;
} }
cimNF = GScount; // file count cimNF = GScount; // file count
skipping to change at line 5786 skipping to change at line 5800
// flag high-contrast pixels to use in each image compare region // flag high-contrast pixels to use in each image compare region
void cim_get_redpix(int im1) void cim_get_redpix(int im1)
{ {
int ww, hh, samp, xzone, yzone; int ww, hh, samp, xzone, yzone;
int pxL, pxH, pyL, pyH; int pxL, pxH, pyL, pyH;
int px, py, ii, jj, npix; int px, py, ii, jj, npix;
int ov1xlo, ov1xhi, ov1ylo, ov1yhi; int ov1xlo, ov1xhi, ov1ylo, ov1yhi;
int Hdist[256], Vdist[256], Hmin, Vmin; int Hdist[256], Vdist[256], Hmin, Vmin;
float zsamp[16] = { 5,5,5,5, 7,8,8,7, 7,8,8,7, 5,5,5,5 }; // % sample per zone, sum = 100 float zsamp[16] = { 5,5,5,5, 7,8,8,7, 7,8,8,7, 5,5,5,5 }; // % sample per zone, sum = 100
uchar *Hcon, *Vcon; uch *Hcon, *Vcon;
float *pix1, *pix2; float *pix1, *pix2;
PXM *pxm; PXM *pxm;
pxm = cimPXMs[im1]; pxm = cimPXMs[im1];
ww = pxm->ww; ww = pxm->ww;
hh = pxm->hh; hh = pxm->hh;
if (cimRedpix) zfree(cimRedpix); // clear prior if (cimRedpix) zfree(cimRedpix); // clear prior
cimRedpix = (char *) zmalloc(ww*hh,"cim redpix"); cimRedpix = (ch *) zmalloc(ww*hh,"cim redpix");
cimRedImage = im1; // image with red pixels cimRedImage = im1; // image with red pixels
ov1xlo = cimOv1xlo + cimSearchRange; // stay within x/y search range ov1xlo = cimOv1xlo + cimSearchRange; // stay within x/y search range
ov1xhi = cimOv1xhi - cimSearchRange; // so that red pixels persist ov1xhi = cimOv1xhi - cimSearchRange; // so that red pixels persist
ov1ylo = cimOv1ylo + cimSearchRange; // over offset changes ov1ylo = cimOv1ylo + cimSearchRange; // over offset changes
ov1yhi = cimOv1yhi - cimSearchRange; ov1yhi = cimOv1yhi - cimSearchRange;
for (yzone = 0; yzone < 4; yzone++) // loop 16 zones for (yzone = 0; yzone < 4; yzone++) // loop 16 zones
for (xzone = 0; xzone < 4; xzone++) for (xzone = 0; xzone < 4; xzone++)
{ {
pxL = ov1xlo + 0.25 * xzone * (ov1xhi - ov1xlo); // px and py zone limits pxL = ov1xlo + 0.25 * xzone * (ov1xhi - ov1xlo); // px and py zone limits
pxH = ov1xlo + 0.25 * (xzone+1) * (ov1xhi - ov1xlo); pxH = ov1xlo + 0.25 * (xzone+1) * (ov1xhi - ov1xlo);
pyL = ov1ylo + 0.25 * yzone * (ov1yhi - ov1ylo); pyL = ov1ylo + 0.25 * yzone * (ov1yhi - ov1ylo);
pyH = ov1ylo + 0.25 * (yzone+1) * (ov1yhi - ov1ylo); pyH = ov1ylo + 0.25 * (yzone+1) * (ov1yhi - ov1ylo);
npix = (pxH - pxL) * (pyH - pyL); // zone pixels npix = (pxH - pxL) * (pyH - pyL); // zone pixels
if (npix < 1) continue; if (npix < 1) continue;
Hcon = (uchar *) zmalloc(npix,"cim redpix"); Hcon = (uch *) zmalloc(npix,"cim redpix");
// horizontal pixel contrast 0-255 // horizontal pixel contrast 0-255
Vcon = (uchar *) zmalloc(npix,"cim redpix"); Vcon = (uch *) zmalloc(npix,"cim redpix");
// vertical pixel contrast 0-255 // vertical pixel contrast 0-255
ii = 4 * yzone + xzone; ii = 4 * yzone + xzone;
samp = cimSampSize * 0.01 * zsamp[ii]; // sample size for zone samp = cimSampSize * 0.01 * zsamp[ii]; // sample size for zone
if (samp > 0.1 * npix) samp = 0.1 * npix; // limit to 10% of zone pixels if (samp > 0.1 * npix) samp = 0.1 * npix; // limit to 10% of zone pixels
if (samp > 500) samp = 500; if (samp > 500) samp = 500;
for (py = pyL; py < pyH; py++) // scan image pixels in zone for (py = pyL; py < pyH; py++) // scan image pixels in zone
for (px = pxL; px < pxH; px++) for (px = pxL; px < pxH; px++)
{ {
ii = (py-pyL) * (pxH-pxL) + (px-pxL); ii = (py-pyL) * (pxH-pxL) + (px-pxL);
skipping to change at line 6336 skipping to change at line 6350
match = cim_match_images(im1,im2); // get match level match = cim_match_images(im1,im2); // get match level
if (cim_sigdiff(match,matchB,0.00001) > 0) { if (cim_sigdiff(match,matchB,0.00001) > 0) {
matchB = match; // save best match matchB = match; // save best match
offsetsB = cimOffs[im2]; offsetsB = cimOffs[im2];
} }
snprintf(paneltext,200,"align: %d match: %.5f",cimNsearch++,matchB); snprintf(paneltext,200,"align: %d match: %.5f",cimNsearch++,matchB);
zmainloop(); zmainloop();
if (Fescape > 1) return; // user kill if (Fescape) return; // user kill
} }
cimOffs[im2] = offsetsB; // restore best match cimOffs[im2] = offsetsB; // restore best match
if (cim_manualwarp) continue; // skip auto warp if (cim_manualwarp) continue; // skip auto warp
// warp corners and search for best match // warp corners and search for best match
wrange = cimWarpRange; // corner warp range and step wrange = cimWarpRange; // corner warp range and step
wstep = cimWarpStep; wstep = cimWarpStep;
skipping to change at line 6392 skipping to change at line 6406
match = cim_match_images(im1,im2); // get match level match = cim_match_images(im1,im2); // get match level
if (cim_sigdiff(match,matchB,0.00001) > 0) { if (cim_sigdiff(match,matchB,0.00001) > 0) {
matchB = match; // save best match matchB = match; // save best match
offsetsB = cimOffs[im2]; offsetsB = cimOffs[im2];
} }
snprintf(paneltext,200,"warp: %d match: %.5f",cimNsearch++,matchB); snprintf(paneltext,200,"warp: %d match: %.5f",cimNsearch++,matchB);
zmainloop(); zmainloop();
if (Fescape > 1) return; // user kill if (Fescape) return; // user kill
} }
cimOffs[im2] = offsetsB; // restore best match cimOffs[im2] = offsetsB; // restore best match
if (cimPano) cim_warp_image_pano(im2,1); // apply corner warps if (cimPano) cim_warp_image_pano(im2,1); // apply corner warps
else if (cimPanoV) cim_warp_image_Vpano(im2,1); else if (cimPanoV) cim_warp_image_Vpano(im2,1);
else cim_warp_image(im2); else cim_warp_image(im2);
} }
} }
skipping to change at line 7172 skipping to change at line 7186
} }
PXM_free(E3pxm); // replace input with output PXM PXM_free(E3pxm); // replace input with output PXM
E3pxm = pxmout; E3pxm = pxmout;
return; return;
} }
// dump offsets to stdout - diagnostic tool // dump offsets to stdout - diagnostic tool
void cim_dump_offsets(cchar *label) void cim_dump_offsets(ch *label)
{ {
Plog(1,"\n offsets: %s \n",label); Plog(1,"\n offsets: %s \n",label);
for (int imx = 0; imx < cimNF; imx++) for (int imx = 0; imx < cimNF; imx++)
{ {
Plog(1," imx %d x/y/t: %.1f %.1f %.4f w0: %.1f %.1f w1: %.1f %.1f w2: %.1f %.1f w3: %.1f %.1f \n", Plog(1," imx %d x/y/t: %.1f %.1f %.4f w0: %.1f %.1f w1: %.1f %.1f w2: %.1f %.1f w3: %.1f %.1f \n",
imx, cimOffs[imx].xf, cimOffs[imx].yf, cimOffs[imx].tf, imx, cimOffs[imx].xf, cimOffs[imx].yf, cimOffs[imx].tf,
cimOffs[imx].wx[0], cimOffs[imx].wy[0], cimOffs[imx].wx[1], cimOf fs[imx].wy[1], cimOffs[imx].wx[0], cimOffs[imx].wy[0], cimOffs[imx].wx[1], cimOf fs[imx].wy[1],
cimOffs[imx].wx[2], cimOffs[imx].wy[2], cimOffs[imx].wx[3], cimOf fs[imx].wy[3]); cimOffs[imx].wx[2], cimOffs[imx].wy[2], cimOffs[imx].wx[3], cimOf fs[imx].wy[3]);
} }
 End of changes. 109 change blocks. 
140 lines changed or deleted 155 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)