Animated Gif Help

  • Thread starter Thread starter Willdoe
  • Start date Start date
W

Willdoe

Guest
Consider the code that follows, the problem I am having is that when I add a gif with transparency already instead of clearing the image and redrawing it just draws on top of what has already been rendered. I think it has something to do with the writeGraphicCtrlExt() sub routine, but I am not sure. Any help would be just great,



Public Class AnimatedGif
Protected width As Integer
Protected height As Integer
Protected transparent As Color
Protected transIndex As Integer ; // transparent index in color table
Protected repeat As Integer = -1 ; // no repeat
Protected delay As Integer = 0 ; // frame delay (hundredths)
Protected started As Boolean = False ; // ready to output frames
Protected out As IO.FileStream
Protected MyOut As IO.FileStream
Protected image1 As Image ; // current frame
Protected pixels() As Byte ; // BGR byte array from frame
Protected indexedPixels() As Byte ; // converted frame indexed to palette
Protected colorDepth As Integer ; // number of bit planes
Protected colorTab() As Byte ; // RGB palette
Protected usedEntry(256) As Boolean = new boolean[256]; // active palette entries
Protected palSize As Integer = 7 ; // color table size (bits-1)
Protected dispose As Integer = -1 ; // disposal code (-1 = use default)
Protected closeStream As Boolean = False ; // close stream when finished
Protected firstFrame As Boolean = True ;
Protected sizeSet As Boolean = False ; // if false, get size from first frame
Protected sample As Integer = 10 ; // default sample interval for quantizer



Public Sub setDelay(ByVal ms As Integer)
delay = Math.Round(ms / 10.0F)
End Sub


Public Sub setDispose(ByVal code As Integer)
If code >= 0 Then
dispose = code
End If
End Sub


Public Sub setRepeat(ByVal iter As Integer)
If iter >= 0 Then
repeat = iter
End If
End Sub
Public Sub setTransparent(ByVal c As Color)
transparent = c
End Sub

Protected Function findClosest(ByVal c As Color) As Int16


End Function









Dim colorpal As Drawing.Imaging.ColorPalette
Public Function addFrame(ByVal im As Image) As Boolean
If IsNothing(im) Or started = False Then
MsgBox("Error Loading Image", MsgBoxStyle.Critical, "Error")
Return False

End If


Dim ok As Boolean = True
Try
If sizeSet = False Then
// use first frames size
setSize(im.Width, im.Height)
image1 = im.Clone
Else
If im.Width <> width Or im.Height <> height Then

Dim G = Graphics.FromImage(image1)
G.DrawImage(im, 0, 0, image1.Width, image1.Height)
G.Dispose()
End If
End If


getImagePixels() // convert to correct format if necessary
analyzePixels() // build color table & map pixels

colorpal = image1.Palette



If firstFrame = True Then
writeLSD() // logical screen descriptior
out.Flush()
writePalette() // global color table
If (repeat >= 0) Then
// use NS app extension to indicate reps
writeNetscapeExt()
End If
Else

End If


writeres()


