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

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Thu Jan 2 14:14:49 UTC 2014


2014/1/1 Tobias Pape <Das.Linux at gmx.de>

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

Thanks for the links Tobias, that's interesting.
Well, no graphics output in Squeak was what I meaned.
Squeak is far from being able to exploit those 10 bits, because it would
require
- BitBlt support with a new format (30 bits depth)
- per device gamma correction
It's also unclear for me how the alpha channel is represented/processed
(pre-processed?)

Do you have plans for such support?

Nicolas


>
> > - 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 --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20140102/03b5d0a8/attachment.htm


More information about the Squeak-dev mailing list