GIFReader.st
changeset 1 6fe019b6ea79
parent 0 3f9277473954
child 5 4d55b551dc57
equal deleted inserted replaced
0:3f9277473954 1:6fe019b6ea79
    50       CompuServe Incorporated. GIF(sm) is a Service Mark property of
    50       CompuServe Incorporated. GIF(sm) is a Service Mark property of
    51       CompuServe Incorporated.
    51       CompuServe Incorporated.
    52 "
    52 "
    53 ! !
    53 ! !
    54 
    54 
       
    55 !GIFReader class methodsFor:'testing'!
       
    56 
       
    57 isValidImageFile:aFileName
       
    58     "return true, if aFileName contains a GIF image"
       
    59 
       
    60     |id inStream|
       
    61 
       
    62     inStream := FileStream readonlyFileNamed:aFileName.
       
    63     inStream isNil ifTrue:[^ false].
       
    64 
       
    65     id := String new:6.
       
    66     inStream nextBytes:6 into:id.
       
    67     inStream close.
       
    68 
       
    69     (id = 'GIF87a') ifFalse:[
       
    70         (id startsWith:'GIF') ifFalse:[^ false].
       
    71 
       
    72         'not GIF87a - untested' printNewline.
       
    73     ].
       
    74     ^ true
       
    75 ! !
       
    76 
    55 !GIFReader methodsFor:'reading from file'!
    77 !GIFReader methodsFor:'reading from file'!
    56 
    78 
    57 fromFile:aFileName
    79 fromFile:aFileName
    58     "read a GIF file"
    80     "read a GIF file"
    59 
    81 
    60     |byte index 
    82     |byte index flag count
    61      colorMapSize bitsPerPixel scrWidth scrHeight
    83      colorMapSize bitsPerPixel scrWidth scrHeight
    62      hasColorMap hasLocalColorMap interlaced id
    84      hasColorMap hasLocalColorMap interlaced id
    63      leftOffs topOffs codeLen
    85      leftOffs topOffs codeLen
    64      compressedData compressedSize
    86      compressedData compressedSize
    65      tmp srcOffset dstOffset|
    87      tmp srcOffset dstOffset|
    68     inStream isNil ifTrue:[
    90     inStream isNil ifTrue:[
    69         'open error' printNewline. 
    91         'open error' printNewline. 
    70         ^ nil
    92         ^ nil
    71     ].
    93     ].
    72 
    94 
       
    95     inStream binary.
       
    96 
       
    97     "GIF-files are always lsb (intel-world)"
    73     byteOrder := #lsb.
    98     byteOrder := #lsb.
    74 
    99 
    75     id := String new:6.
   100     id := String new:6.
    76     inStream nextBytes:6 into:id.
   101     inStream nextBytes:6 into:id.
    77 
   102 
    87         'not a gif87a file - hope that works' printNewline.
   112         'not a gif87a file - hope that works' printNewline.
    88     ].
   113     ].
    89 
   114 
    90     "get screen dimensions (not used)"
   115     "get screen dimensions (not used)"
    91 
   116 
    92     scrWidth := self readShort.
   117     scrWidth := inStream nextShortMSB:false.
    93     scrHeight := self readShort.
   118     scrHeight := inStream nextShortMSB:false.
    94 
   119 
    95     "get flag byte"
   120     "get flag byte"
    96     byte := inStream nextByte.
   121     flag := inStream nextByte.
    97     hasColorMap :=      (byte bitAnd:2r10000000) ~~ 0.
   122     hasColorMap :=      (flag bitAnd:2r10000000) ~~ 0.
    98     "bitsPerRGB :=     ((byte bitAnd:2r01110000) bitShift:-4) + 1. "
   123     "bitsPerRGB :=     ((flag bitAnd:2r01110000) bitShift:-4) + 1. "
    99     "colorMapSorted := ((byte bitAnd:2r00001000) ~~ 0.             "
   124     "colorMapSorted := ((flag bitAnd:2r00001000) ~~ 0.             "
   100     bitsPerPixel :=     (byte bitAnd:2r00000111) + 1.
   125     bitsPerPixel :=     (flag bitAnd:2r00000111) + 1.
   101     colorMapSize := 1 bitShift:bitsPerPixel.
   126     colorMapSize := 1 bitShift:bitsPerPixel.
   102 
   127 
   103     "get background (not used)"
   128     "get background (not used)"
   104     byte := inStream nextByte.
   129     inStream nextByte.
   105 
   130 
   106     "aspect ratio"
   131     "aspect ratio (not used)"
   107     byte := inStream nextByte.
   132     inStream nextByte.
   108 
   133 
   109     "get colorMap"
   134     "get colorMap"
   110     hasColorMap ifTrue:[
   135     hasColorMap ifTrue:[
   111         self readColorMap:colorMapSize
   136         self readColorMap:colorMapSize
   112     ].
   137     ].
   117         'corrupted gif file (no imgSep)' printNewline.
   142         'corrupted gif file (no imgSep)' printNewline.
   118         ^ nil
   143         ^ nil
   119     ].
   144     ].
   120 
   145 
   121     "get image data"
   146     "get image data"
   122     leftOffs := self readShort.
   147     leftOffs := inStream nextShortMSB:false.
   123     topOffs := self readShort.
   148     topOffs := inStream nextShortMSB:false.
   124     width := self readShort.
   149     width := inStream nextShortMSB:false.
   125     height := self readShort.
   150     height := inStream nextShortMSB:false.
   126 
   151 
   127 'width ' print. width printNewline.
   152 'width ' print. width printNewline.
   128 'height ' print. height printNewline.
   153 'height ' print. height printNewline.
   129 
   154 
   130     byte := inStream nextByte.
   155     "another flag byte"
   131     interlaced :=           (byte bitAnd:2r01000000) ~~ 0.
   156     flag := inStream nextByte.
   132     hasLocalColorMap :=     (byte bitAnd:2r10000000) ~~ 0.
   157     interlaced :=           (flag bitAnd:2r01000000) ~~ 0.
   133     "localColorMapSorted := (byte bitAnd:2r00100000) ~~ 0.      "
   158     hasLocalColorMap :=     (flag bitAnd:2r10000000) ~~ 0.
       
   159     "localColorMapSorted := (flag bitAnd:2r00100000) ~~ 0.      "
       
   160 
       
   161     "if image has a local colormap, this one is used"
   134 
   162 
   135     hasLocalColorMap ifTrue:[
   163     hasLocalColorMap ifTrue:[
   136         "local descr. overwrites"
   164         "local descr. overwrites"
   137         bitsPerPixel := (byte bitAnd:2r00000111) + 1.
   165         bitsPerPixel := (flag bitAnd:2r00000111) + 1.
   138         colorMapSize := 1 bitShift:bitsPerPixel.
   166         colorMapSize := 1 bitShift:bitsPerPixel.
   139 " 'local colormap' printNewline. "
   167 " 'local colormap' printNewline. "
   140         "overwrite colormap"
   168         "overwrite colormap"
   141         self readColorMap:colorMapSize
   169         self readColorMap:colorMapSize
   142     ].
   170     ].
   143 
   171 
       
   172     "get codelen for decompression"
   144     codeLen := inStream nextByte.
   173     codeLen := inStream nextByte.
   145 
   174 
   146     compressedData := ByteArray uninitializedNew:(inStream size).
   175     compressedData := ByteArray uninitializedNew:(inStream size).
   147 
   176 
       
   177     "get compressed data"
   148     index := 1.
   178     index := 1.
   149     byte := inStream nextByte.
   179     count := inStream nextByte.
   150     [byte notNil and:[byte ~~ 0]] whileTrue:[
   180     [count notNil and:[count ~~ 0]] whileTrue:[
   151         inStream nextBytes:byte into:compressedData startingAt:index.
   181         inStream nextBytes:count into:compressedData startingAt:index.
   152         index := index + byte.
   182         index := index + count.
   153         byte := inStream nextByte
   183         count := inStream nextByte
   154     ].
   184     ].
   155     compressedSize := index - 1.
   185     compressedSize := index - 1.
   156     inStream close.
   186     inStream close.
   157 
   187 
   158     data := ByteArray uninitializedNew:((width + 1) * (height + 1)).
   188     data := ByteArray uninitializedNew:((width + 1) * (height + 1)).
   163                             into:data
   193                             into:data
   164                       startingAt:1
   194                       startingAt:1
   165                          codeLen:(codeLen + 1).
   195                          codeLen:(codeLen + 1).
   166 
   196 
   167     interlaced ifTrue:[
   197     interlaced ifTrue:[
       
   198         Transcript showCr:'deinterlacing'.
   168         tmp := ByteArray uninitializedNew:(data size).
   199         tmp := ByteArray uninitializedNew:(data size).
   169 
   200 
   170         "phase 1: 0, 8, 16, 24, ..."
   201         "phase 1: 0, 8, 16, 24, ..."
   171 
   202 
   172         srcOffset := 1.
   203         srcOffset := 1.
   209     ].
   240     ].
   210 
   241 
   211     photometric := #palette.
   242     photometric := #palette.
   212     samplesPerPixel := 1.
   243     samplesPerPixel := 1.
   213     bitsPerSample := #(8).
   244     bitsPerSample := #(8).
       
   245 
       
   246     "check if only grey values are used,
       
   247      could make it a greyscale image if so (currently not done)"
       
   248 
       
   249     self checkGreyscaleColormap ifTrue:[
       
   250         self makeGreyscale
       
   251     ].
       
   252         
   214     colorMap := Array with:redMap with:greenMap with:blueMap.
   253     colorMap := Array with:redMap with:greenMap with:blueMap.
   215 
   254 
   216     "GIFReader fromFile:'../fileIn/bitmaps/claus.gif"
   255     "GIFReader fromFile:'../fileIn/bitmaps/claus.gif"
   217     "GIFReader fromFile:'../fileIn/bitmaps/garfield.gif'"
   256     "GIFReader fromFile:'../fileIn/bitmaps/garfield.gif'"
   218 !
   257 !
   219 
   258 
   220 readColorMap:colorMapSize
   259 readColorMap:colorMapSize
   221         redMap := Array new:colorMapSize.
   260     "get gif colormap consisting of colorMapSize entries"
   222         greenMap := Array new:colorMapSize.
   261 
   223         blueMap := Array new:colorMapSize.
   262     redMap := Array new:colorMapSize.
   224         1 to:colorMapSize do:[:i |
   263     greenMap := Array new:colorMapSize.
   225             redMap at:i put:(inStream nextByte).
   264     blueMap := Array new:colorMapSize.
   226             greenMap at:i put:(inStream nextByte).
   265     1 to:colorMapSize do:[:i |
   227             blueMap at:i put:(inStream nextByte)
   266         redMap at:i put:(inStream nextByte).
   228         ]
   267         greenMap at:i put:(inStream nextByte).
       
   268         blueMap at:i put:(inStream nextByte)
       
   269     ]
       
   270 !
       
   271 
       
   272 checkGreyscaleColormap
       
   273     "return true, if colormap is really a greymap"
       
   274 
       
   275     1 to:redMap size do:[:i |
       
   276         (redMap at:i) ~~ (greenMap at:i) ifTrue:[^ false].
       
   277         (redMap at:i) ~~ (blueMap at:i) ifTrue:[^ false].
       
   278     ].
       
   279     ^ true
       
   280 !
       
   281 
       
   282 makeGreyscale
       
   283     "not yet implemented/needed"
   229 ! !
   284 ! !