Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: bower_components/gif.js/src/gif.coffee

Issue 786953007: npm_modules: Fork bower_components into Polymer 0.4.0 and 0.5.0 versions (Closed) Base URL: https://chromium.googlesource.com/infra/third_party/npm_modules.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 {EventEmitter} = require 'events'
2 browser = require './browser.coffee'
3
4 class GIF extends EventEmitter
5
6 defaults =
7 workerScript: 'gif.worker.js'
8 workers: 2
9 repeat: 0 # repeat forever, -1 = repeat once
10 background: '#fff'
11 quality: 10 # pixel sample interval, lower is better
12 width: null # size derermined from first frame if possible
13 height: null
14 transparent: null
15
16 frameDefaults =
17 delay: 500 # ms
18 copy: false
19
20 constructor: (options) ->
21 @running = false
22
23 @options = {}
24 @frames = []
25
26 @freeWorkers = []
27 @activeWorkers = []
28
29 @setOptions options
30 for key, value of defaults
31 @options[key] ?= value
32
33 setOption: (key, value) ->
34 @options[key] = value
35 if @_canvas? and key in ['width', 'height']
36 @_canvas[key] = value
37
38 setOptions: (options) ->
39 @setOption key, value for own key, value of options
40
41 addFrame: (image, options={}) ->
42 frame = {}
43 frame.transparent = @options.transparent
44 for key of frameDefaults
45 frame[key] = options[key] or frameDefaults[key]
46
47 # use the images width and height for options unless already set
48 @setOption 'width', image.width unless @options.width?
49 @setOption 'height', image.height unless @options.height?
50
51 if ImageData? and image instanceof ImageData
52 frame.data = image.data
53 else if (CanvasRenderingContext2D? and image instanceof CanvasRenderingConte xt2D) or (WebGLRenderingContext? and image instanceof WebGLRenderingContext)
54 if options.copy
55 frame.data = @getContextData image
56 else
57 frame.context = image
58 else if image.childNodes?
59 if options.copy
60 frame.data = @getImageData image
61 else
62 frame.image = image
63 else
64 throw new Error 'Invalid image'
65
66 @frames.push frame
67
68 render: ->
69 throw new Error 'Already running' if @running
70
71 if not @options.width? or not @options.height?
72 throw new Error 'Width and height must be set prior to rendering'
73
74 @running = true
75 @nextFrame = 0
76 @finishedFrames = 0
77
78 @imageParts = (null for i in [0...@frames.length])
79 numWorkers = @spawnWorkers()
80 @renderNextFrame() for i in [0...numWorkers]
81
82 @emit 'start'
83 @emit 'progress', 0
84
85 abort: ->
86 loop
87 worker = @activeWorkers.shift()
88 break unless worker?
89 console.log "killing active worker"
90 worker.terminate()
91 @running = false
92 @emit 'abort'
93
94 # private
95
96 spawnWorkers: ->
97 numWorkers = Math.min(@options.workers, @frames.length)
98 [@freeWorkers.length...numWorkers].forEach (i) =>
99 console.log "spawning worker #{ i }"
100 worker = new Worker @options.workerScript
101 worker.onmessage = (event) =>
102 @activeWorkers.splice @activeWorkers.indexOf(worker), 1
103 @freeWorkers.push worker
104 @frameFinished event.data
105 @freeWorkers.push worker
106 return numWorkers
107
108 frameFinished: (frame) ->
109 console.log "frame #{ frame.index } finished - #{ @activeWorkers.length } ac tive"
110 @finishedFrames++
111 @emit 'progress', @finishedFrames / @frames.length
112 @imageParts[frame.index] = frame
113 if null in @imageParts
114 @renderNextFrame()
115 else
116 @finishRendering()
117
118 finishRendering: ->
119 len = 0
120 for frame in @imageParts
121 len += (frame.data.length - 1) * frame.pageSize + frame.cursor
122 len += frame.pageSize - frame.cursor
123 console.log "rendering finished - filesize #{ Math.round(len / 1000) }kb"
124 data = new Uint8Array len
125 offset = 0
126 for frame in @imageParts
127 for page, i in frame.data
128 data.set page, offset
129 if i is frame.data.length - 1
130 offset += frame.cursor
131 else
132 offset += frame.pageSize
133
134 image = new Blob [data],
135 type: 'image/gif'
136
137 @emit 'finished', image, data
138
139 renderNextFrame: ->
140 throw new Error 'No free workers' if @freeWorkers.length is 0
141 return if @nextFrame >= @frames.length # no new frame to render
142
143 frame = @frames[@nextFrame++]
144 worker = @freeWorkers.shift()
145 task = @getTask frame
146
147 console.log "starting frame #{ task.index + 1 } of #{ @frames.length }"
148 @activeWorkers.push worker
149 worker.postMessage task#, [task.data.buffer]
150
151 getContextData: (ctx) ->
152 return ctx.getImageData(0, 0, @options.width, @options.height).data
153
154 getImageData: (image) ->
155 if not @_canvas?
156 @_canvas = document.createElement 'canvas'
157 @_canvas.width = @options.width
158 @_canvas.height = @options.height
159
160 ctx = @_canvas.getContext '2d'
161 ctx.setFill = @options.background
162 ctx.fillRect 0, 0, @options.width, @options.height
163 ctx.drawImage image, 0, 0
164
165 return @getContextData ctx
166
167 getTask: (frame) ->
168 index = @frames.indexOf frame
169 task =
170 index: index
171 last: index is (@frames.length - 1)
172 delay: frame.delay
173 transparent: frame.transparent
174 width: @options.width
175 height: @options.height
176 quality: @options.quality
177 repeat: @options.repeat
178 canTransfer: (browser.name is 'chrome')
179
180 if frame.data?
181 task.data = frame.data
182 else if frame.context?
183 task.data = @getContextData frame.context
184 else if frame.image?
185 task.data = @getImageData frame.image
186 else
187 throw new Error 'Invalid frame'
188
189 return task
190
191 module.exports = GIF
OLDNEW
« no previous file with comments | « bower_components/gif.js/src/browser.coffee ('k') | bower_components/gif.js/src/gif.worker.coffee » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698