[squeak-dev] The Inbox: Graphics-nice.285.mcz

Tobias Pape Das.Linux at gmx.de
Wed Jan 1 22:07:02 UTC 2014


On 01.01.2014, at 19:55, commits at source.squeak.org wrote:

> Nicolas Cellier uploaded a new version of Graphics to project The Inbox:
> http://source.squeak.org/inbox/Graphics-nice.285.mcz
> 
> ==================== Summary ====================
> 
> Name: Graphics-nice.285
> Author: nice
> Time: 1 January 2014, 8:53:32.416 pm
> UUID: 04aee02d-83ae-4b4d-aed9-968a6a7487db
> Ancestors: Graphics-nice.284
> 
> Change Color implementation from 10 bits per (rgb) component to 8 bits per component.
> Several considerations motivate this change:
> - no Graphic output is using 10 bits;

Au contraire!
http://lmgtfy.com/?q=10+bit+graphics
https://nvidia.custhelp.com/app/answers/detail/a_id/3011/~/10-bit-per-color-support-on-nvidia-geforce-gpus
http://www.luminous-landscape.com/reviews/accessories/10bit.shtml
http://www.amd.com/us/Documents/10-Bit.pdf

Best
	-Tobias

> - alpha channel is already stored using 8 bits;
> - 8 bits matches nowadays most used 32 bits depth Form - thus it's an optimization.
> Note that the tolerance for testing Color components has to be increased to a value >= (1/255), I suggest 0.005.
> 
> =============== Diff against Graphics-nice.284 ===============
> 
> Item was added:
> + (PackageInfo named: 'Graphics') preamble: '"Change color components from 10 to 8 bits"
> + Color allSubInstancesDo:
> + 	[:c |
> + 	| rgb |
> + 	rgb := c instVarNamed: ''rgb''.
> + 	rgb := (rgb bitAnd: 16r3FC00000) >> 2 + (rgb bitAnd: 16rFF000) >> 2 + (rgb bitAnd: 16r3FC) >> 2.
> + 	c instVarNamed: ''rgb'' put: rgb; flushCache].'!
> 
> Item was changed:
>  ----- Method: Color class>>initialize (in category 'class initialization') -----
>  initialize
>  	"Color initialize"
> 
>  	"Details: Externally, the red, green, and blue components of color
>  	are floats in the range [0.0..1.0]. Internally, they are represented
>  	as integers in the range [0..ComponentMask] packing into a
>  	small integer to save space and to allow fast hashing and
>  	equality testing.
> 
>  	For a general description of color representations for computer
>  	graphics, including the relationship between the RGB and HSV
>  	color models used here, see Chapter 17 of Foley and van Dam,
>  	Fundamentals of Interactive Computer Graphics, Addison-Wesley,
>  	1982."
> 
> + 	ComponentMask := 255.
> + 	HalfComponentMask := 128.  "used to round up in integer calculations"
> + 	ComponentMax := 255.0.  "a Float used to normalize components"
> + 	RedShift := 16.
> + 	GreenShift := 8.
> - 	ComponentMask := 1023.
> - 	HalfComponentMask := 512.  "used to round up in integer calculations"
> - 	ComponentMax := 1023.0.  "a Float used to normalize components"
> - 	RedShift := 20.
> - 	GreenShift := 10.
>  	BlueShift := 0.
> 
>  	PureRed		 := self r: 1 g: 0 b: 0.
>  	PureGreen	 := self r: 0 g: 1 b: 0.
>  	PureBlue	 := self r: 0 g: 0 b: 1.
>  	PureYellow	 := self r: 1 g: 1 b: 0.
>  	PureCyan	 := self r: 0 g: 1 b: 1.
>  	PureMagenta := self r: 1 g: 0 b: 1.
> 
>  	RandomStream := Random new.
> 
>  	self initializeIndexedColors.
>  	self initializeGrayToIndexMap.
>  	self initializeNames.
>  	self initializeHighLights.
>  !
> 
> Item was changed:
>  ----- Method: Color class>>initializeGrayToIndexMap (in category 'class initialization') -----
>  initializeGrayToIndexMap
>  	"Build an array of gray values available in the 8-bit colormap. This array is indexed by a gray level between black (1) and white (256) and returns the pixel value for the corresponding gray level."
>  	"Note: This method must be called after initializeIndexedColors, since it uses IndexedColors."
>  	"Color initializeGrayToIndexMap"
> 
>  	| grayLevels grayIndices c distToClosest dist indexOfClosest |
>  	"record the level and index of each gray in the 8-bit color table"
>  	grayLevels := OrderedCollection new.
>  	grayIndices := OrderedCollection new.
>  	"Note: skip the first entry, which is reserved for transparent"
>  	2 to: IndexedColors size do: [:i |
>  		c := IndexedColors at: i.
>  		c saturation = 0.0 ifTrue: [  "c is a gray"
> + 			grayLevels add: c privateBlue.  "top 8 bits; R, G, and B are the same"
> - 			grayLevels add: (c privateBlue) >> 2.  "top 8 bits; R, G, and B are the same"
>  			grayIndices add: i - 1]].  "pixel values are zero-based"
>  	grayLevels := grayLevels asArray.
>  	grayIndices := grayIndices asArray.
> 
>  	"for each gray level in [0..255], select the closest match"
>  	GrayToIndexMap := ByteArray new: 256.
>  	0 to: 255 do: [:level |
>  		distToClosest := 10000.  "greater than distance to any real gray"
>  		1 to: grayLevels size do: [:i |
>  			dist := (level - (grayLevels at: i)) abs.
>  			dist < distToClosest ifTrue: [
>  				distToClosest := dist.
>  				indexOfClosest := grayIndices at: i]].
>  		GrayToIndexMap at: (level + 1) put: indexOfClosest].
>  !
> 
> Item was changed:
>  ----- Method: Color>>asHTMLColor (in category 'conversions') -----
>  asHTMLColor
> + 	^'#' , (rgb printStringBase: 16 length: 6 padded: true)!
> - 	| s |
> - 	s := '#000000' copy.
> - 	s at: 2 put: (Character digitValue: ((rgb bitShift: -6 - RedShift) bitAnd: 15)).
> - 	s at: 3 put: (Character digitValue: ((rgb bitShift: -2 - RedShift) bitAnd: 15)).
> - 	s at: 4 put: (Character digitValue: ((rgb bitShift: -6 - GreenShift) bitAnd: 15)).
> - 	s at: 5 put: (Character digitValue: ((rgb bitShift: -2 - GreenShift) bitAnd: 15)).
> - 	s at: 6 put: (Character digitValue: ((rgb bitShift: -6 - BlueShift) bitAnd: 15)).
> - 	s at: 7 put: (Character digitValue: ((rgb bitShift: -2 - BlueShift) bitAnd: 15)).
> - 	^ s!
> 
> Item was changed:
>  ----- Method: Color>>closestPixelValue1 (in category 'conversions') -----
>  closestPixelValue1
>  	"Return the nearest approximation to this color for a monochrome Form."
> 
>  	"fast special cases"
>  	rgb = 0 ifTrue: [^ 1].  "black"
> + 	rgb = 16rFFFFFFF ifTrue: [^ 0].  "white"
> - 	rgb = 16r3FFFFFFF ifTrue: [^ 0].  "white"
> 
>  	self luminance > 0.5
>  		ifTrue: [^ 0]  "white"
>  		ifFalse: [^ 1].  "black"
>  !
> 
> Item was changed:
>  ----- Method: Color>>closestPixelValue2 (in category 'conversions') -----
>  closestPixelValue2
>  	"Return the nearest approximation to this color for a 2-bit deep Form."
> 
>  	| lum |
>  	"fast special cases"
>  	rgb = 0 ifTrue: [^ 1].  "black"
> + 	rgb = 16rFFFFFFF ifTrue: [^ 2].  "opaque white"
> - 	rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
> 
>  	lum := self luminance.
>  	lum < 0.2 ifTrue: [^ 1].  "black"
>  	lum > 0.6 ifTrue: [^ 2].  "opaque white"
>  	^ 3  "50% gray"
>  !
> 
> Item was changed:
>  ----- Method: Color>>closestPixelValue4 (in category 'conversions') -----
>  closestPixelValue4
>  	"Return the nearest approximation to this color for a 4-bit deep Form."
> 
>  	| bIndex |
>  	"fast special cases"
>  	rgb = 0 ifTrue: [^ 1].  "black"
> + 	rgb = 16rFFFFFFF ifTrue: [^ 2].  "opaque white"
> - 	rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
> 
>  	rgb = PureRed privateRGB ifTrue: [^ 4].
>  	rgb = PureGreen privateRGB ifTrue: [^ 5].
>  	rgb = PureBlue privateRGB ifTrue: [^ 6].
>  	rgb = PureCyan privateRGB ifTrue: [^ 7].
>  	rgb = PureYellow privateRGB ifTrue: [^ 8].
>  	rgb = PureMagenta privateRGB ifTrue: [^ 9].
> 
>  	bIndex := (self luminance * 8.0) rounded.  "bIndex in [0..8]"
>  	^ #(
>  		1	"black"
>  		10	"1/8 gray"
>  		11	"2/8 gray"
>  		12	"3/8 gray"
>  		3	"4/8 gray"
>  		13	"5/8 gray"
>  		14	"6/8 gray"
>  		15	"7/8 gray"
>  		2	"opaque white"
>  	) at: bIndex + 1.
>  !
> 
> Item was changed:
>  ----- Method: Color>>closestPixelValue8 (in category 'conversions') -----
>  closestPixelValue8
>  	"Return the nearest approximation to this color for an 8-bit deep Form."
> 
>  	"fast special cases"
>  	rgb = 0 ifTrue: [^ 1].  "black"
> + 	rgb = 16rFFFFFFF ifTrue: [^ 255].  "white"
> - 	rgb = 16r3FFFFFFF ifTrue: [^ 255].  "white"
> 
>  	self saturation < 0.2 ifTrue: [
> + 		^ GrayToIndexMap at: self privateGreen + 1.  "nearest gray"
> - 		^ GrayToIndexMap at: (self privateGreen >> 2) + 1.  "nearest gray"
>  	] ifFalse: [
>  		"compute nearest entry in the color cube"
>  		^ 40 +
>  		  ((((self privateRed * 5) + HalfComponentMask) // ComponentMask) * 36) +
>  		  ((((self privateBlue * 5) + HalfComponentMask) // ComponentMask) * 6) +
>  		  (((self privateGreen * 5) + HalfComponentMask) // ComponentMask)].
>  !
> 
> Item was changed:
>  ----- Method: Color>>pixelValueForDepth: (in category 'conversions') -----
>  pixelValueForDepth: d
>  	"Returns an integer representing the bits that appear in a single pixel of this color in a Form of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32. Contrast with pixelWordForDepth: and bitPatternForDepth:, which return either a 32-bit word packed with the given pixel value or a multiple-word Bitmap containing a pattern. The inverse is the class message colorFromPixelValue:depth:"
>  	"Details: For depths of 8 or less, the result is a colorMap index. For depths of 16 and 32, it is a direct color value with 5 or 8 bits per color component."
>  	"Transparency: The pixel value zero is reserved for transparent. For depths greater than 8, black maps to the darkest possible blue."
> 
>  	| val |
>  	d > 8 "most common case"
>  		ifTrue: 
>  			[d = 32 ifTrue: [
>  				"eight bits per component; top 8 bits set to all ones (opaque alpha)"
> + 				^rgb = 0 ifTrue: [16rFF000001] ifFalse: [rgb bitOr: 16rFF000000]].
> - 				val := (LargePositiveInteger new: 4)
> - 					at: 4 put: 16rFF;
> - 					at: 3 put: ((rgb bitShift: -22) bitAnd: 16rFF);
> - 					at: 2 put: ((rgb bitShift: -12) bitAnd: 16rFF);
> - 					at: 1 put: ((rgb bitShift: -2) bitAnd: 16rFF);
> - 					normalize. "normalize is not necessary as long as SmallInteger maxVal highBit < 32, but let's be future proof"
> - 				^val < 16rFF000001 ifTrue: [16rFF000001] ifFalse: [val]].
>  				
>  			d = 16 ifTrue: [
>  				"five bits per component; top bits ignored"
> + 				val := (((rgb bitShift: -9) bitAnd: 16r7C00) bitOr:
> + 					 ((rgb bitShift: -6) bitAnd: 16r03E0)) bitOr:
> + 					 ((rgb bitShift: -3) bitAnd: 16r001F).
> - 				val := (((rgb bitShift: -15) bitAnd: 16r7C00) bitOr:
> - 					 ((rgb bitShift: -10) bitAnd: 16r03E0)) bitOr:
> - 					 ((rgb bitShift: -5) bitAnd: 16r001F).
>  				^val < 1 ifTrue: [1] ifFalse: [val]].
> 
>  			d = 12 ifTrue: [  "for indexing a color map with 4 bits per color component"
> + 				val := (((rgb bitShift: -12) bitAnd: 16r0F00) bitOr:
> + 					 ((rgb bitShift: -8) bitAnd: 16r00F0)) bitOr:
> + 					 ((rgb bitShift: -4) bitAnd: 16r000F).
> - 				val := (((rgb bitShift: -18) bitAnd: 16r0F00) bitOr:
> - 					 ((rgb bitShift: -12) bitAnd: 16r00F0)) bitOr:
> - 					 ((rgb bitShift: -6) bitAnd: 16r000F).
>  				^val < 1 ifTrue: [1] ifFalse: [val]].
> 
>  			d = 9 ifTrue: [  "for indexing a color map with 3 bits per color component"
> + 				val := (((rgb bitShift: -15) bitAnd: 16r01C0) bitOr:
> + 					 ((rgb bitShift: -10) bitAnd: 16r0038)) bitOr:
> + 					 ((rgb bitShift: -5) bitAnd: 16r0007).
> - 				val := (((rgb bitShift: -21) bitAnd: 16r01C0) bitOr:
> - 					 ((rgb bitShift: -14) bitAnd: 16r0038)) bitOr:
> - 					 ((rgb bitShift: -7) bitAnd: 16r0007).
>  				^val < 1 ifTrue: [1] ifFalse: [val]]].
>  	d = 8 ifTrue: [^ self closestPixelValue8].
>  	d = 4 ifTrue: [^ self closestPixelValue4].
>  	d = 2 ifTrue: [^ self closestPixelValue2]..
>  	d = 1 ifTrue: [^ self closestPixelValue1].
> 
>  	self error: 'unknown pixel depth: ', d printString
>  !
> 
> Item was added:
> + (PackageInfo named: 'Graphics') postscript: '"The cache might hold incorrect values during 10->8 bits per component transition"
> + Color allSubInstancesDo: [:c | c flushCache].'!
> 
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 1665 bytes
Desc: Message signed with OpenPGP using GPGMail
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20140101/af67aa2b/signature.pgp


More information about the Squeak-dev mailing list