'From Squeak3.1alpha of 4 February 2001 [latest update: #3806] on 7 March 2001 at 1:14:22 am'! "Change Set: JPEGTweaks3 Date: 7 March 2001 Author: Andreas Raab A few streamlined methods give us another 25% in speed for free."! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/7/2001 00:18'! decompressionTest "Test decompression; don't generate actual image" | xStep yStep x y | MessageTally spyOn:[ ditherMask _ DitherMasks at: 32. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. x _ x + xStep]. y _ y + yStep]. ].! ! !JPEGReadWriter methodsFor: 'public access' stamp: 'ar 3/7/2001 00:17'! nextImageDitheredToDepth: depth | form xStep yStep x y | ditherMask _ DitherMasks at: depth ifAbsent: [self error: 'can only dither to display depths']. residuals _ WordArray new: 3. sosSeen _ false. self parseFirstMarker. [sosSeen] whileFalse: [self parseNextMarker]. form _ Form extent: (width @ height) depth: 32. xStep _ mcuWidth * DCTSize. yStep _ mcuHeight * DCTSize. y _ 0. 1 to: mcuRowsInScan do: [:row | x _ 0. 1 to: mcusPerRow do: [:col | self decodeMCU. self idctMCU. self colorConvertMCU. mcuImageBuffer displayOn: form at: (x @ y). x _ x + xStep]. y _ y + yStep]. ^ form! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/6/2001 22:28'! parseAPPn | length buffer thumbnailLength markerStart | markerStart _ self position. length _ self nextWord. buffer _ self next: 4. (buffer asString = 'JFIF') ifFalse: [ "Skip APPs that we're not interested in" stream next: length-6. ^self]. self next. majorVersion _ self next. minorVersion _ self next. densityUnit _ self next. xDensity _ self nextWord. yDensity _ self nextWord. thumbnailLength _ self next * self next * 3. length _ length - (self position - markerStart). length = thumbnailLength ifFalse: [self error: 'APP0 thumbnail length is incorrect.']. self next: length! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/6/2001 22:18'! parseNextMarker | byte discardedBytes | discardedBytes _ 0. [(byte _ self next) = 16rFF] whileFalse: [discardedBytes _ discardedBytes + 1]. [[(byte _ self next) = 16rFF] whileTrue. byte = 16r00] whileTrue: [discardedBytes _ discardedBytes + 2]. discardedBytes > 0 ifTrue: [self notify: 'warning: extraneous data discarded']. self perform: (JFIFMarkerParser at: byte ifAbsent: [(self okToIgnoreMarker: byte) ifTrue: [#skipMarker] ifFalse: [self error: 'marker ', byte hex , ' cannot be handled']])! ! !JPEGReadWriter methodsFor: 'marker parsing' stamp: 'ar 3/7/2001 01:01'! perScanSetup mcusPerRow _ (width / (mcuWidth * DCTSize)) ceiling. mcuRowsInScan _ (height / (mcuHeight * DCTSize)) ceiling. (currentComponents size = 3 or: [currentComponents size = 1]) ifFalse: [self error: 'JPEG color space not recognized']. mcuMembership _ OrderedCollection new. currentComponents withIndexDo: [:c :i | c priorDCValue: 0. mcuMembership addAll: ((1 to: c totalMcuBlocks) collect: [:b | i])]. mcuMembership _ mcuMembership asArray. mcuSampleBuffer _ (1 to: mcuMembership size) collect: [:i | IntegerArray new: DCTSize2]. currentComponents withIndexDo: [:c :i | c initializeSampleStreamBlocks: ((1 to: mcuMembership size) select: [:j | i = (mcuMembership at: j)] thenCollect: [:j | mcuSampleBuffer at: j])]. mcuImageBuffer _ Form extent: (mcuWidth @ mcuHeight) * DCTSize depth: 32. restartsToGo _ restartInterval.! ! !JPEGReadWriter methodsFor: 'huffman encoding' stamp: 'ar 3/7/2001 01:00'! decodeMCU | comp ci | (restartInterval ~= 0 and: [restartsToGo = 0]) ifTrue: [self processRestart]. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. self primDecodeBlockInto: (mcuSampleBuffer at: i) component: comp dcTable: (hDCTable at: comp dcTableIndex) acTable: (hACTable at: comp acTableIndex) stream: stream. ]. restartsToGo _ restartsToGo - 1.! ! !JPEGReadWriter methodsFor: 'dct' stamp: 'ar 3/7/2001 00:58'! idctMCU | comp fp ci | fp _ self useFloatingPoint. 1 to: mcuMembership size do:[:i| ci _ mcuMembership at: i. comp _ currentComponents at: ci. fp ifTrue:[ self idctBlockFloat: (mcuSampleBuffer at: i) component: comp. ] ifFalse:[ self primIdctInt: (mcuSampleBuffer at: i) qt: (qTable at: comp qTableIndex)]].! ! !JPEGReadWriter methodsFor: 'colorspace conversion' stamp: 'ar 3/7/2001 01:02'! colorConvertMCU ^ currentComponents size = 3 ifTrue: [self useFloatingPoint ifTrue: [self colorConvertFloatYCbCrMCU] ifFalse: [self primColorConvertYCbCrMCU: currentComponents bits: mcuImageBuffer bits residuals: residuals ditherMask: ditherMask.]] ifFalse: [self primColorConvertGrayscaleMCU]! !