writeGraphicCtrlExt() ; // write graphic control extension
writeImageDesc() ; \// image descriptor
If firstFrame = False Then ) {
writePalette()
End If

writePixels() // encode and write pixel data
firstFrame = False
Catch
ok = False
End Try

Return ok
End Function


Public Function finish() As Boolean
If started = False Then Return False
Dim ok As Boolean = True
started = False
Try

out.WriteByte(&H3B) ; // gif trailer
out.Flush() ;
If (closeStream = True) Then
out.Close()
out.Dispose()
image1.Dispose()
End If
Catch
ok = False
End Try

// reset for subsequent use
transIndex = 0 ;
out = Nothing
image1 = Nothing
ReDim pixels(0)
ReDim indexedPixels(0)
ReDim colorTab(0)
closeStream = False
firstFrame = True

Return ok
End Function

/**
* Sets frame rate in frames per second. Equivalent to
*
Code:
setDelay(1000/fps)
.
*
* @param fps float frame rate (frames per second)
*/
Public Sub setFrameRate(ByVal fps As Single)
If fps <> 0 Then
delay = Math.Round(100.0F / fps)
End If
End Sub

/**
* Sets quality of color quantization (conversion of images
* to the maximum 256 colors allowed by the GIF specification).
* Lower values (minimum = 1) produce better colors, but slow
* processing significantly. 10 is the default, and produces
* good color mapping at reasonable speeds. Values greater
* than 20 do not yield significant improvements in speed.
*
* @param quality int greater than 0.
* @return
*/
Public Sub setQuality(ByVal quality As Integer)
If quality < 1 Then quality = 1
sample = quality
End Sub
/**
* Sets the GIF frame size. The default size is the
* size of the first frame added if this method is
* not invoked.
*
* @param w int frame width.
* @param h int frame width.
*/
Public Sub setSize(ByVal w As Integer, ByVal h As Integer)
If started = True And firstFrame = False Then Exit Sub
width = w
height = h
If (width < 1) Then width = 320
If (height < 1) Then height = 240
sizeSet = True
End Sub


/**
* Initiates GIF file creation on the given stream. The stream
* is not closed automatically.
*
* @param os OutputStream on which GIF images are written.
* @return false if initial write failed.
*/
Public Overloads Function start(ByRef os As IO.FileStream) As Boolean
If IsNothing(os) Then Return False
Dim ok As Boolean = True
closeStream = False
out = os
Try
writeString("GIF89a") ; // header
Catch
ok = False
End Try
started = ok

Return started

End Function

/**
* Initiates writing of a GIF file with the specified name.
*
* @param file String containing output file name.
* @return false if open or initial write failed.
*/
Dim outputstream As System.IO.StreamWriter
Public Overloads Function start(ByVal file As String)
Dim ok As Boolean = True
Try
outputstream = New System.IO.StreamWriter(file)
Try
out.Dispose()
Catch
End Try
out = New IO.FileStream(file, IO.FileMode.Create)

ok = start(out)
closeStream = True
Catch
ok = False
End Try
started = ok
Return started
End Function

/**
* Analyzes image colors and creates color map.
*/

/**
* Returns index of palette color closest to c
*
*/


/**
* Extracts image pixels into byte array "pixels"
*/
Protected Sub getImagePixels()
Dim w As Integer = image1.Width()
Dim h As Integer = image1.Height()
Dim thetype As Integer = image1.GetType

If w <> width Or h <> height Then
image1 = New Bitmap(width, height)
End If

if ((w != width)
|| (h != height)
|| (type != BufferedImage.TYPE_3BYTE_BGR)) {
// create new image with right size/format
dim temp as Image = new Bitmap(width,height,
new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = temp.createGraphics();
g.drawImage(image, 0, 0, null);
image = temp;
}

colorpal.

For x As Int16 = 0 To pixels.Count - 1
Console.WriteLine(x & ":" & Hex(x) & ":" & Hex(pixels(x)) & " : " & CStr(x))
Next
Try
Array.Clear(pixels, 0, pixels.Length)
Catch
End Try
ReDim pixels(0)
Dim mem As New IO.MemoryStream
image1.Save(mem, System.Drawing.Imaging.ImageFormat.Gif)
pixels = mem.ToArray
colorpal = image1.Palette.Entries


End Sub

/**
* Writes Graphic Control Extension
*/
Protected Sub writeGraphicCtrlExt()
Dim transp As Integer, disp As Integer
If transparent = Nothing Then
transp = 0
disp = 0 // dispose = no action
Else
transp = 1
disp = 2 ; // force clear if using transparent color
End If
If (dispose >= 0) Then
disp = dispose & 7 ; // user override
End If
disp <<= 2


out.WriteByte(0)



out.WriteByte(&H21) ; // extension introducer
out.WriteByte(&HF9) ; // GCE label
out.WriteByte(&H4) ; // data block size

out.WriteByte(&H4)
// packed fields
out.WriteByte(0 Or 2 Or 0 Or 1) // 1:3 reserved
out.WriteByte(&H1)

disp | // 4:6 disposal
0 | // 7 user input - 0 = none
transp); // 8 transparency flag
writeShort(delay)
56) ; // delay x 1/100 sec
out.WriteByte(pixels(787)) ; // transparent color index
out.WriteByte(0) ; // block terminator
out.Flush()
End Sub

/**
* Writes Image Descriptor
*/
Protected Sub writeImageDesc()
Exit Sub
out.WriteByte(&H2C) ; // image separator
writeShort(0) ; // image position x,y = 0,0
writeShort(0) ;
writeShort(width) ; // image size
writeShort(height) ;
// packed fields
firstFrame = False
If firstFrame = True Then

