[futurebasic] vImage Deconvolve change? (FB example)

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : September 2012 : Group Archive : Group : All Groups

From: Robert Covington <artlythere@...>
Date: Mon, 17 Sep 2012 08:56:45 -0400
I use RP's demo to sharpen blurred images, works great. In 10.6.8 at least. In 10.8.1 (not sure about 10.7), the left 1/4 of the image is incorrectly scanned.

Wondering what the issue is…be it a var type change, or GWorld issue, or other?  

What is uint8_t?

("t"  part)
 
Thus far, I cannot find any information where this has changed as to 10.8. etc

rc

/*
Image deblurring by deconvolution.
We convolve an image with a known kernel, then deconvolve it.

Deconvolution is used in astronomy to remove known aberrations of a telescope.

For a black & white image, vImageRichardsonLucyDeConvolve_ARGB8888() does 4x as much work as needed.
It would be more efficient to extract a Planar8 image and use vImageRichardsonLucyDeConvolve_Planar8().
rp 20090604
*/



include library "Accelerate/Accelerate.h>

#if ndef _DEFINEDINCARBON

// vImage_Types.h
#define vImagePixelCount as UInt32
#define vImage_Error     as SInt32
#define vImage_Flags     as UInt32
#define Pixel_8888       as ^UInt8 // typedef uint8_t  Pixel_8888[4];

begin record vImage_Buffer
dim as ptr              data /* Pointer to the top left pixel of the buffer. */
dim as vImagePixelCount height /* The height (in pixels) of the buffer  */
dim as vImagePixelCount width /* The width (in pixels) of the buffer   */
dim as UInt32           rowBytes /* The number of bytes in a pixel row  */
end record

#endif /* _DEFINEDINCARBON */

// Convolution.h
toolbox fn vImageConvolve_ARGB8888( const vImage_Buffer *src, const vImage_Buffer *dest,¬
 ptr tempBuffer, vImagePixelCount srcOffsetToROI_X, vImagePixelCount srcOffsetToROI_Y,¬
 ptr kernel, UInt32 kernel_height, UInt32 kernel_width, UInt32 divisor,¬
 Pixel_8888 backgroundColor, vImage_Flags flags ) = vImage_Error

toolbox fn vImageRichardsonLucyDeConvolve_ARGB8888( const vImage_Buffer *src,¬
const vImage_Buffer *dest,¬
ptr tempBuffer,¬
vImagePixelCount srcOffsetToROI_X,¬
vImagePixelCount srcOffsetToROI_Y,¬
ptr kernel,¬
ptr kernel2,¬
UInt32 kernel_height,¬
UInt32 kernel_width,¬
UInt32 kernel_height2,¬
UInt32 kernel_width2,¬
SInt32 divisor,¬
SInt32 divisor2,¬
Pixel_8888 backgroundColor, ¬
UInt32 iterationCount,¬
vImage_Flags flags ) = vImage_Error //  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;

_kvImageNoFlags                = 0
_kvImageLeaveAlphaUnchanged    = 1 /* Operate on red, green and blue channels only. Alpha is copied from source to destination. For Interleaved formats only. */
_kvImageCopyInPlace            = 2 /* Copy edge pixels. Convolution Only. */
_kvImageBackgroundColorFill    = 4/* Use the background color for missing pixels. */
_kvImageEdgeExtend             = 8 /* Extend border data elements. */
_kvImageDoNotTile              = 16 /* Pass to turn off internal tiling. Use this if you want to do your own tiling, or to use the Min/Max filters in place. */
_kvImageHighQualityResampling  = 32 /* Use a higher quality, slower resampling filter for Geometry operations (shear, scale, rotate, affine transform, etc.) */
_kvImageTruncateKernel         = 64 /* Use only the part of the kernel that overlaps the image. For integer kernels, real_divisor = divisor * (sum of used kernel elements) / (sum of kernel elements). */
/* This should preserve image brightness at the edges. Convolution only. AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER */
_kvImageGetTempBufferSize      = 128 /* The function will return the number of bytes required for the temp buffer. If this value is negative, it is an error, per standard usage.  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER */

