ImageEditor.st
changeset 919 4e50c3164625
parent 917 43e80afe8222
child 920 bde5b9369ef8
equal deleted inserted replaced
918:1172ecb3fd63 919:4e50c3164625
   786                     ) nil
   786                     ) nil
   787                     nil
   787                     nil
   788                 )
   788                 )
   789             )
   789             )
   790              #(#MenuItem
   790              #(#MenuItem
   791                 #label: 'Color Map'
   791                 #label: 'ColorMap'
   792                 #translateLabel: true
   792                 #translateLabel: true
   793                 #activeHelpKey: #colorMap
   793                 #activeHelpKey: #colorMap
   794                 #enabled: #imageIsLoaded
   794                 #enabled: #imageIsLoaded
   795                 #submenu: 
   795                 #submenu: 
   796                  #(#Menu
   796                  #(#Menu
   853                           #translateLabel: true
   853                           #translateLabel: true
   854                           #activeHelpKey: #colorMap
   854                           #activeHelpKey: #colorMap
   855                           #argument: '1-plane + mask'
   855                           #argument: '1-plane + mask'
   856                           #indication: #colorMapMode:value:
   856                           #indication: #colorMapMode:value:
   857                       )
   857                       )
       
   858                        #(#MenuItem
       
   859                           #label: '-'
       
   860                       )
       
   861                        #(#MenuItem
       
   862                           #label: 'Compress colormap'
       
   863                           #translateLabel: true
       
   864                           #value: #compressColorMap
       
   865                       )
   858                     ) nil
   866                     ) nil
   859                     nil
   867                     nil
   860                 )
   868                 )
   861             )
   869             )
   862              #(#MenuItem
   870              #(#MenuItem
   898                 #submenuChannel: #menuHelp
   906                 #submenuChannel: #menuHelp
   899             )
   907             )
   900           ) nil
   908           ) nil
   901           nil
   909           nil
   902       )
   910       )
       
   911 
       
   912     "Modified: / 28.7.1998 / 20:03:52 / cg"
   903 !
   913 !
   904 
   914 
   905 menuMouseButtonColors
   915 menuMouseButtonColors
   906     "This resource specification was automatically generated
   916     "This resource specification was automatically generated
   907      by the MenuEditor of ST/X."
   917      by the MenuEditor of ST/X."
  1346     "returns whether colorMapMode is equal to aMode"
  1356     "returns whether colorMapMode is equal to aMode"
  1347 
  1357 
  1348     ^colorMapMode = aMode
  1358     ^colorMapMode = aMode
  1349 !
  1359 !
  1350 
  1360 
  1351 colorMapMode: aMode value: aValue
       
  1352     "calculates a new color map for the image from aMode"
       
  1353 
       
  1354     |depth newColorMap newImage image newColors realColorMap oldFileName| 
       
  1355 
       
  1356     imageEditView makeUndo.
       
  1357 
       
  1358     newColorMap := self class listOfColorMaps at: aMode.
       
  1359     depth       := (newColorMap size log: 2) asInteger. 
       
  1360     newImage    := (Image implementorForDepth: depth) new.  
       
  1361     oldFileName := self image fileName.
       
  1362 
       
  1363     Object errorSignal handle:
       
  1364     [:ex|
       
  1365         Object errorSignal handle:
       
  1366         [:ex|
       
  1367             imageEditView undo.
       
  1368             ^self warn: 'Convertation failed!!'
       
  1369         ]
       
  1370         do:
       
  1371         [
       
  1372             self image colorsFromX:0 y:0 toX:(self image width-1) y:(self image height-1) do:
       
  1373             [:x :y :clr |
       
  1374                 (newColorMap includes: clr)
       
  1375                     ifTrue: [self image colorAtX:x y:y put:clr]
       
  1376                     ifFalse: [self image colorAtX:x y:y put: self image colorMap first]
       
  1377             ].
       
  1378             image := newImage fromImage: self image.
       
  1379         ].
       
  1380     ] 
       
  1381     do:
       
  1382     [ 
       
  1383         image := newImage fromImage: self image
       
  1384     ].
       
  1385 
       
  1386     (String fromString: aMode) reverse readStream nextWord reverse = 'mask'
       
  1387     ifTrue:
       
  1388     [
       
  1389         image mask isNil
       
  1390         ifTrue:
       
  1391         [
       
  1392             image mask: (Depth1Image fromImage: (image asThresholdMonochromeImage: 0.1)). 
       
  1393         ].
       
  1394     ]
       
  1395     ifFalse:
       
  1396     [ 
       
  1397         image mask: nil.
       
  1398     ]. 
       
  1399     realColorMap := OrderedCollection new.
       
  1400     image realColorMap do:
       
  1401     [:clr|
       
  1402         (realColorMap includes: clr) ifFalse: [realColorMap add: clr]
       
  1403     ].
       
  1404     newColors := realColorMap copyFrom: 1 to: (newColorMap size min: realColorMap size).
       
  1405     newColorMap do:
       
  1406     [:clr|
       
  1407         ((newColors size < newColorMap size) and: [(newColors includes: clr) not]) 
       
  1408         ifTrue:
       
  1409         [      
       
  1410             newColors add: clr
       
  1411         ]
       
  1412     ].                  
       
  1413     image colorMap: newColors.
       
  1414     colorMapMode := aMode.            
       
  1415     (imageEditView image: image) notNil
       
  1416     ifTrue:
       
  1417     [
       
  1418         self image fileName: oldFileName.
       
  1419         self listOfColors contents: image colorMap.
       
  1420         self findColorMapMode.
       
  1421         self updateLabelsAndHistory.
       
  1422     ]
       
  1423 !
       
  1424 
       
  1425 editMode: aMode
  1361 editMode: aMode
  1426     "returns whether editMode is equal to aMode"
  1362     "returns whether editMode is equal to aMode"
  1427 
  1363 
  1428     ^imageEditView editMode = aMode
  1364     ^imageEditView editMode = aMode
  1429 !
  1365 !
  1516     postOpenAction notNil ifTrue: [postOpenAction value].
  1452     postOpenAction notNil ifTrue: [postOpenAction value].
  1517 
  1453 
  1518     super postOpenWith:aBuilder
  1454     super postOpenWith:aBuilder
  1519 
  1455 
  1520     "Modified: / 26.7.1998 / 12:32:55 / cg"
  1456     "Modified: / 26.7.1998 / 12:32:55 / cg"
       
  1457 ! !
       
  1458 
       
  1459 !ImageEditor methodsFor:'user actions - colormap'!
       
  1460 
       
  1461 colorMapMode:aMode value: aValue
       
  1462     "calculates a new color map for the image from aMode"
       
  1463 
       
  1464     |depth numColors newColorMap newImage 
       
  1465      oldImage image newColors realColorMap oldFileName
       
  1466      usedColors useNearest usageCounts tmpBits tmpMap| 
       
  1467 
       
  1468     self withExecuteCursorDo:[
       
  1469         oldImage := self image.
       
  1470 
       
  1471         newColorMap := self class listOfColorMaps at:aMode.
       
  1472         depth       := (newColorMap size log: 2) asInteger. 
       
  1473 
       
  1474         useNearest := false.
       
  1475         (self confirm:'Keep colormap (or use standard)') ifTrue:[
       
  1476             "/ keep the colormap
       
  1477             depth > oldImage depth ifTrue:[
       
  1478                 "/ easy - simply copy the part
       
  1479                 numColors := 1 bitShift:oldImage depth.
       
  1480                 0 to:numColors-1 do:[:pixel |
       
  1481                     newColorMap at:(pixel+1) put:(oldImage colorFromValue:pixel)
       
  1482                 ].
       
  1483             ] ifFalse:[
       
  1484                 "/ see if all used color fit the new colormap
       
  1485                 usedColors := oldImage usedColors.
       
  1486                 usedColors := usedColors asArray.
       
  1487                 usedColors size <= (1 bitShift:depth) ifTrue:[
       
  1488                     "/ yea - just install them
       
  1489                     usedColors keysAndValuesDo:[:idx :clr |
       
  1490                         newColorMap at:idx put:clr
       
  1491                     ]
       
  1492                 ] ifFalse:[
       
  1493                     "/ copy over those that are most often used.
       
  1494                     oldImage depth ~~ 8 ifTrue:[
       
  1495                         tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
       
  1496                         oldImage bits
       
  1497                             expandPixels:(oldImage depth)
       
  1498                             width:oldImage width
       
  1499                             height:oldImage height 
       
  1500                             into:tmpBits
       
  1501                             mapping:nil.
       
  1502                     ] ifFalse:[
       
  1503                         tmpBits := oldImage bits
       
  1504                     ].
       
  1505                     usageCounts := tmpBits usageCounts.
       
  1506                     tmpMap := Array new:usageCounts size.
       
  1507                     oldImage colorMap asArray keysAndValuesDo:[:i :clr |
       
  1508                         tmpMap at:i put:clr
       
  1509                     ].
       
  1510                     usageCounts sort:[:a :b | a > b] with:tmpMap.
       
  1511 
       
  1512                     1 to:(1 bitShift:depth) do:[:idx |
       
  1513                         newColorMap at:idx put:(tmpMap at:idx)
       
  1514                     ].
       
  1515 
       
  1516                     useNearest := Dialog 
       
  1517                                         confirmWithCancel:('Image requires %1 colors.\ColorMap has only space for %2\\Use nearest (or map to black) ?'
       
  1518                                                            bindWith:usedColors size
       
  1519                                                            with:(1 bitShift:depth)) withCRs
       
  1520                                         labels:#('cancel' 'black' 'nearest').
       
  1521                     useNearest isNil ifTrue:[
       
  1522                         ^ self   "/ cancel
       
  1523                     ].
       
  1524                 ]
       
  1525             ]
       
  1526         ] ifFalse:[
       
  1527             "/ standard colormap
       
  1528         ].
       
  1529 
       
  1530         imageEditView makeUndo.
       
  1531 
       
  1532         newImage    := (Image implementorForDepth: depth) new.  
       
  1533         oldFileName := oldImage fileName.
       
  1534 
       
  1535         Object errorSignal handle:
       
  1536         [:ex|
       
  1537             Object errorSignal handle:
       
  1538             [:ex|
       
  1539                 imageEditView undo.
       
  1540                 ^self warn: 'Conversion failed!!'
       
  1541             ]
       
  1542             do:
       
  1543             [
       
  1544                 newImage := (Image implementorForDepth: depth) new.
       
  1545                 newImage width:oldImage width height:oldImage height depth:depth.
       
  1546                 newImage colorMap:newColorMap.
       
  1547                 newImage photometric:#palette.
       
  1548                 newImage bits:(ByteArray new:(newImage bytesPerRow * newImage height)).
       
  1549             
       
  1550                 oldImage colorsFromX:0 y:0 toX:(oldImage width-1) y:(oldImage height-1) do:
       
  1551                 [:x :y :clr |
       
  1552                     |newColor|
       
  1553 
       
  1554                     (newColorMap includes:clr)
       
  1555                         ifTrue: [newColor := clr]
       
  1556                         ifFalse: [
       
  1557                             useNearest ifTrue:[
       
  1558                                 newColor := clr nearestIn:newColorMap
       
  1559                             ] ifFalse:[
       
  1560                                 newColor := oldImage colorMap first
       
  1561                             ]
       
  1562                         ].
       
  1563                     newImage colorAtX:x y:y put:newColor.
       
  1564                 ].
       
  1565                 image := newImage
       
  1566             ].
       
  1567         ] 
       
  1568         do:
       
  1569         [ 
       
  1570             image := newImage fromImage: oldImage
       
  1571         ].
       
  1572 
       
  1573         (String fromString: aMode) reverse readStream nextWord reverse = 'mask'
       
  1574         ifTrue:
       
  1575         [
       
  1576             image mask isNil
       
  1577             ifTrue:
       
  1578             [
       
  1579                 image mask: (Depth1Image fromImage: (image asThresholdMonochromeImage: 0.1)). 
       
  1580             ].
       
  1581         ]
       
  1582         ifFalse:
       
  1583         [ 
       
  1584             image mask: nil.
       
  1585         ]. 
       
  1586         realColorMap := OrderedCollection new.
       
  1587         image realColorMap do:
       
  1588         [:clr|
       
  1589             (realColorMap includes: clr) ifFalse: [realColorMap add: clr]
       
  1590         ].
       
  1591         newColors := realColorMap copyFrom: 1 to: (newColorMap size min: realColorMap size).
       
  1592         newColorMap do:
       
  1593         [:clr|
       
  1594             ((newColors size < newColorMap size) and: [(newColors includes: clr) not]) 
       
  1595             ifTrue:
       
  1596             [      
       
  1597                 newColors add: clr
       
  1598             ]
       
  1599         ].                  
       
  1600         image colorMap: newColors.
       
  1601         colorMapMode := aMode.            
       
  1602 
       
  1603         (imageEditView image: image) notNil ifTrue:
       
  1604         [
       
  1605             image fileName: oldFileName.
       
  1606             self listOfColors contents: image colorMap.
       
  1607             self findColorMapMode.
       
  1608             self updateLabelsAndHistory.
       
  1609         ]
       
  1610     ]
       
  1611 
       
  1612     "Modified: / 28.7.1998 / 21:42:14 / cg"
       
  1613 !
       
  1614 
       
  1615 compressColorMap
       
  1616     "calculates a new color map for the image, using only used colors"
       
  1617 
       
  1618     |depth numColors newColorMap newImage 
       
  1619      oldImage  newColors realColorMap oldFileName
       
  1620      usedColors useNearest oldToNew oldBits newBits tmpBits| 
       
  1621 
       
  1622     oldImage := self image.
       
  1623     depth := oldImage depth.
       
  1624 
       
  1625     oldImage photometric ~~ #palette ifTrue:[
       
  1626         self information:'Only palette images have colormaps.'.
       
  1627         ^ self
       
  1628     ].
       
  1629 
       
  1630     usedColors := oldImage usedColors.
       
  1631     usedColors size == (1 bitShift:depth) ifTrue:[
       
  1632         self information:'All colors are used - no compression.'.
       
  1633         ^ self
       
  1634     ].
       
  1635     usedColors size == oldImage colorMap size ifTrue:[
       
  1636         self information:'Colormap already compressed - no compression.'.
       
  1637         ^ self
       
  1638     ].
       
  1639 
       
  1640     imageEditView makeUndo.
       
  1641 
       
  1642     self information:('%1 colors used.' bindWith:usedColors size).
       
  1643 
       
  1644     self withExecuteCursorDo:[
       
  1645         newColorMap := Array new:usedColors size.
       
  1646 
       
  1647         "/ translation table
       
  1648         oldToNew := ByteArray new:(1 bitShift:depth).
       
  1649         newColorMap := usedColors asArray.
       
  1650         oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
       
  1651             |newPixel|
       
  1652 
       
  1653             (usedColors includes:clr) ifTrue:[
       
  1654                 newPixel := newColorMap indexOf:clr.
       
  1655                 oldToNew at:oldIdx put:newPixel-1.
       
  1656             ]
       
  1657         ].
       
  1658 
       
  1659         oldBits := oldImage bits.
       
  1660         newBits := ByteArray new:(oldBits size).
       
  1661         depth ~~ 8 ifTrue:[
       
  1662             "/ expand/compress can only handle 8bits
       
  1663             tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
       
  1664             oldBits
       
  1665                 expandPixels:depth
       
  1666                 width:oldImage width
       
  1667                 height:oldImage height 
       
  1668                 into:tmpBits
       
  1669                 mapping:oldToNew.
       
  1670             tmpBits
       
  1671                 compressPixels:depth 
       
  1672                 width:oldImage width 
       
  1673                 height:oldImage height 
       
  1674                 into:newBits 
       
  1675                 mapping:nil
       
  1676         ] ifFalse:[
       
  1677             oldBits
       
  1678                 expandPixels:depth
       
  1679                 width:oldImage width
       
  1680                 height:oldImage height 
       
  1681                 into:newBits
       
  1682                 mapping:oldToNew.
       
  1683         ].
       
  1684 
       
  1685         newImage := oldImage species new
       
  1686                         width:oldImage width
       
  1687                         height:oldImage height
       
  1688                         depth:depth
       
  1689                         fromArray:newBits.
       
  1690 
       
  1691         newImage colorMap:newColorMap.  
       
  1692         newImage fileName:oldImage fileName.
       
  1693         newImage mask:(oldImage mask copy).
       
  1694 
       
  1695         (imageEditView image:newImage) notNil ifTrue:
       
  1696         [
       
  1697             self listOfColors contents: newImage colorMap.
       
  1698             self findColorMapMode.
       
  1699             self updateLabelsAndHistory.
       
  1700         ]
       
  1701     ]
       
  1702 
       
  1703     "Created: / 28.7.1998 / 20:03:11 / cg"
       
  1704     "Modified: / 28.7.1998 / 21:36:17 / cg"
  1521 ! !
  1705 ! !
  1522 
  1706 
  1523 !ImageEditor methodsFor:'user actions - editing'!
  1707 !ImageEditor methodsFor:'user actions - editing'!
  1524 
  1708 
  1525 doBrowseClass
  1709 doBrowseClass