[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
|