local mode
local fn ConvolveKernel( srcGW as CGrafPtr, destGW as CGrafPtr, kernel as ^SInt16, kernel_ht as UInt32, kernel_wdth as UInt32, divisor as SInt32, bkgrnd as ^UInt8, flags as vImage_Flags )
'~'1
dim as vImage_Buffer srcBuf, destBuf
dim as ^^PixMap      pmHandle 

pmHandle = fn GetGWorldPixMap( srcGW )
srcBuf.data     = fn GetPixBaseAddr( pmHandle )
srcBuf.height   = pmHandle..bounds.bottom
srcBuf.width    = pmHandle..bounds.right
srcBuf.rowBytes = fn GetPixRowBytes( pmHandle )

pmHandle = fn GetGWorldPixMap( destGW )
destBuf.data     = fn GetPixBaseAddr( pmHandle )
destBuf.height   = pmHandle..bounds.bottom
destBuf.width    = pmHandle..bounds.right
destBuf.rowBytes = fn GetPixRowBytes( pmHandle )
end fn = fn vImageConvolve_ARGB8888( srcBuf, destBuf, 0, 0, 0, kernel, kernel_ht, kernel_wdth, divisor, bkgrnd, flags )

local mode
local fn DeconvolveKernel( srcGW as CGrafPtr, destGW as CGrafPtr, kernel as ^SInt16, kernel_ht as UInt32, kernel_wdth as UInt32, divisor as SInt32, bkgrnd as ^UInt8, iterCount as UInt32, flags as vImage_Flags )
'~'1
dim as vImage_Buffer srcBuf, destBuf
dim as ^^PixMap      pmHandle 

pmHandle = fn GetGWorldPixMap( srcGW )
srcBuf.data     = fn GetPixBaseAddr( pmHandle )
srcBuf.height   = pmHandle..bounds.bottom
srcBuf.width    = pmHandle..bounds.right
srcBuf.rowBytes = fn GetPixRowBytes( pmHandle )

pmHandle = fn GetGWorldPixMap( destGW )
destBuf.data     = fn GetPixBaseAddr( pmHandle )
destBuf.height   = pmHandle..bounds.bottom
destBuf.width    = pmHandle..bounds.right
destBuf.rowBytes = fn GetPixRowBytes( pmHandle )
end fn = fn vImageRichardsonLucyDeConvolve_ARGB8888( srcBuf, destBuf, 0, 0, 0, kernel, 0, kernel_ht, kernel_wdth, 0, 0, divisor, 0, bkgrnd, iterCount, flags )

include "Tlbx Timer.incl"

// a compact timer function whose resolution is 1 µs on Intel, ≈20 µs on PPC
local mode
local fn MyGetTime as double // system time in s
'~'1
dim as UnsignedWide us
dim as double s
Microseconds( @us )
s = 4294967296.0 * us.hi + us.lo
#if ndef _FBtoC
if ( us.lo < 0 ) then s += 4294967296.0 // workaround for bug in FB compiler
#endif
end fn = s * 1e-6



local mode
local fn DrawTextInGWorld( theGW as CGrafPtr )
'~'1
dim as CGrafPtr  currGW
dim as GDHandle  currDevice
dim as Str255    s
dim as Rect      r

GetGWorld( @currGW, @currDevice )
SetGWorld( theGW, 0 )
SetRect( r, 0, 0, 800, 800 )
PaintRect( r )
MoveTo( 50, 50 )
TextSize( 11 )
TextMode( _srcXor )
s = "a slick green box slumped under the crazy hog"
DrawString( s )
SetGWorld( currGW, currDevice )
end fn

local mode
local fn GetGWorldRect( gw as CGrafPtr, outR as ^Rect )
'~'1
dim as ^^PixMap  pmHandle 

pmHandle = fn GetGWorldPixMap( gw )
BlockMoveData( @pmHandle..bounds, outR, sizeof( Rect ) )
end fn


local mode
local fn CopyGWToSameSizedGW( srcGW as CGrafPtr, destGW as CGrafPtr )
'~'1
dim as Rect  r

