pro align1img, index, data, xc, yc, nx, ny, ox0, oy0, outres, $
	fast=fast, roll=roll, $
	qcor=qcor, typout=typout, typ_in=typ_in, oy=oy, $
	ref_image=ref_image, override=override, $
	norm_fact=norm_fact, $
	qdebug=qdebug, qstop=qstop
;
;+
;NAME:
;	align1img
;PURPOSE:
;	To align a single image
;INPUT/OUTPUT:
;	index
;	data	- The data will be changed by this routine.
;INPUT:
;	xc	- The X CCD address which should be the lower left corner
;		  of the output image
;	yc	- The Y CCD address which should be the lower left corner
;		  of the output image
;	nx	- The number of x pixels
;	ny	- The number of y pixels
;	outres	- The output resolution
;OPTIONAL KEYWORD INPUT:
;       fast    - If set, then perform the registration in "FAST" mode which
;               is simple full pixel shifts instead of POLY2D.
;	qcor	- Set if corrections were enabled for this data
;	typ_in	- The data type of the input
;	typout	- The data type of the output
;	override- If set, pass to MOD_RES and override the protection against
;		  changing the resolution on a byte type image.
;       norm_fact - If set to 1, then do not normalize the signal level
;                 for the number of pixels binned/spread.
;                 The default is to divide by the number of pixels that
;                 the charge is being spread into.
;                 For example, when going from HR to FR the signal is
;                 from one pixel is spread into 4 pixels.  The default
;                 is to divide the signal by 4.  /NORM_FACTOR will
;                 leave the signal as is.
;                 If set to 2, then normalize by the sqrt(# pixels
;                 the charge is spread into.  For the example above,
;                 divide the signal by 2.  This is used for the handling
;                 the uncertainty arrays.
;OPTIONAL KEYWORD OUTPUT:
;	oy	- 
;HISTORY:
;	Written 16-Aug-93 by M.Morrison (breaking up ALIGN_PFI)
;	16-Sep-93 (MDM) - Added NORM_FACT option for MOD_RES
;	18-Nov-93 (MDM) - Minor mod
;			- Added FIX statement to SXT_SUBIMG3 call
;			  ext_subimg3(index, data, fri=fix([xc,yc]), ...)
;V1.01	19-Nov-93 (MDM) - Corrected logging of ARCSEC_SHIFT.  It was not
;			  logging the arceseconds properly for HR and QR cases
;V1.02  24-Nov-93 (MDM) - Corrected error with OR assembly.  The problem was
;                         with EXT_SUBIMG3.  Added the /TRIM option to the
;			  EXT_SUBIMG3 call
;V2.00	 4-Jan-94 (MDM) - Added ROLL keyword option
;			- Incorporated the shift correction of the optical images to
;                         be aligned with the x-ray images
;V2.01	22-Feb-94 (MDM) - Added FAST option
;V2.02	14-Nov-94 (MDM) - Corrected error which was resulting in no POLY2D sub-pixel
;			  adjustment being performed if "xoffset" or "yoffset" was
;			  zero (conditional used AND instead of OR).  The number
;			  of cases where this would have caused an error is probably
;			  none because of the resolution of the pointing.
;-
;
progverno = 2.020*1000
if (n_elements(qcor) eq 0) then qcor = 1
if (n_elements(typ_in) eq 0) then typ_in = -99
;
if (keyword_set(ref_image)) then begin
    xc = gt_corner(ref_image, /x)
    yc = gt_corner(ref_image, /y)
    nx = gt_shape(ref_image, /x)
    ny = gt_shape(ref_image, /y)
    outres = gt_res(ref_image)
end
;
res0 = gt_res(index)
pixout = 2.^outres	;1,2 or 4
;
f1 = gt_shape(index, /x, /fr) / (nx*pixout)	;ratio of input image size to output image size in FR pixels
f2 = gt_shape(index, /y, /fr) / (ny*pixout)
;
if ((f1 ge 1.8) or (f2 ge 1.8)) then begin		;input image is larger than twice the size of the output
							;so extract a sub-portion first
    if (keyword_set(qdebug)) then print, 'ALIGN1IMG: Extracting a subportion of image: '+fmt_tim(index)
    margin = 1
    factor = 2.^outres / 2.^gt_res(index)         ;pass in HR, outres is FR means 1/2 as many pixels extracted
    data = ext_subimg3(index, data, fri=fix([xc,yc]), nx=nx*factor+margin*2, ny=ny*factor+margin*2, $
				margin=margin, /update_index, /trim, qdebug=qdebug)
    if (keyword_set(qstop)) then stop
end
;
if (res0 ne outres) then begin	;change resolution
    if ((qcor eq 0) and (typ_in eq 1)) then begin
	message, 'WARNING - Changing the resolution (and therefore the signal level) ', /info
	message, '          and /NOCORRECTIONS was set and DATA is BYTE type - should be decompressed?', /info
    end

    if (keyword_set(qdebug)) then print, 'Changing the resolution for image: ' + fmt_tim(index)
    data = mod_res(index, data, outres=outres, /update_index, override=override, norm_fact=norm_fact)
    if (keyword_set(qstop)) then stop
end
;
nx_in = gt_shape(index, /x)
ny_in = gt_shape(index, /y)
;
;----- ix,iy and ox,oy pixel units are in the same resolution below (the output resolution)
;
x00 = gt_corner(index, /x)		;original corner address of PFI
y00 = gt_corner(index, /y)

off = 0
if (keyword_set(fast)) then off=0.5		;MDM added 22-Feb-94
ox0 = fix((x00-xc)/pixout + off)		;pixel location in the output array where the PFI should be inserted 
oy0 = fix((y00-yc)/pixout + off)		;in units of the output resolution
ox1 = ox0 + nx_in-1
oy1 = oy0 + ny_in-1
xoffset = ((x00-xc)/pixout-ox0)			;should be less than 1 pixel
yoffset = ((y00-yc)/pixout-oy0)
if (keyword_set(fast)) then begin		;MDM added 22-Feb-94
    xoffset = 0					;do not do POLY_2D sub-pixel shift
    yoffset = 0
end

;----- perform the sub-pixel shift before "trimming" the image because of the edge pixel effect.

if ((xoffset ne 0) or (yoffset ne 0)) then data = poly_2d(temporary(data), [-xoffset,0,1,0], [-yoffset,1,0,0], 1)

;----- perform the roll adjustment

if (keyword_set(roll)) then begin
    xpiv = -gt_corner(index, /from_sc, /x)		;invert the sign
    ypiv = -gt_corner(index, /from_sc, /y)
    data = rot(data, -roll, 1, xpiv, ypiv, missing=0, /pivot)
end

;----- insert it where it belongs

ix0 = 0		& ix1 = nx_in-1		;pixels to be used from the INPUT image
iy0 = 0		& iy1 = ny_in-1
qtrim = 0
if (ox0 lt 0) then begin 	& ix0 = abs(ox0) 	& ox0 = 0 & qtrim = 1 & end	;input image falls outside on the left
if (oy0 lt 0) then begin 	& iy0 = abs(oy0) 	& oy0 = 0 & qtrim = 1 & end	;input image falls outside on the bottom
if (ox1 ge nx) then begin	& ix1 = (nx_in-1) - (ox1-nx+1)    & qtrim = 1 & end	;input image falls outside on the right
if (oy1 ge ny) then begin	& iy1 = (ny_in-1) - (oy1-ny+1)    & qtrim = 1 & end	;input image falls outside on the top
qtrim = (qtrim or (ix1 gt (nx_in-1)) or (iy1 gt (ny_in-1)))	;added 25-Aug-93
ix1 = ix1 < (nx_in-1)
iy1 = iy1 < (ny_in-1)

oy = [oy0, oy1]		;MDM 12-Aug-93

if (keyword_set(qdebug)) then print, 'ix0,ix1,iy0,iy1', ix0,ix1,iy0,iy1
if (keyword_set(qdebug)) then print, 'ox0,ox1,oy0,oy1', ox0,ox1,oy0,oy1
if (keyword_set(qdebug)) then print, 'xoffset,yoffset', xoffset, yoffset

if ((iy0 ge ny_in) or (ix0 ge nx_in) or (ix1 lt 0) or (iy1 lt 0)) then begin
    print, 'Image ', fmt_tim(index), ' falls outside of the declared window'
    data = 0
end else begin
    if (qtrim eq 1) then data = data(ix0:ix1, iy0:iy1)
end

his_index, index, 0, 'q_registered', progverno
his_index, index, 0, 'arcsec_shift', [-xoffset, -yoffset]*gt_pix_size()*pixout		;MDM added *pixout 19-Nov-93
his_index, index, 0, 'corner_sav', [xc, yc]
index.sxt.shape_sav = [nx, ny]
;
if (keyword_set(roll)) then his_index, index, 0, 'q_roll_corr', progverno	;MDM added 4-Jan-94
;
if (keyword_set(qstop)) then stop
return
end
