|
| Rotating image created with Victor functions rotate and savegifframe. |
Private Sub mnumakeanimatedgif_Click()
Dim rcode As Long
Dim loadfname As String
Dim tdat As TiffData
Dim frames As Long
Dim srcimg As imgdes
Dim savefname As String
Dim savesegments As Boolean
loadfname = "victor.tif"
rcode = tiffinfo(loadfname, tdat)
If (rcode = NO_ERROR) Then
rcode = allocimage(srcimg, tdat.width, tdat.length, tdat.vbitcount)
If (rcode = NO_ERROR) Then
rcode = loadtif(loadfname, srcimg)
If (rcode = NO_ERROR) Then
frames = 10
savefname = "rotate.gif"
savesegments = False
rcode = makespinningGIF(frames, srcimg, savefname, savesegments)
End If
freeimage srcimg
End If
End If
End Sub
' A helper function to find the white color in the palette.
Private Function findwhite(srcimg As imgdes) As Long
Dim gifPalette(0 To 255) As RGBQUAD
Dim j As Long
Dim r As Long, g As Long, b As Long
Dim maxwhite As Long
Dim maxwhiteindex As Long
CopyMemory gifPalette(0), srcimg.palette, srcimg.colors * 4
maxwhiteindex = -1
For j = 0 To srcimg.colors - 1
r = gifPalette(j).rgbRed
g = gifPalette(j).rgbGreen
b = gifPalette(j).rgbBlue
If r = g And r = b Then
If r > maxwhite Then
maxwhiteindex = j
maxwhite = r
End If
End If
Next
findwhite = maxwhiteindex
End Function
Public Function makespinningGIF(frames As Long, srcimg As imgdes, savefname As String, Optional savesegments As Boolean) As Long
Dim srcimgBMH As BITMAPINFOHEADER
Dim rcode As Long
Dim cols As Long, rows As Long
Dim j As Long
Dim diagonal As Long
Dim ddiagonal As Double
Dim desimg As imgdes
Dim foundwhite As Long
Dim gdata As GifGlobalSaveData
Dim fdata As GifFrameSaveData
CopyMemory srcimgBMH, srcimg.bmh, 40
If srcimgBMH.biBitCount <> 8 Then
makespinningGIF = BAD_BPP: Exit Function
End If
cols = CALC_WIDTH(srcimg)
rows = CALC_HEIGHT(srcimg)
foundwhite = findwhite(srcimg)
ddiagonal = Sqr(cols ^ 2 + rows ^ 2)
diagonal = ddiagonal + 0.5
' GIF global data used by savegifframe()
gdata.scrwidth = diagonal
gdata.scrlength = diagonal
gdata.hasColorMap = 1 ' Global color table is present!
gdata.bckColor = foundwhite ' Color index of screen backgnd
gdata.loop = 1000 ' Number of iterations
fdata.startx = 0
fdata.starty = 0 ' X,Y pixel position with respect to scrwidth, scrlength
fdata.hasColorMap = 0 ' Local color table present?
fdata.delay = 1 ' 100ths of a second to display frame
fdata.transColor = -1 ' Transparent color index, -1 => none
fdata.waitForUserInput = 0 ' If true, expect user input
fdata.removeBy = 2 ' How graphic is to be treated after display
' 0 – The image is left unremoved
' 1 – The image is left unremoved
' 2 – The image is replaced by the background
' 3 – The image is replaced by the previous image
rcode = allocimage(desimg, diagonal, diagonal, 8)
copyimagepalette srcimg, desimg
For j = frames - 1 To 0 Step -1
Dim angle As Double
Dim tmpangle As Double
Dim dx As Long, dy As Long
zeroimage foundwhite, desimg
angle = 360 / frames * j
' Calc the width and height of the rotated image area
tmpangle = angle
Do While tmpangle > 90: tmpangle = tmpangle - 90: Loop
If (angle >= 0 And angle <= 90) Or (angle > 180 And angle <= 270) Then
dx = (Sin(D2R * (tmpangle)) * rows) + (Sin(D2R * (90 - tmpangle)) * cols)
dy = (Sin(D2R * (tmpangle)) * cols) + (Sin(D2R * (90 - tmpangle)) * rows)
ElseIf (angle > 90 And angle <= 180) Or (angle > 270 And angle < 360) Then
dx = (Sin(D2R * (tmpangle)) * cols) + (Sin(D2R * (90 - tmpangle)) * rows)
dy = (Sin(D2R * (tmpangle)) * rows) + (Sin(D2R * (90 - tmpangle)) * cols)
End If
' Set the area into which to place the rotated image
desimg.stx = (diagonal - dx) / 2
desimg.sty = (diagonal - dy) / 2
desimg.endx = desimg.stx + dx - 1
desimg.endy = desimg.sty + dy - 1
rotate angle, srcimg, desimg
' Restore starting position, save whole frame
desimg.stx = 0
desimg.sty = 0
desimg.endx = diagonal - 1
desimg.endy = diagonal - 1
If savesegments = False Then
rcode = savegifframe(savefname, desimg, gdata, fdata, GIFNOCOMP)
Else
rcode = savegifframe(left(savefname, Len(savefname) - 4) & Format(j, "000") & ".gif", desimg, gdata, fdata, GIFNOCOMP)
End If
Next
freeimage desimg
makespinningGIF = rcode
End Function
// A helper function to find the white color in the palette. int findwhite(imgdes *srcimg) { int j; int r, g, b; int maxwhite = 0; int maxwhiteindex = -1; for(j = 0; j <= srcimg->colors; j++) { r = srcimg->palette[j].rgbRed; g = srcimg->palette[j].rgbGreen; b = srcimg->palette[j].rgbBlue; if(r == g && r == b) if (r > maxwhite) { maxwhiteindex = j; maxwhite = r; } } return maxwhiteindex; } /* A helper function that does a fast calculation of rotated width = costheta * cols + sintheta * rows rotated height = sintheta * cols + costheta * rows see any graphics (or trig) textbook for details. */ // Calculate the cols and rows (in pixels) that will contain the rotated image area. static void calcMinRotImageArea(double angDeg, imgdes far *image, int far *dcols, // Dimensions of image area that can hold the int far *drows) // rotated source image { #define L_MULTIP 15 // Power of 2 to scale doubles to #define MRD_FACTOR (double)(1L << L_MULTIP) #define MRL_FACTOR (1L << L_MULTIP) #define MRSCALE_UPD(dval) ((long)((dval) * MRD_FACTOR)) #define MRSCALE_DNL(lval) ((int)((lval + (MRL_FACTOR - 1)) / MRL_FACTOR)) #define PI 3.141592654 #define DEGTORAD(ang) ((ang) * PI / 180.0) unsigned cols, rows; long sintheta, costheta; double angRad; // Make sure angle lies between -360 -> +360 while(angDeg > 360.0) angDeg -= 360.0; while(angDeg < -360.0) angDeg += 360.0; // Convert angle to radians angRad = DEGTORAD(angDeg); // Calc a long int version of our sine and cosine sintheta = MRSCALE_UPD( sin(angRad) ); costheta = MRSCALE_UPD( cos(angRad) ); // Calc absolute values of sine and cosine if(sintheta < 0L) sintheta = -sintheta; if(costheta < 0L) costheta = -costheta; cols = CALC_WIDTH(image); rows = CALC_HEIGHT(image); *dcols = MRSCALE_DNL( costheta * cols + sintheta * rows ); *drows = MRSCALE_DNL( sintheta * cols + costheta * rows ); } int makespinningGIF(int frames, imgdes *srcimg) { int rcode = NO_ERROR; int cols, rows; int j; int diagonal; double ddiagonal; imgdes desimg; int foundwhite; GifGlobalSaveData gdata; GifFrameSaveData fdata; if(srcimg->bmh->biBitCount != 8) return(BAD_BPP); cols = CALC_WIDTH(srcimg); rows = CALC_HEIGHT(srcimg); foundwhite = findwhite(srcimg); ddiagonal = sqrt( (double) (cols*cols +rows*rows) ); diagonal = (int)(ddiagonal+.5); // GIF global data used by savegifframe() gdata.scrwidth = diagonal; gdata.scrlength = diagonal; gdata.hasColorMap = TRUE; // Global color table is present! gdata.bckColor = foundwhite; // Color index of screen backgnd gdata.loop = 1000; // Number of iterations fdata.startx = 0; fdata.starty = 0; // X,Y pixel position with respect to scrwidth, scrlength fdata.hasColorMap = FALSE; // Local color table present? fdata.delay = 1; // 100ths of a second to display frame fdata.transColor = -1; // Transparent color index, -1 => none fdata.waitForUserInput = FALSE; // If true, expect user input fdata.removeBy = 2; // How graphic is to be treated after display // 0 – The image is left unremoved // 1 – The image is left unremoved // 2 – The image is replaced by the background // 3 – The image is replaced by the previous image rcode = allocimage(&desimg, diagonal, diagonal, 8); copyimagepalette(srcimg, &desimg); for(j = frames-1; j >= 0; j--) { double angle; int dx, dy; zeroimage(foundwhite, &desimg); angle = (double) (360 / (double)frames * (double)j); // Calc the width and height of the rotated image area calcMinRotImageArea(angle, &Image, &dx, &dy); // Set the area into which to place the rotated image desimg.stx = (diagonal - dx) / 2; desimg.sty = (diagonal - dy) / 2; desimg.endx = desimg.stx + dx - 1; desimg.endy = desimg.sty + dy - 1; rotate(angle, srcimg, &desimg); // Restore starting position, save whole frame desimg.stx = 0; desimg.sty = 0; desimg.endx = diagonal - 1; desimg.endy = diagonal - 1; rcode = savegifframe("rotate.gif", &desimg, &gdata, &fdata, GIFNOCOMP); } freeimage(&desimg); return (rcode); }
Victor Image Processing Library homepage | Victor Product Summary | more source code