'From R&DSqueak2.8 of 6 June 2001 [latest update: #42] on 28 January 2002 at 1:08:03 pm'! !JPEGMovieFile class methodsFor: 'movie conversion' stamp: 'jm 1/25/2002 20:46'! convertFromFolderOfFramesNamed: folderName toJPEGMovieNamed: jpegFileName frameRate: frameRate quality: quality "Convert a folder of frames into a JPEG movie. The named folder is assumed to contain only image files, all of the same size, and whose alphabetical order (case-insensitive) is the sequence in which they will appear in in the movie. A useful convention is to make the image files end in zero-padded frame numbers, for example 'frame0001.bmp', 'frame0002.bmp', etc. The image files can be any format readable by Form>fromFileNamed:. The movie frame extent is taken from the first frame file." | jpegFile dir fileNames frameCount frameForm frameOffsets | (FileDirectory default directoryExists: folderName) ifFalse: [^ self inform: 'Folder not found: ', folderName]. jpegFile _ (FileStream newFileNamed: jpegFileName) binary. dir _ FileDirectory default on: folderName. fileNames _ self sortedByFrameNumber: dir fileNames. frameCount _ fileNames size. frameForm _ Form fromFileNamed: (dir fullNameFor: fileNames first). "write header" self writeHeaderExtent: frameForm extent frameRate: frameRate frameCount: frameCount soundtrackCount: 0 on: jpegFile. "convert and write frames" frameOffsets _ Array new: frameCount + 1. 1 to: frameCount do: [:i | frameOffsets at: i put: jpegFile position. frameForm _ Form fromFileNamed: (dir fullNameFor: (fileNames at: i)). self writeFrame: frameForm on: jpegFile quality: quality displayFlag: true]. frameOffsets at: (frameCount + 1) put: jpegFile position. self updateFrameOffsets: frameOffsets on: jpegFile. jpegFile close. Display restore. ! ! !JPEGMovieFile class methodsFor: 'movie creation-private' stamp: 'jm 1/25/2002 21:08'! extractFrameNumberFrom: aString "Answer the integer frame number from the given file name string. The frame number is assumed to be the last contiguous sequence of digits in the given string. For example, 'take2 005.jpg' is frame 5 of the sequence 'take2'." "Assume: The given string contains at least one digit." | end start | end _ aString size. [(aString at: end) isDigit not] whileTrue: [end _ end - 1]. start _ end. [(start > 1) and: [(aString at: start - 1) isDigit]] whileTrue: [start _ start - 1]. ^ (aString copyFrom: start to: end) asNumber ! ! !JPEGMovieFile class methodsFor: 'movie creation-private' stamp: 'jm 1/25/2002 20:53'! sortedByFrameNumber: fileNames "Sort the given collection of fileNames by frame number. The frame number is the integer value of the last contiguous sequence of digits in the file name." | pairs | "make sure file names contain frame numbers" (fileNames first select: [:c | c isDigit]) size = 0 ifTrue: [ ^ fileNames sort: [:n1 :n2 | n1 caseInsensitiveLessOrEqual: n2]]. "make array of number, name pairs" pairs _ fileNames asArray collect: [:fn | Array with: (self extractFrameNumberFrom: fn) with: fn]. "sort them, then extract the second element of each pair" pairs sort: [:p1 :p2 | p1 first < p2 first]. ^ pairs collect: [:p | p last]. ! !