// no LCT - GCT is used for first (or only) frame
out.WriteByte(0)
Else
// specify normal LCT
out.WriteByte(&H80 Or 0 Or 0 Or 0 Or palSize) // 1 local color table 1=yes
0 | // 2 interlace - 0=no
0 | // 3 sorted - 0=no
0 | // 4-5 reserved
palSize); // 6-8 size of color table
End If

End Sub


/**
* Writes Logical Screen Descriptor
*/
Protected Sub writeLSD() throws IOException {
// logical screen size
out.Flush()
writeShort(width)
writeShort(height)
// packed fields
out.WriteByte(&H80 Or &H70 Or &H0 Or palSize) | // 1 : global color table flag = 1 (gct used)
0x70 | // 2-4 : color resolution = 7
0x00 | // 5 : gct sort flag = 0
palSize)); // 6-8 : gct size

out.WriteByte(0) ; // background color index

out.WriteByte(0) ; // pixel aspect ratio - assume 1:1

out.Write(pixels, 0, 12)



End Sub

/**
* Writes Netscape application extension to define
* repeat count.
*/
Dim NetOffSet As Integer = 0

Protected Sub writeNetscapeExt() throws IOException {
out.WriteByte(&H21) ; // extension introducer
out.WriteByte(&HFF) ; // app extension label
out.WriteByte(11) ; // block size
writeString("NETSCAPE" & "2.0") ; // app id + auth code
out.WriteByte(3) ; // sub-block size
out.WriteByte(1) ; // loop sub-block id
writeShort(repeat) ; // loop count (extra iterations, 0=repeat forever)
out.WriteByte(0) ; // block terminator
NetOffSet = 19
End Sub


/**
* Writes color table

Dim ColorBytes(767) As Byte

Protected Sub writePalette() throws IOException {
out.Write(colorTab, 0, colorTab.Length - 1) , 0, colorTab.Length)



Dim J As Integer = 0
For a As Int16 = 0 To colorpal.Entries.Length - 1

TheColor = colorpal.Entries(a)
ColorBytes(J) = TheColor.R
ColorBytes(J + 1) = TheColor.G
ColorBytes(J + 2) = TheColor.B
J += 3
Next

For x As Int16 = (13) To (780)
out.WriteByte(pixels(x))
Next


out.Write(ColorBytes, 0, ColorBytes.Length)

out.Flush()
Dim n As Integer = (3 * 256) - colorTab.Length ;
For i As Integer = 0 To n
out.WriteByte(0)

Next

End Sub

/**
* Encodes and writes pixel data
*/
Protected Sub writePixels() throws IOException {
Dim encoder As New LZWEncoder1
encoder.LZWEncoder(width, height, indexedPixels, colorDepth)
encoder.encode(out)


For x As Long = 799 To pixels.Length - 2
If x = 796 Then
If firstFrame = True Then
pixels(x) = 0
Else
pixels(x) = &H80 Or 0 Or 0 Or 0 Or palSize
End If
End If


If x = 786 Then
writeShort(delay)
Else
out.WriteByte(pixels(x))
Console.WriteLine(x & " - " & pixels(x))
End If


Next x
out.WriteByte(8)
out.WriteByte(0)

End While

End Sub

/**
* Write 16-bit value to output stream, LSB first
*/
Protected Sub writeShort(ByVal value As Int16) throws IOException {
out.Write(System.Text.ASCIIEncoding.Unicode.GetBytes(value And &HFF), 0, Len(value))
Dim val1 As Int16, val2 As Int16
val1 = value And &HFF
val2 = (value >> 8) And &HFF

Dim bytes() As Byte = System.BitConverter.GetBytes(val1)
bytes = System.Text.Encoding.ASCII.GetBytes(value)
out.Write(bytes, 0, bytes.Length - 1)
Dim bytes2() As Byte = System.BitConverter.GetBytes(val2)
out.Write(bytes2, 0, bytes2.Length - 1)
out.WriteByte(value And &HFF)
out.WriteByte((value >> 8) And &HFF)
End Sub

/**
* Writes string to output stream
*/
Protected Sub writeString(ByVal s As String) throws IOException {
For i As Integer = 0 To s.Length() - 1
out.Write(System.Text.Encoding.ASCII.GetBytes(s), 0, System.Text.Encoding.ASCII.GetByteCount(s.Length))
out.WriteByte(AscW(s(i)))
Next




End Sub

Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
End Class

Continue reading...
 
Back
Top