Files
FireBee_Setup/tools/vision/LDV/SRC/bhole/bhole.c
2022-11-14 10:05:42 +01:00

853 lines
29 KiB
C

/*
*
*
* Version PureC / Gcc
*/
#define PCGEMLIB 1 /* mettre 1 si les utilisateurs de Pure C
* utilise les librairies GEM Pure C */
/* Fichiers headers */
#include <stdio.h> /* Forget this and sprintf will badly format numbers */
#include <portab.h>
#if PCGEMLIB
#include <aes.h>
#include <vdi.h>
#else
#include <aesbind.h>
#include <vdibind.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "..\..\ldg.h"
#include "..\..\vapi.h"
#include "..\..\ldv.h"
#include "..\..\mt_aes.h"
/* Prototypages */
LDV_INFOS * cdecl GetLDVCapabilities(VAPI *vapi) ;
LDV_STATUS cdecl PreRun(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ;
LDV_STATUS cdecl Run(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ;
LDV_STATUS cdecl Preview(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out) ;
void OnClose(void) ;
/* Variables globales */
PROC Proc[] = {
"GetLDVCapabilities", "LDV Capabilities", (void *)GetLDVCapabilities,
"PreRun", "Run Initiliaze", (void *)PreRun,
"Run", "LDV Feature", (void *)Run,
"Preview", "Preview", (void *)Preview,
} ;
char Info[] = "LDV";
LDGLIB Ldg[] = {
0x0100, /* LDV version */
4, /* Number of functions in the lib */
Proc, /* Pointers to LDV functions */
Info, /* Library Information */
0x0, /* Lib flags, mandatory */
OnClose, /* Closing, free VDIHandle */
};
#define BP_CAPS (LDVF_ATARIFORMAT | LDVF_SUPPORTPREVIEW | LDVF_SUPPORTPROG | LDVF_REALTIMEPARAMS | LDVF_SUPPORTCANCEL | LDVF_NOSELECTION)
#define TC_CAPS (LDVF_SPECFORMAT | LDVF_SUPPORTPREVIEW | LDVF_SUPPORTPROG | LDVF_REALTIMEPARAMS | LDVF_SUPPORTCANCEL | LDVF_NOSELECTION)
LDV_INFOS LdvInfos = {
(short) sizeof(LDV_INFOS), /* Size of this structure */
TLDV_MODIFYIMG, /* LDV Type */
"Jean Lusetti", /* Authors */
{
{ 1, 1, BP_CAPS }, /* 1 bit-plane capabilities */
{ 2, 2, BP_CAPS }, /* 2 bit-plane capabilities */
{ 4, 4, BP_CAPS }, /* 4 bit-plane capabilities */
{ 8, 8, BP_CAPS }, /* 8 bit-plane capabilities */
{ 16, 16, TC_CAPS }, /* 16 bit-plane capabilities */
{ 32, 32, TC_CAPS }, /* 32 bit-plane capabilities */
{ 0, 0, 0UL } /* End of capabilities list */
},
} ;
VAPI *Vapi = NULL ;
#define ITRIGO_ARRAY_NBITS 14
#define ITRIGO_ARRAY_SIZE (1 << ITRIGO_ARRAY_NBITS)
#define ITRIGO_ANGLE_MAX (ITRIGO_ARRAY_SIZE-1)
#define QUARTER (ITRIGO_ARRAY_SIZE/4)
#define ANGLE_ADD (M_PI/2.0/(double)QUARTER) ;
long* pre_cosin = NULL ; /* Array of pre-computed cosinus/sinus values */
long* pre_loffset = NULL ; /* To hold pre-computation of line offsets */
int lo_w=0, lo_h=0, lo_nplanes=0 ; /* Current parameters for line offset */
unsigned long VapiLogLevel = LL_DISABLED ;
unsigned long ProcMask = 0L ;
short UseSym = -1 ; /* By default use symmetry to save CPU calculations */
/* On Aranym, this is usually slower, so there is a */
/* Setting in bhole.ini to force no symetry usage */
/* Macro to access pre-computed cosinus/sinus array */
/* Sinus is right after cosinus value */
#define COS(i) (pre_cosin[(i)<<1])
#define SIN(i) (pre_cosin[1 + ( (i)<<1 )])
/* Back Hole computation parameters are not passed to speed up calculations, */
/* They are global to the module */
/* Black Hole symmetry rotation */
typedef struct _RECT
{
short x ;
short y ;
short w ;
short h ;
}
RECT, *PRECT ;
typedef struct _BH_SPROPERTIES
{
short estdpc ; /* Estimated duration in % (100 being the one without using symmetry) */
short nrect ;
short nsym ;
RECT rect[9] ;
}
BH_SPROPERTIES, *PBH_SPROPERTIES ;
extern long bh_xd, bh_yd, bh_rd2, bh_xs, bh_ys, bh_ref ;
extern long bh_xc, bh_yc ;
extern short bh_out_w, bh_out_h, bh_in_w, bh_in_h ;
extern short bh_out_x, bh_out_y ;
short bh_pc, bh_nrect ;
/* This is the routine address that will operate on a line basis */
static void (*BHLRoutine)(short use_sym, void* in, void* out) ;
/* Specific 68030 and FPU routines */
/* In BHOLE.S */
extern void BHL32_68030(short use_sym, void* in, void* out) ;
extern void BHL16_68030(short use_sym, void* in, void* out) ;
extern void BHLInd_68030(short use_sym, void* in, void* out) ;
extern void BHL32_F68030(short use_sym, void* in, void* out) ;
extern void BHL16_F68030(short use_sym, void* in, void* out) ;
extern void BHLInd_F68030(short use_sym, void* in, void* out) ;
extern void lcosin_fpu(long i, long* pcs) ;
/* GET/SET pixel macros for True Color 16 and 32bit */
#define SET_TCPIXEL(p,x,y,val) (p[pre_loffset[y]+x]=val)
#define GET_TCPIXEL(p,x,y) (p[pre_loffset[y]+x])
/* Rotation by 90° macro */
#define R90(x,y) { long _x=x; x=-y; y=_x; }
/* Macro to initialize calculations for a line */
#define BH_INIT_LINE\
bh_xd = bh_out_x-bh_xc ;\
bh_rd2 = (bh_xd*bh_xd + bh_yd*bh_yd) ;\
/* This is the routine that computes the resulting pixel (bh_xs,bh_ys) in source image */
/* From the pixel (bh_xd, bh_yd) in destination image */
/* (bh_xc,bh_yc) is the center pixel of the back hole */
/* This routine also returns if the resulting pixel is in the source image */
int rBH_68000(void)
{
int not_in_range = 1 ;
long alpha ;
bh_rd2 += ( bh_xd << 1 ) + 1 ;
alpha = bh_ref / (1+bh_rd2) ;
alpha &= ITRIGO_ANGLE_MAX ;
bh_xs = bh_xd * COS(alpha) - bh_yd * SIN(alpha) ;
bh_xs >>= 16 ;
if ( (bh_xs >= -bh_xc) && (bh_xs < -bh_xc+bh_in_w) )
{
bh_ys = bh_xd * SIN(alpha) + bh_yd * COS(alpha) ;
bh_ys >>= 16 ;
if ( (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h) )
not_in_range = 0 ;
}
return not_in_range ;
}
/* For 68000/bit-planes organization: */
/* This routine returns the value of the pixel index in the source image */
/* Assuming (bh_xs,bh_ys) is within the source image */
#pragma warn -par
void BHLInd_68000(short use_sym, void* in, void* out)
{
unsigned char* in_ptr = (unsigned char*) in ;
unsigned char* out_ptr = (unsigned char*) out ;
short x ;
for ( x = bh_out_x; x < bh_out_w; x++, bh_xd++ )
{
if ( rBH_68000() == 0 )
out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ;
else
out_ptr[x] = 0 ;
}
}
#pragma warn +par
/* For 68000/16bit TrueColor organization: */
/* This routine returns the value of the pixel index in the source image */
/* Assuming (bh_xs,bh_ys) is within the source image */
void BHL16_68000(short use_sym, void* in, void* out)
{
unsigned int* in_ptr = (unsigned int*) in ;
unsigned int* out_ptr = (unsigned int*) out ;
short x ;
if (use_sym)
{
unsigned long save_bh_xd, save_bh_yd ;
short n ;
for ( x = bh_out_x; x <= bh_out_x+bh_out_w/2; x++, bh_xd++ )
{
/* Save bh_xd and bh_yd as they will change */
save_bh_xd = bh_xd ;
save_bh_yd = bh_yd ;
if ( rBH_68000() == 0 ) /* Compute 1st pixel with Black Hole formula */
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ;
else
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFF) ;
/* Deduce 2nd, 3rd and 4th pixel */
for (n=0; n < 3; n++)
{
R90(bh_xd, bh_yd) ;
R90(bh_xs, bh_ys) ;
if ( (bh_xd>=-bh_xc) && (bh_xd < -bh_xc+bh_in_w) && (bh_yd >= -bh_yc) && (bh_yd < -bh_yc+bh_in_h))
{
if ( (bh_xs>=-bh_xc) && (bh_xs < -bh_xc+bh_in_w) && (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h))
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ;
else
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFF) ;
}
}
/* Restore bh_xd and bh_yd */
bh_xd = save_bh_xd ;
bh_yd = save_bh_yd ;
}
}
else
{
for ( x = bh_out_x; x < bh_out_x+bh_out_w; x++, bh_xd++ )
{
if ( rBH_68000() == 0 )
out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ;
else
out_ptr[x] = 0xFFFF ;
}
}
}
/* For 68000/32bit TrueColor organization: */
/* This routine returns the value of the pixel index in the source image */
/* Assuming (bh_xs,bh_ys) is within the source image */
void BHL32_68000(short use_sym, void* in, void* out)
{
unsigned long* in_ptr = (unsigned long*) in ;
unsigned long* out_ptr = (unsigned long*) out ;
short x ;
if (use_sym)
{
unsigned long save_bh_xd, save_bh_yd ;
short n ;
for ( x = bh_out_x; x <= bh_out_x+bh_out_w/2; x++, bh_xd++ )
{
/* Save bh_xd and bh_yd as they will change */
save_bh_xd = bh_xd ;
save_bh_yd = bh_yd ;
if ( rBH_68000() == 0 ) /* Compute 1st pixel with Black Hole formula */
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ;
else
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFFFFFFL) ;
/* Deduce 2nd, 3rd and 4th pixel */
for (n=0; n < 3; n++)
{
R90(bh_xd, bh_yd) ;
R90(bh_xs, bh_ys) ;
if ( (bh_xd>=-bh_xc) && (bh_xd < -bh_xc+bh_in_w) && (bh_yd >= -bh_yc) && (bh_yd < -bh_yc+bh_in_h))
{
if ( (bh_xs>=-bh_xc) && (bh_xs < -bh_xc+bh_in_w) && (bh_ys >= -bh_yc) && (bh_ys < -bh_yc+bh_in_h))
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, GET_TCPIXEL(in_ptr, bh_xs+bh_xc, bh_ys+bh_yc)) ;
else
SET_TCPIXEL(out_ptr, bh_xd+bh_xc, bh_yd+bh_yc, 0xFFFFFFFFL) ;
}
}
/* Restore bh_xd and bh_yd */
bh_xd = save_bh_xd ;
bh_yd = save_bh_yd ;
}
}
else
{
for ( x = bh_out_x; x < bh_out_x+bh_out_w; x++, bh_xd++ )
{
if ( rBH_68000() == 0 )
out_ptr[x] = in_ptr[pre_loffset[bh_ys+bh_yc] + bh_xs+bh_xc] ;
else
out_ptr[x] = 0xFFFFFFFFL ;
}
}
}
void lcosin(long i, long* pcs)
{
double angle = i*ANGLE_ADD ;
pcs[0] = (long) (65536.0 * cos(angle)) ;
pcs[1] = (long) (65536.0 * sin(angle)) ;
}
int InitTrigo(int fpu)
{
void (*rlcosin)(long i, long* pcs) ;
long cs[2] ;
long q, i;
clock_t t0 ;
/* if ( pre_cosin[0] == 65536L ) return 0 ; Used to detect init done before dynamic allocation design */
if ( pre_cosin ) return 0 ;
pre_cosin = (long*) calloc( ITRIGO_ARRAY_SIZE, 2*sizeof(long) ) ;
if ( pre_cosin == NULL ) return -1 ;
t0 = clock() ;
if (fpu) rlcosin = lcosin_fpu ;
else rlcosin = lcosin ;
for ( i = 0; i < QUARTER; i++ )
{
rlcosin( i, cs ) ;
COS(i) = cs[0] ;
SIN(i) = cs[1] ;
q = QUARTER ;
/* Set [PI/2;PI] */
COS(q+i) = -SIN(i) ;
SIN(q+i) = COS(i) ;
q += QUARTER ;
/* Set [PI;3*PI/2] */
COS(q+i) = -COS(i) ;
SIN(q+i) = -SIN(i) ;
q += QUARTER ;
/* Set [3*PI/2; 2*PI] */
COS(q+i) = COS(i) ;
SIN(q+i) = -SIN(i) ;
}
if (Vapi && Vapi->LoDoLog)
Vapi->LoDoLog(LL_INFO, "IniTrigo%s done in %ldms", fpu ? "(FPU)":"", 1000L * (clock()-t0)/CLK_TCK) ;
return 0 ;
}
/* Called when LDV is loaded, take this opportunity to get some */
/* Info about system: VAPI version and CPU/FPU availability */
LDV_INFOS * cdecl GetLDVCapabilities(VAPI *vapi)
{
Vapi = vapi ;
VapiLogLevel = LL_DISABLED ;
if ( Vapi && (Vapi->Header.Version >= 0x0104) && Vapi->LoDoLog && Vapi->LoGetLogLevel )
{
VapiLogLevel = Vapi->LoGetLogLevel() ;
if (Vapi->CoGetProcessors)
ProcMask = Vapi->CoGetProcessors() ;
if (ProcMask & CO_HAS_030)
Vapi->LoDoLog(LL_INFO, "%s", "68030 processor available") ;
if (ProcMask & CO_HAS_FPU)
Vapi->LoDoLog(LL_INFO, "%s", "Floating Point unit available") ;
}
return( &LdvInfos ) ;
}
/* Free allocated RunTime stuff */
void OnClose(void)
{
if ( pre_cosin ) free( pre_cosin ) ;
pre_cosin = NULL ;
if ( pre_loffset ) free( pre_loffset ) ;
pre_loffset = NULL ;
}
/* Pre-compute line offsets from source to speed-up computations */
int compute_loffset(MFDB* in, long** ppre_lo, int* plo_w, int* plo_h, int* plo_nplanes)
{
/* Sanity checks */
if ( (ppre_lo == NULL) || (plo_w == NULL) || (plo_h == NULL) || (plo_nplanes == NULL) )
return -2 ;
if ( *ppre_lo && (*plo_w == in->fd_w) && (*plo_h == in->fd_h) && (*plo_nplanes == in->fd_nplanes) )
{
/* Current line offsets are still valid */
return 0 ;
}
else
{
/* Need to compute line offsets */
*plo_w = *plo_h = *plo_nplanes = 0 ;
if (*ppre_lo) free(*ppre_lo) ;
*ppre_lo = (long*) malloc(sizeof(long) * (long)in->fd_h) ;
if (*ppre_lo)
{
long* pt_off ;
long add = (long) ALIGN16( in->fd_w ) ;
long offset = 0L ;
int y ;
pt_off = *ppre_lo ;
for ( y = 0; y < in->fd_h; y++ )
{
*pt_off++ = offset ;
offset += add ;
}
*plo_w = in->fd_w ;
*plo_h = in->fd_h ;
*plo_nplanes = in->fd_nplanes ;
return 0 ;
}
}
return -1 ;
}
#pragma warn -par
/* Just say that output image has same width/length than source */
LDV_STATUS cdecl PreRun(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out)
{
out->Raster.fd_w = in->Raster.fd_w ;
out->Raster.fd_h = in->Raster.fd_h ;
return( ELDV_NOERROR ) ;
}
#pragma warn +par
/* Update progression window 1 time on 16 */
char check_prog(short y, short ymax)
{
char cancel = 0 ;
if ( ( y & 0x0F ) == 0 )
{
int pc = (short) ( ( 100L * (long)y ) / (long)ymax ) ;
cancel = Vapi->PrSetProgEx( bh_pc+pc/bh_nrect ) ;
}
return cancel ;
}
/* Initialize global variables for calculation */
void init_computation(short xc, short yc, long angle, MFDB* in, RECT* rect)
{
long maxrd2 ;
bh_xd = -xc ;
bh_yd = -yc ;
maxrd2 = bh_xd*bh_xd + bh_yd*bh_yd ;
if ( (ProcMask & (CO_HAS_030|CO_HAS_FPU)) == (CO_HAS_030|CO_HAS_FPU) )
maxrd2 = (long) sqrt(maxrd2) ;
bh_ref = (angle * maxrd2) ;
bh_xc = xc ;
bh_yc = yc ;
bh_in_w = in->fd_w ;
bh_in_h = in->fd_h ;
bh_out_x = rect->x ;
bh_out_y = rect->y ;
bh_out_w = rect->w ;
bh_out_h = rect->h ;
bh_yd = bh_out_y-bh_yc ;
}
/* 68000 routine for bit-plane images */
LDV_STATUS bpRun(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym)
{
MFDB dst_line ;
LDV_STATUS status = ELDV_NOERROR ;
size_t size_indexes, size_dst_line ;
short y ;
long wout, sizelout ;
unsigned char *index_in, *index_out, *out_ptr ;
char cancel = 0 ;
/* We will convert the whole image in indexes */
/* Allocate memory to convert then to bitplanes */
/* A line to destination tion */
size_indexes = (long) ALIGN16( in->fd_w ) ;
size_indexes *= (long) in->fd_h ;
size_dst_line = (long) ALIGN16( out->fd_w ) ;
index_in = (unsigned char *) malloc( size_indexes ) ;
if ( index_in == NULL ) return ELDV_NOTENOUGHMEMORY ;
index_out = (unsigned char *) malloc(size_dst_line) ;
if ( index_out == NULL )
{
free(index_in) ;
return ELDV_NOTENOUGHMEMORY ;
}
/* Convert all source to indexes */
Vapi->RaRaster2Ind( in->fd_addr, size_indexes, (long)in->fd_nplanes, index_in ) ;
memcpy( &dst_line, out, sizeof(MFDB) ) ;
dst_line.fd_wdwidth = out->fd_w / 16 ;
if ( out->fd_w % 16 ) dst_line.fd_wdwidth++ ;
dst_line.fd_h = 1 ;
wout = (long) ALIGN16( out->fd_w ) ;
out_ptr = out->fd_addr ;
sizelout = Vapi->RaGetImgSize( (long) dst_line.fd_w, (long) dst_line.fd_h, (long) out->fd_nplanes ) ;
init_computation(xc, yc, angle, in, rect) ;
for ( y = 0; !cancel && (y < out->fd_h); y++, bh_yd++, out_ptr += sizelout )
{
BH_INIT_LINE ;
BHLRoutine(use_sym, index_in, index_out) ;
dst_line.fd_addr = out_ptr ;
Vapi->RaInd2RasterInit( &dst_line, wout ) ;
Vapi->RaInd2Raster( index_out, wout ) ;
cancel = check_prog(y, out->fd_h) ;
}
free(index_in) ;
free(index_out) ;
if ( cancel ) status = ELDV_CANCELLED ;
return( status ) ;
}
/* 68000 routine for 16bit True Color images */
LDV_STATUS Run16(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym)
{
LDV_STATUS status = ELDV_NOERROR ;
unsigned int *in_ptr, *out_ptr ;
unsigned long sizelout = 0 ;
short y, hy ;
char cancel = 0 ;
in_ptr = (unsigned int*) in->fd_addr ;
out_ptr = (unsigned int*) out->fd_addr ;
init_computation(xc, yc, angle, in, rect) ;
hy = bh_out_y+bh_out_h/2 ;
if (!use_sym)
{
sizelout = (long) ALIGN16( out->fd_w ) ;
out_ptr += sizelout*(long)rect->y ;
hy = bh_out_y+bh_out_h ;
}
for ( y = bh_out_y; !cancel && (y < hy); y++, bh_yd++, out_ptr += sizelout )
{
BH_INIT_LINE ;
BHLRoutine(use_sym, in_ptr, out_ptr) ;
cancel = check_prog(y, hy-bh_out_y) ;
}
if ( cancel ) status = ELDV_CANCELLED ;
return( status ) ;
}
/* 68000 routine for 32bit True Color images */
LDV_STATUS Run32(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym)
{
LDV_STATUS status = ELDV_NOERROR ;
unsigned long *in_ptr, *out_ptr ;
unsigned long sizelout = 0 ;
short y, hy ;
char cancel = 0 ;
in_ptr = (unsigned long*) in->fd_addr ;
out_ptr = (unsigned long*) out->fd_addr ;
init_computation(xc, yc, angle, in, rect) ;
hy = bh_out_y+bh_out_h/2 ;
if (!use_sym)
{
sizelout = (long) ALIGN16( out->fd_w ) ;
out_ptr += sizelout*(long)rect->y ;
hy = bh_out_y+bh_out_h ;
}
for ( y = bh_out_y; !cancel && (y < hy); y++, bh_yd++, out_ptr += sizelout )
{
BH_INIT_LINE ;
BHLRoutine(use_sym, in_ptr, out_ptr) ;
cancel = check_prog(y, hy-bh_out_y) ;
}
if ( cancel ) status = ELDV_CANCELLED ;
return( status ) ;
}
int MayAddRect(RECT* subRect, BH_SPROPERTIES* sgProps)
{
int add = (subRect->w && subRect->h) ;
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"MayAddRect (%d,%d,%d,%d)", subRect->x, subRect->y, subRect->w, subRect->h);
if ( add ) /* Sub Rectangle not empty */
memcpy( &sgProps->rect[sgProps->nrect++], subRect, sizeof(RECT) ) ;
return( add ) ;
}
/* Estimation of the expected gain by using rotation symmetry */
void SymmetrySplit(MFDB* img, short xc, short yc, BH_SPROPERTIES* sgProps)
{
long npts_insym, npts_total, npts_to_compute ;
short sw = 0 ;
if ( UseSym && ( (img->fd_nplanes == 16) || (img->fd_nplanes == 32) ) )
{
/* Bitplane organization would have make things too complicated */
/* By the way, who is using bitplanes nowadays ? */
sw = xc ;
if ( img->fd_w-xc < sw ) sw = img->fd_w-xc ;
if ( yc < sw ) sw = yc ;
if ( img->fd_h-yc < sw ) sw = img->fd_h-yc ;
if ( img->fd_h-yc < sw ) sw = img->fd_h-yc ;
/* Let's build the rectangle arrays to define the image */
/* First rectangle (square actually) is the one to use for symmetry */
/* On this one only 25% of pixels will be computed with Black Hole formula */
sgProps->nrect = 1 ;
sgProps->nsym = 0 ;
sgProps->rect[0].x = xc-sw ;
sgProps->rect[0].y = yc-sw ;
sgProps->rect[0].w = 2*sw ;
sgProps->rect[0].h = 2*sw ;
}
npts_total = (long)img->fd_w*(long)img->fd_h ;
npts_insym = 4L*(long)sw*(long)sw ;
npts_to_compute = npts_total-((3L*npts_insym)/4L) ;
sgProps->estdpc = (100L*npts_to_compute)/npts_total ;
if ( sgProps->estdpc > 70 )
{
/* Not worth make things complicated for that gain */
sgProps->nrect = 1 ;
sgProps->nsym = -1 ;
sgProps->rect[0].x = 0 ;
sgProps->rect[0].y = 0 ;
sgProps->rect[0].w = img->fd_w ;
sgProps->rect[0].h = img->fd_h ;
}
else
{
/* Let's build the remaining rectangles */
RECT* sRect = &sgProps->rect[0] ; /* Symmetry Rectangle */
RECT subRect ;
/*
|----------------------------------------|
| R1 | R2 | R3 |
|----------------------------------------|
| ****** |
| R4 ****** R5 |
| ****** |
| ****** |
|----------------------------------------|
| R6 | R7 | R8 |
|----------------------------------------|
*/
/* R1 */
subRect.x = 0 ; subRect.y = 0 ;
subRect.w = sRect->x ; subRect.h = sRect->y ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R1(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R2 */
subRect.x = sRect->x ; subRect.y = 0 ;
subRect.w = sRect->w ; subRect.h = sRect->y ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R2(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R3 */
subRect.x = sRect->x+sRect->w ; subRect.y = 0 ;
subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = sRect->y ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R3(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R4 */
subRect.x = 0 ; subRect.y = sRect->y ;
subRect.w = sRect->x ; subRect.h = sRect->h ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R4(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R5 */
subRect.x = sRect->x+sRect->w ; subRect.y = sRect->y ;
subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = sRect->h ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R5(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R6 */
subRect.x = 0 ; subRect.y = sRect->y+sRect->h ;
subRect.w = sRect->x ; subRect.h = img->fd_h-sRect->y-sRect->h ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R6(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R7 */
subRect.x = sRect->x ; subRect.y = sRect->y+sRect->h ;
subRect.w = sRect->w ; subRect.h = img->fd_h-sRect->y-sRect->h ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R7(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
/* R8 */
subRect.x = sRect->x+sRect->w ; subRect.y = sRect->y+sRect->h ;
subRect.w = img->fd_w-sRect->x-sRect->w ; subRect.h = img->fd_h-sRect->y-sRect->h ;
if (MayAddRect( &subRect, sgProps ))
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG,"Adding R8(%d,%d,%d,%d)", subRect.x, subRect.y, subRect.w, subRect.h);
}
}
short GetSymetryUsageFromIni(void)
{
short use_sym = 1 ; /* Unless INI file say no, assume symetry usage */
long found = 0 ;
char *path_ldv, *language ;
char val_key[64] ;
path_ldv = Vapi->CoGetLDVPath() ;
language = Vapi->CoGetCurrentLanguage() ;
if ( path_ldv && language && Vapi->InGetKeyFromFile )
{
char filename[256] ;
sprintf( filename, "%s\\%s\\BHOLE.INI", path_ldv, language ) ;
if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Looking into %s to see symetry usage...", filename) ;
found = Vapi->InGetKeyFromFile( filename, "Private", "UseSym", val_key ) ;
if ( !found )
{
sprintf( filename, "%s\\BHOLE.INI", path_ldv ) ;
if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Looking into non language specific %s to see symetry usage...", filename) ;
found = Vapi->InGetKeyFromFile( filename, "Private", "UseSym", val_key ) ;
}
}
else if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_WARNING,"Can't access LDV (%s) or language path (%s)!", path_ldv, language) ;
if ( found ) use_sym = atoi( val_key ) ;
if ( Vapi->LoDoLog ) Vapi->LoDoLog(LL_INFO,"Symetry usage: %d (found=%ld)", use_sym, found) ;
return use_sym ;
}
/* LDV Run routine */
LDV_STATUS cdecl Run(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out)
{
BH_SPROPERTIES sgProps ;
LDV_STATUS (*RunRoutine)(MFDB *in, long angle, short xc, short yc, MFDB *out, RECT* rect, short use_sym) ;
LDV_STATUS status = ELDV_NOERROR ;
long angle, np=0 ;
short xc, yc, n ;
if ( Vapi->Header.Version < 0x102 ) return ELDV_BADVAPIVERSION ;
if ( InitTrigo((ProcMask & CO_HAS_FPU) == CO_HAS_FPU) != 0 ) return ELDV_NOTENOUGHMEMORY ;
if ( compute_loffset(&in->Raster, &pre_loffset, &lo_w, &lo_h, &lo_nplanes) ) return ELDV_NOTENOUGHMEMORY ;
if ( UseSym == -1 ) UseSym = GetSymetryUsageFromIni() ;
if ( in->Raster.fd_nplanes <= 8 ) { BHLRoutine = BHLInd_68000 ; RunRoutine = bpRun ; }
else if ( in->Raster.fd_nplanes == 16 ) { BHLRoutine = BHL16_68000 ; RunRoutine = Run16 ; }
else if ( in->Raster.fd_nplanes == 32 ) { BHLRoutine = BHL32_68000 ; RunRoutine = Run32 ; }
else return ELDV_IMGFORMATMISMATCH ;
if (ProcMask & CO_HAS_030)
{
if (ProcMask & CO_HAS_FPU)
{
/* Note that FPU requires also a 68030 here */
/* To avoid having another set of macros in bhole.s */
/* And convert even 68000 routines to ASM */
/* FPU won't speed-up computations; it will just */
/* Make the angle proportional to the distance to */
/* Black Hole Center instead of its square */
Vapi->PrOptimize(0x05) ;
if ( in->Raster.fd_nplanes <= 8 ) BHLRoutine = BHLInd_F68030 ;
else if ( in->Raster.fd_nplanes == 16 ) BHLRoutine = BHL16_F68030 ;
else if ( in->Raster.fd_nplanes == 32 ) BHLRoutine = BHL32_F68030 ;
}
else
{
/* CPU 030 'only', note that it is about 2 times faster than 68000 */
/* Routine mostly because of 32x32x-->32 MULS.L instruction */
Vapi->PrOptimize(0x01) ;
if ( in->Raster.fd_nplanes <= 8 ) BHLRoutine = BHLInd_68030 ;
else if ( in->Raster.fd_nplanes == 16 ) BHLRoutine = BHL16_68030 ;
else if ( in->Raster.fd_nplanes == 32 ) BHLRoutine = BHL32_68030 ;
}
}
angle = (long) params->Param[0].s ;
xc = ((long)params->Param[1].s * (long)in->Raster.fd_w)/100L ;
yc = ((long)params->Param[2].s * (long)in->Raster.fd_h)/100L ;
SymmetrySplit(&in->Raster, xc, yc, &sgProps) ;
if (Vapi->LoDoLog)
{
Vapi->LoDoLog(LL_DEBUG, "100 being the time without using symmetry, using symmetry would be %d", sgProps.estdpc) ;
Vapi->LoDoLog(LL_DEBUG, "Image source : (0,0,+%d,+%d); %ld pixels", in->Raster.fd_w, in->Raster.fd_h, (long)in->Raster.fd_w * (long)in->Raster.fd_h) ;
Vapi->LoDoLog(LL_DEBUG, "Symmetry zone : (%d,%d,+%d,+%d), index:%d", sgProps.rect[0].x, sgProps.rect[0].y, sgProps.rect[0].w, sgProps.rect[0].h, sgProps.nsym) ;
}
bh_nrect = sgProps.nrect ;
for ( n=0; (status != ELDV_CANCELLED) && (n < sgProps.nrect); n++)
{
long npix ;
bh_pc = (100*n)/sgProps.nrect ; /* For progression indicator as we may have multiple loops */
npix = (long)sgProps.rect[n].w * (long)sgProps.rect[n].h ;
np += npix ;
if ( VapiLogLevel >= LL_PERF)
{
size_t t0, tms ;
t0 = clock() ;
status = RunRoutine( &in->Raster, angle, xc, yc, &out->Raster, &sgProps.rect[n], (sgProps.nsym == n) ) ;
tms = (1000L * (clock() - t0) ) / CLK_TCK ;
if (tms == 0 ) tms = 1 ;
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_PERF, "Run zone %d: (%d,%d,+%d,+%d), use_sym=%d, %ld pixels, done in %ldms, %ld Kpixels/s",
n, sgProps.rect[n].x, sgProps.rect[n].y, sgProps.rect[n].w, sgProps.rect[n].h, (sgProps.nsym == n), (long)sgProps.rect[n].w * (long)sgProps.rect[n].h, tms, npix/tms) ;
}
else
status = RunRoutine( &in->Raster, angle, xc, yc, &out->Raster, &sgProps.rect[n], (sgProps.nsym == n) ) ;
}
if (Vapi->LoDoLog)
Vapi->LoDoLog(LL_DEBUG, "%ld pixels computed or deduced", np) ;
return( status ) ;
}
LDV_STATUS cdecl Preview(LDV_IMAGE *in, LDV_PARAMS *params, LDV_IMAGE *out)
{
return( Run( in, params, out ) ) ;
}
int main(void)
{
ldg_init( Ldg ) ;
return( 0 ) ;
}