| |
— | pdf:implementingpixmapsupport [2015/03/31 12:45] (current) – created christian |
---|
| ===== Implementing Pixmap support ===== |
| |
| |
| 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: |
| <html> |
| <ul><li> Device colour spaces |
| <ul><li> <b>/DeviceGray</b> |
| </li><li> <b>/DeviceRGB</b> |
| </li><li> <b>/DeviceCMYK</b> |
| </li></ul> |
| </li><li> CIE based colour spaces |
| <ul><li> <b>[/CalGray</b> <i>dictionary</i><b>]</b> |
| </li><li> <b>[/CalRGB</b> <i>dictionary</i><b>]</b> |
| </li><li> <b>[/Lab</b> <i>dictionary</i><b>]</b> |
| </li><li> <b>[/ICCBased</b> <i>stream</i><b>]</b> |
| </li></ul> |
| </li><li> Special colour spaces |
| <ul><li> <b>[Indexed</b> <i>base hival lookup</i><b>]</b> |
| </li><li> <b>/Pattern</b> or <br><b>[/Pattern</b> <i>underlyingColourSpace</i><b>]</b> |
| </li><li> <b>[/Separation</b> <i>name alternateSpace tintTransform</i><b>]</b> |
| </li><li> <b>[/DeviceN</b> <i>names alternateSpace tintTransform</i><b>]</b> or <br><b>[/DeviceN</b> <i>names alternateSpace tintTransform attributes</i><b>]</b> |
| </li></ul> |
| </li></ul> |
| </html> |
| |
| 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: |
| |
| <html> |
| <ul><li> /Name |
| <ul><li> <i><b>/DeviceColourSpace</b></i> |
| <ul><li> <b>/DeviceGray</b> |
| </li><li> <b>/DeviceRGB</b> |
| </li><li> <b>/DeviceCMYK</b> |
| </li></ul> |
| </li><li> <b>/Pattern</b> |
| </li></ul> |
| </li><li> /Array |
| <ul><li> <i><b>/CIEColourSpace</b></i> |
| <ul><li> <b>/CalGray</b> |
| </li><li> <b>/CalRGB</b> |
| </li><li> <b>/Lab</b> |
| </li><li> <b>/ICCBased</b> |
| </li></ul> |
| </li><li> <i><b>/SpecialColourSpace</b></i> |
| <ul><li> <b>/Indexed</b> |
| </li><li> <b>/UncolouredPattern</b> |
| </li><li> <b>/Separation</b> |
| </li><li> <b>/DeviceN</b> |
| </li></ul> |
| </li></ul> |
| </li></ul> |
| </html> |
| |
| Class **/ColourSpace** as new **/TypeClass**. |
| |
| <html> |
| <ul><li> /Entity |
| <ul><li> <b>/TypeClass</b> |
| <ul><li> <b>/ColourSpace</b> |
| </li><li> <i><b>/Function</b></i> |
| </li><li> <i><b>/Shading</b></i> |
| </li></ul> |
| </li></ul> |
| </li></ul> |
| </html> |
| |
| 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: [[Typing]]. |