Submitted by ChristianHaider on Thu, 2011-09-01 10:48

(this is for collecting my thoughts)

I need to implement shadows for a client. The example was created with Illustrator CS5 and has a couple of pixmaps for painting and soft masks (transparency). I have to analyse the pixmaps in order to reconstruct the shadow algorithm of Illustrator (called “Schlagschatten” in Germen; could be “cast shadow” in English).

Therefore, I need to read the pixmaps from the PDF - and being able to write them when I create them. PDF defines Images (/ImageXObject) as rectangular grid of colour values. An image is organized in rows: the first value is the colour in the top left corner with coordinates 1 @ 1. The next value is the next colour in the row right beside the last at 2 @ 1 and so on. The size of the rows is given by the required attribute /Width of /ImageXObject. The number of rows is given with /Height. The colour value in each cell is defined by the /ColorSpace attribute which knows how many components a colour in this space has (f.ex. /DeviceRGB has 3 components, /DeviceCMYK has 4, /Indexed and /DeviceGray 1). The size of one component is given by /BitsPerComponent.

Therefore, I need to implement colour spaces properly, i.e. have a real colour space object after reading. I have defined all colour space classes grouped in Families as Values as placeholders for the real ones when I need them. The objective of this first implementation was to have /DeviceCMYK and /DeviceGray colour space objects which know how to set the stroking and filling colours in a renderer. Now I have to do this right.

Unfortunately, colour space types dont follow the Smalltalk class hierarchy very well. The current implementation has two hierarchies: for Values and for Objects. Dictionary is defined as Object and serves as super class for most PDF objects. Especially Stream is a Dictionary which is super class to many PDF objects. So far, the Smalltalk hierarchy worked well except for two monsters: /Function and /Shading. There are 4 types of /Function where 2 are Dictionaries and 2 are Streams. /Shading has 7 types with 3 Dictionaries and 4 Streams. I got away with that by defining the attributes for both subhierarchies. F.ex. a /Function attribute would have

  <type: #FunctionDictionary>
  <type: #FunctionStream>

This is clearly not as good as saying

  <type: #Function>. 

With colour spaces this is even worse, because they can be Names or Arrays:

  • Device colour spaces
    • /DeviceGray
    • /DeviceRGB
    • /DeviceCMYK
  • CIE based colour spaces
    • [/CalGray dictionary]
    • [/CalRGB dictionary]
    • [/Lab dictionary]
    • [/ICCBased stream]
  • Special colour spaces
    • [Indexed base hival lookup]
    • /Pattern or
      [/Pattern underlyingColourSpace]
    • [/Separation name alternateSpace tintTransform]
    • [/DeviceN names alternateSpace tintTransform] or
      [/DeviceN names alternateSpace tintTransform attributes]

I will try the following implementation strategy: define the colour spaces as subclasses of /Name and /Array and add the abstract class /ColourSpace. Then the typing must be extended so that all the colour space classes scattered around the implementation hierarchy are recognized as being of type class /ColourSpace.

The implementation hierarchy of colour spaces:

  • /Name
    • /DeviceColourSpace
      • /DeviceGray
      • /DeviceRGB
      • /DeviceCMYK
    • /Pattern
  • /Array
    • /CIEColourSpace
      • /CalGray
      • /CalRGB
      • /Lab
      • /ICCBased
    • /SpecialColourSpace
      • /Indexed
      • /UncolouredPattern
      • /Separation
      • /DeviceN

Class /ColourSpace as new /TypeClass.

  • /Entity
    • /TypeClass
      • /ColourSpace
      • /Function
      • /Shading

A /TypeClass should not be instantiated, but serve as dispatcher for the type machinery.

Now I need tests to see how this should look like in code…

Lets see - I'll write a doc page for this: PDF Object Types.

  • implementingpixmapsupport.txt
  • Last modified: 2016/09/28 00:11
  • by 93.204.170.156