fn GetGWorldRect( srcGW, @r )
ForeColor( _blackColor ) // prevent...
BackColor( _whiteColor ) //...false colouration
CopyBits( #fn GetPortBitMapForCopyBits( srcGW ), #fn GetPortBitMapForCopyBits( destGW ), r, r, _srcCopy, 0 )
end fn



// a tent filter with circular symmetry (a cone)
local mode
local fn MakeTentKernel( kernel(_maxLong) as SInt16, filtWidth as long )
'~'1
dim as long    j, k, sum, filtWidthM1, index
dim as double  radius

filtWidthM1 = filtWidth - 1
sum = 0
for j = 0 to filtWidthM1
for k = 0 to filtWidthM1
index = j*filtWidth + k
radius = sqr( (j - 0.5*filtWidthM1)^2 + (k - 0.5*filtWidthM1)^2 )
long if ( radius <= 0.5*(filtWidth) )
kernel(index) = 256*(1.0 - radius/(0.5*filtWidth))
xelse
kernel(index) = 0
end if
sum += kernel(index)
next
next
end fn = sum


local mode
local fn DrawGWorldInNewWindow( srcGW as CGrafPtr, title as Str255 )
'~'1
begin globals
dim as long sWindNum
end globals
dim as Rect  r

fn NewWindowPositionMethod( _kWindowCascadeOnMainScreen )
fn GetGWorldRect( srcGW, @r )
sWindNum++
window sWindNum, title, @r
fn CopyGWToSameSizedGW( srcGW, window( _wndPort ) )
delay 100
FlushWindowBuffer
end fn


'~Main Program

_filtWidth = 11 // must be odd
_filtWidthM1 = _filtWidth - 1

dim as Rect       r        
dim as OSStatus   err
dim as CGrafPtr   rawGW, blurredGW, deblurredGW
dim as SInt16     kernel(_filtWidthM1, _filtWidthM1)
dim as UInt8      backGrnd(3)
dim as long       sum

sum = fn MakeTentKernel( kernel(0, 0), _filtWidth )

SetRect( @r, 0, 0, 350, 100 )
if fn NewGWorld( @rawGW, 32, r, 0, 0, 0 ) then stop "NewGWorld error"
if fn NewGWorld( @blurredGW, 32, r, 0, 0, 0 ) then stop "NewGWorld error"
if fn NewGWorld( @deblurredGW, 32, r, 0, 0, 0 ) then stop "NewGWorld error"

fn DrawTextInGWorld( rawGW )

fn DrawGWorldInNewWindow( rawGW, "Original" )

err = fn ConvolveKernel( rawGW, blurredGW, @kernel(0, 0), _filtWidth, _filtWidth, sum, @backGrnd(0), _kvImageEdgeExtend + _kvImageLeaveAlphaUnchanged )
if ( err ) then stop "ConvolveKernel error " + str$( err )
fn DrawGWorldInNewWindow( blurredGW, "Blurred" )

err = fn DeconvolveKernel( blurredGW, deblurredGW, @kernel(0, 0), _filtWidth, _filtWidth, sum, @backGrnd(0), 20, _kvImageEdgeExtend + _kvImageLeaveAlphaUnchanged )
if ( err ) then stop "DeconvolveKernel error " + str$( err )
fn DrawGWorldInNewWindow( deblurredGW, "Deblurred 20" )

err = fn DeconvolveKernel( blurredGW, deblurredGW, @kernel(0, 0), _filtWidth, _filtWidth, sum, @backGrnd(0), 400, _kvImageEdgeExtend + _kvImageLeaveAlphaUnchanged )
if ( err ) then stop "DeconvolveKernel error " + str$( err )
fn DrawGWorldInNewWindow( deblurredGW, "Deblurred 400" )
/*
err = fn DeconvolveKernel( blurredGW, deblurredGW, @kernel(0, 0), _filtWidth, _filtWidth, sum, @backGrnd(0), 2400, _kvImageEdgeExtend _kvImageLeaveAlphaUnchanged )
if ( err ) then stop "DeconvolveKernel error " + str$( err )
fn DrawGWorldInNewWindow( deblurredGW, "Deblurred 2400" )*/

do
HandleEvents
until gFBQuit