301 "Modified: / 31.10.1997 / 16:19:23 / cg" |
75 "Modified: / 31.10.1997 / 16:19:23 / cg" |
302 ! ! |
76 ! ! |
303 |
77 |
304 !ImageEditView methodsFor:'accessing'! |
78 !ImageEditView methodsFor:'accessing'! |
305 |
79 |
|
80 coordInfoBlock: aBlock |
|
81 |
|
82 coordInfoBlock := aBlock |
|
83 ! |
|
84 |
|
85 gridMagnification: aPoint |
|
86 |
|
87 gridMagnification := aPoint |
|
88 ! |
|
89 |
|
90 imageReaderClass |
|
91 |
|
92 ^imageReaderClass |
|
93 ! |
|
94 |
|
95 magnification |
|
96 |
|
97 ^magnification |
|
98 |
|
99 ! |
|
100 |
|
101 magnification:aPoint |
|
102 |
|
103 magnification ~= aPoint |
|
104 ifTrue: |
|
105 [ |
|
106 magnification := aPoint asPoint. |
|
107 self scrollToTopLeft. |
|
108 self contentsChanged. |
|
109 self invalidate. |
|
110 ]. |
|
111 ! |
|
112 |
|
113 resourceClass |
|
114 |
|
115 ^resourceClass |
|
116 ! |
|
117 |
|
118 resourceClass: aClassOrSymbol |
|
119 |
|
120 resourceClass := aClassOrSymbol isClass ifTrue: [aClassOrSymbol name] ifFalse: [aClassOrSymbol asSymbol]. |
|
121 |
|
122 ! |
|
123 |
|
124 resourceMessage |
|
125 |
|
126 ^resourceClass, ' ', resourceSelector |
|
127 ! |
|
128 |
|
129 resourceMessage: aMessage |
|
130 |
|
131 (aMessage notNil and: [aMessage trimBlanks size > 0]) |
|
132 ifTrue: |
|
133 [ |
|
134 resourceClass := aMessage readStream nextWord asSymbol. |
|
135 resourceSelector := aMessage reversed readStream nextWord reverse asSymbol. |
|
136 ] |
|
137 ifFalse: |
|
138 [ |
|
139 ^nil |
|
140 ]. |
|
141 |
|
142 ^self resourceClass: resourceClass selector: resourceSelector |
|
143 |
|
144 |
|
145 ! |
|
146 |
|
147 resourceSelector |
|
148 |
|
149 ^resourceSelector |
|
150 ! |
|
151 |
|
152 resourceSelector: aStringOrSymbol |
|
153 |
|
154 resourceSelector := aStringOrSymbol asSymbol |
|
155 ! |
|
156 |
|
157 selectedColor |
|
158 |
|
159 ^selectColors at: mouseKeyColorMode |
|
160 ! |
|
161 |
|
162 selectedColor: aColor |
|
163 |
|
164 selectColors at: mouseKeyColorMode put: aColor |
|
165 ! ! |
|
166 |
|
167 !ImageEditView methodsFor:'accessing menu'! |
|
168 |
|
169 menuEdit |
|
170 "this window spec was automatically generated by the UI Builder" |
|
171 |
|
172 ^ self class menuEdit |
|
173 |
|
174 |
|
175 ! ! |
|
176 |
|
177 !ImageEditView methodsFor:'drawing'! |
|
178 |
|
179 redrawImageX:x y:y width:w height:h |
|
180 |ih iw dotW dotH minX maxX minY maxY color last lastY runW x0 xI yI maskColor| |
|
181 |
|
182 ih := image height. |
|
183 iw := image width. |
|
184 dotW := magnification x. |
|
185 dotH := magnification y. |
|
186 |
|
187 minX := (x // dotW). |
|
188 minX >= iw ifTrue:[minX := iw - 1]. |
|
189 minY := (y // dotH). |
|
190 minY >= ih ifTrue:[minY := ih - 1]. |
|
191 maxX := (x + w) // dotW + 1. |
|
192 maxX > iw ifTrue:[maxX := iw]. |
|
193 maxY := (y + h) // dotH + 1. |
|
194 maxY > ih ifTrue:[maxY := ih]. |
|
195 |
|
196 lastY := -1. |
|
197 |
|
198 x0 := minX. |
|
199 runW := 0. |
|
200 maskColor := false. |
|
201 image colorsFromX:minX y:minY toX:maxX-1 y:maxY-1 do: |
|
202 [:xx :yy :color| |
|
203 |
|
204 yy ~~ lastY ifTrue: |
|
205 [ |
|
206 runW ~~ 0 ifTrue: |
|
207 [ |
|
208 |origin| |
|
209 origin := (x0 * dotW + margin)@(lastY * dotH + margin). |
|
210 self fillRectangle: (origin extent: (runW@dotH)). |
|
211 0 to: runW by: dotW do: [:xxx| self drawFrameAt: ((origin x + xxx) @origin y)]. |
|
212 maskColor ifTrue: |
|
213 [ |
|
214 self drawMaskPointAt: origin |
|
215 ]. |
|
216 runW := 0. |
|
217 ]. |
|
218 x0 := xx. |
|
219 lastY := yy. |
|
220 ]. |
|
221 |
|
222 color ~~ last ifTrue: |
|
223 [ |
|
224 runW ~~ 0 ifTrue: |
|
225 [ |
|
226 |origin| |
|
227 origin := (x0 * dotW + margin)@(yy * dotH + margin). |
|
228 self fillRectangle: (origin extent: (runW@dotH)). |
|
229 0 to: runW by: dotW do: [:xxx| self drawFrameAt: ((origin x + xxx) @origin y)]. |
|
230 maskColor ifTrue: |
|
231 [ |
|
232 self drawMaskPointAt: origin |
|
233 ]. |
|
234 runW := 0. |
|
235 ]. |
|
236 |
|
237 self paint: (last := color). |
|
238 image mask notNil ifTrue: |
|
239 [ |
|
240 maskColor := false. |
|
241 (image mask colorAt: xx@yy) = Color black ifTrue: |
|
242 [ |
|
243 self paint: (last := self viewBackground). |
|
244 maskColor := true. |
|
245 ]. |
|
246 last := nil. |
|
247 ]. |
|
248 runW := 0. |
|
249 x0 := xx. |
|
250 ]. |
|
251 runW := runW + dotW |
|
252 ]. |
|
253 runW ~~ 0 ifTrue: |
|
254 [ |
|
255 |origin| |
|
256 origin := (x0 * dotW + margin)@(lastY * dotH + margin). |
|
257 self fillRectangle: (origin extent: runW@dotH). |
|
258 0 to: runW by: dotW do: [:xxx| self drawFrameAt: ((origin x + xxx) @origin y)]. |
|
259 maskColor ifTrue: |
|
260 [ |
|
261 self drawMaskPointAt: origin. |
|
262 ]. |
|
263 runW := 0. |
|
264 ]. |
|
265 ! |
|
266 |
|
267 redrawX:x y:y width:w height:h |
|
268 |ih iw xI yI| |
|
269 |
|
270 image isNil ifTrue:[^self]. |
|
271 |
|
272 magnification = (1@1) ifTrue: |
|
273 [ |
|
274 super redrawX:x y:y width:w height:h. |
|
275 self drawFrame. |
|
276 ^ self |
|
277 ]. |
|
278 self clippingRectangle: (x@y extent: w@h). |
|
279 |
|
280 self redrawImageX:x y:y width:w height:h. |
|
281 |
|
282 "/ right of image ? |
|
283 adjust == #center ifTrue: |
|
284 [ |
|
285 xI := (width - (margin * 2) - ih) // 2. |
|
286 yI := (height - (margin * 2) - iw) // 2. |
|
287 ] |
|
288 ifFalse: |
|
289 [ |
|
290 xI := yI := margin |
|
291 ]. |
|
292 (x + w - 1) > (xI + (magnification x * image width)) ifTrue: |
|
293 [ |
|
294 self clearRectangleX:(xI + (magnification x * image width)) |
|
295 y:y |
|
296 width:(x + w - (magnification x * image width) - xI) |
|
297 height:h |
|
298 ]. |
|
299 (y + h - 1) > (yI + (magnification y * image height)) ifTrue: |
|
300 [ |
|
301 self clearRectangleX:margin |
|
302 y:(yI + (magnification y * image height)) |
|
303 width:w |
|
304 height:(y + h - (magnification y * image height) - yI) |
|
305 ]. |
|
306 self drawFrame. |
|
307 self clippingRectangle: nil. |
|
308 ! ! |
|
309 |
|
310 !ImageEditView methodsFor:'edit modes'! |
|
311 |
|
312 editMode |
|
313 |
|
314 editMode isNil ifTrue: [editMode := 'point']. |
|
315 ^editMode |
|
316 ! |
|
317 |
|
318 editMode:aMode |
|
319 |
|
320 editMode := aMode |
|
321 ! |
|
322 |
|
323 mouseKeyColorMode |
|
324 |
|
325 ^mouseKeyColorMode printString |
|
326 ! |
|
327 |
|
328 mouseKeyColorMode:aMode |
|
329 |
|
330 mouseKeyColorMode := aMode asInteger |
|
331 ! ! |
|
332 |
|
333 !ImageEditView methodsFor:'event handling'! |
|
334 |
|
335 buttonMotion:state x:x y:y |
|
336 |
|
337 self selectedColor notNil & image notNil & (self imageContainsPoint: x@y) & (editMode = 'point') |
|
338 ifTrue: [^self pointAt: x@y]. |
|
339 |
|
340 ^super buttonMotion:state x:x y:y |
|
341 |
|
342 ! |
|
343 |
|
344 buttonPress:button x:x y:y |
|
345 |
|
346 self selectedColor notNil & image notNil & (self imageContainsPoint: x@y) |
|
347 ifTrue: |
|
348 [ |
|
349 undoImage := image copy. |
|
350 mouseKeyColorMode := button. |
|
351 (editMode = 'point') ifTrue: [self pointAt: x@y]. |
|
352 (editMode = 'replace') ifTrue: [self replaceAt: x@y]. |
|
353 (editMode = 'paste') ifTrue: [self pasteAt: x@y]. |
|
354 (editMode = 'box') | (editMode = 'copy') ifTrue: [self boxAt: x@y]. |
|
355 ^self |
|
356 ]. |
|
357 |
|
358 ^super buttonPress:button x:x y:y |
|
359 ! ! |
|
360 |
|
361 !ImageEditView methodsFor:'image drawing'! |
|
362 |
|
363 boxAt: aPoint |
|
364 |
|
365 |firstPoint currentPoint lastCurrentPoint currentExtent imageFirstPoint imageExtent| |
|
366 |
|
367 firstPoint := lastCurrentPoint := aPoint//magnification*magnification. |
|
368 [Display anyButtonPressed] |
|
369 whileTrue: |
|
370 [ |
|
371 currentPoint := (0@0) max: (image extent * magnification min: (self translation negated + (device translatePoint: self sensor mousePoint from:device rootView id to:self id))). |
|
372 currentPoint := currentPoint//magnification*magnification. |
|
373 currentExtent := (firstPoint - currentPoint) abs. |
|
374 currentPoint ~= lastCurrentPoint ifTrue: |
|
375 [ |
|
376 self redraw: ((firstPoint min: lastCurrentPoint) - 1 extent: (firstPoint - lastCurrentPoint) abs + 2). |
|
377 editMode = 'copy' |
|
378 ifTrue: |
|
379 [ |
|
380 self xoring: [self fillRectangle: ((firstPoint min: currentPoint) + 1 extent: currentExtent - 1)] |
|
381 ]. |
|
382 editMode = 'box' |
|
383 ifTrue: |
|
384 [ |
|
385 self selectedColor ~= Color noColor |
|
386 ifTrue: [self paint: self selectedColor] |
|
387 ifFalse: [self paint: self viewBackground]. |
|
388 self fillRectangle: ((firstPoint min: currentPoint) + 1 extent: currentExtent - 1) |
|
389 ]. |
|
390 ]. |
|
391 self drawLabel: currentPoint//magnification. |
|
392 lastCurrentPoint := currentPoint. |
|
393 ]. |
|
394 |
|
395 imageFirstPoint := (firstPoint min: currentPoint)//magnification. |
|
396 imageExtent := currentExtent//magnification. |
|
397 editMode = 'box' |
|
398 ifTrue: |
|
399 [ |
|
400 self selectedColor ~= Color noColor |
|
401 ifTrue: |
|
402 [ |
|
403 image mask notNil ifTrue: [image mask fillRectangleX: imageFirstPoint x y: imageFirstPoint y width: imageExtent x height: imageExtent y with:Color white]. |
|
404 image fillRectangleX: imageFirstPoint x y: imageFirstPoint y width: imageExtent x height: imageExtent y with: self selectedColor. |
|
405 self paint: self selectedColor. |
|
406 ] |
|
407 ifFalse: |
|
408 [ |
|
409 image fillRectangleX: imageFirstPoint x y: imageFirstPoint y width: imageExtent x height: imageExtent y with: ((image colorMap includes: Color black) ifTrue: [Color black] ifFalse: [image colorMap first]). |
|
410 image mask notNil ifTrue: [image mask fillRectangleX: imageFirstPoint x y: imageFirstPoint y width: imageExtent x height: imageExtent y with: Color black]. |
|
411 self paint: self viewBackground. |
|
412 ]. |
|
413 image restored. |
|
414 modified := true. |
|
415 ]. |
|
416 editMode = 'copy' |
|
417 ifTrue: |
|
418 [ |
|
419 Clipboard := image subImageIn: (imageFirstPoint extent: imageExtent - 1) |
|
420 ]. |
|
421 self redraw: ((firstPoint min: currentPoint) - 1 extent: (firstPoint - currentPoint) abs + 2). |
|
422 ! |
|
423 |
|
424 pasteAt: aPoint |
|
425 |
|
426 Object errorSignal handle: |
|
427 [:ex| |
|
428 WarningBox warn: 'Pasting into this image failed!!'. |
|
429 ] |
|
430 do: |
|
431 [ |
|
432 |imagePoint| |
|
433 imagePoint := aPoint//magnification. |
|
434 image copyFrom: Clipboard x:0 y:0 toX: imagePoint x y: imagePoint y width: Clipboard width height: Clipboard height. |
|
435 self redraw: (imagePoint * magnification extent: (Clipboard extent * magnification)). |
|
436 self drawLabel: imagePoint. |
|
437 image restored. |
|
438 modified := true. |
|
439 ] |
|
440 ! |
|
441 |
|
442 pointAt: aPoint |
|
443 |
|
444 |imagePoint| |
|
445 imagePoint := aPoint//magnification. |
|
446 self selectedColor ~= Color noColor |
|
447 ifTrue: |
|
448 [ |
|
449 image mask notNil ifTrue: [image mask colorAt: imagePoint put: Color white]. |
|
450 image colorAt: imagePoint put: self selectedColor. |
|
451 self paint: self selectedColor. |
|
452 ] |
|
453 ifFalse: |
|
454 [ |
|
455 image colorAt: imagePoint put: ((image colorMap includes: Color black) ifTrue: [Color black] ifFalse: [image colorMap first]). |
|
456 image mask notNil ifTrue: [image mask colorAt: imagePoint put: Color black]. |
|
457 self paint:self viewBackground. |
|
458 ]. |
|
459 |
|
460 self fillRectangle: (imagePoint * magnification + 1 extent: magnification). |
|
461 self selectedColor = Color noColor |
|
462 ifTrue: |
|
463 [ |
|
464 self drawMaskPointAt: imagePoint * magnification + 1. |
|
465 ]. |
|
466 self drawFrameAt: aPoint. |
|
467 self drawLabel: imagePoint. |
|
468 image restored. |
|
469 modified := true. |
|
470 ! |
|
471 |
|
472 replaceAt: aPoint |
|
473 |
|
474 |imagePoint| |
|
475 imagePoint := aPoint//magnification. |
|
476 self selectedColor ~= Color noColor |
|
477 ifTrue: |
|
478 [ |
|
479 image mask notNil ifTrue: [image mask fillAround: imagePoint withColor: Color white]. |
|
480 image fillAround: imagePoint withColor: self selectedColor. |
|
481 self paint: self selectedColor. |
|
482 ] |
|
483 ifFalse: |
|
484 [ |
|
485 image mask notNil ifTrue: [image mask fillAround: imagePoint withColor: Color black]. |
|
486 self paint:self viewBackground. |
|
487 ]. |
|
488 self drawLabel: imagePoint. |
|
489 self invalidate. |
|
490 image restored. |
|
491 modified := true. |
|
492 |
|
493 ! |
|
494 |
|
495 undo |
|
496 |
|
497 undoImage notNil |
|
498 ifTrue: |
|
499 [ |
|
500 modified := false. |
|
501 self image: undoImage. |
|
502 self invalidate |
|
503 ] |
|
504 ! ! |
|
505 |
|
506 !ImageEditView methodsFor:'image editing'! |
|
507 |
|
508 flipHorizontal |
|
509 |
|
510 self image: image flipHorizontal. |
|
511 |
|
512 ! |
|
513 |
|
514 flipVertical |
|
515 |
|
516 self image: image flipVertical. |
|
517 |
|
518 ! |
|
519 |
|
520 negativeImage |
|
521 |
|
522 self image: image negative. |
|
523 |
|
524 ! |
|
525 |
|
526 resizeImage |
|
527 |
|
528 |b newSize| |
|
529 |
|
530 b := EnterBox new. |
|
531 b title:'resize image'. |
|
532 b okText:'apply'. |
|
533 b abortText:'abort'. |
|
534 b initialText:image extent printString. |
|
535 b showAtPointer. |
|
536 (newSize := Object readFromString: b contents onError:nil) notNil |
|
537 ifTrue: |
|
538 [ |
|
539 self image: (image magnifiedBy: newSize/image extent) |
|
540 ]. |
|
541 ! |
|
542 |
|
543 rotateImage |
|
544 |
|
545 |b rotation| |
|
546 |
|
547 b := EnterBox new. |
|
548 b title:'rotate image'. |
|
549 b okText:'apply'. |
|
550 b abortText:'abort'. |
|
551 b initialText: '0'. |
|
552 b showAtPointer. |
|
553 (rotation := Object readFromString: b contents onError:nil) notNil |
|
554 ifTrue: |
|
555 [ Object errorSignal handle: |
|
556 [:ex| |
|
557 WarningBox warn: 'Image rotation failed.\' withCRs, 'An increase of image depth could help.'. |
|
558 ] |
|
559 do: |
|
560 [ |
|
561 self image: (image hardRotated: rotation) |
|
562 ] |
|
563 ]. |
|
564 ! ! |
|
565 |
|
566 !ImageEditView methodsFor:'image emphasis'! |
|
567 |
|
568 drawFrame |
|
569 |
|
570 self paint:Color black. |
|
571 "self lineWidth: (magnification x//3 min: 3). " |
|
572 self displayRectangle: ((0@0) extent:(image extent * magnification) + 2). |
|
573 self lineWidth:1. |
|
574 ! |
|
575 |
|
576 drawFrameAt: aPoint |
|
577 |
|
578 magnification > gridMagnification |
|
579 ifTrue: |
|
580 [ |
|
581 |lineStartingPoint lineEndingPoint oldColor| |
|
582 lineStartingPoint := aPoint//magnification*magnification. |
|
583 lineEndingPoint := aPoint//magnification*magnification + magnification. |
|
584 oldColor := self paint. |
|
585 self xoring: |
|
586 [ |
|
587 self displayLineFrom: lineEndingPoint |
|
588 to: (lineEndingPoint x)@(lineStartingPoint y). |
|
589 self displayLineFrom: lineEndingPoint |
|
590 to: (lineStartingPoint x)@(lineEndingPoint y). |
|
591 ]. |
|
592 self paint: oldColor. |
|
593 ] |
|
594 ! |
|
595 |
|
596 drawLabel: aLabel |
|
597 coordInfoBlock notNil |
|
598 ifTrue: |
|
599 [ |
|
600 coordInfoBlock value: aLabel printString |
|
601 ] |
|
602 ! |
|
603 |
|
604 drawMaskPointAt: aPoint |
|
605 |
|
606 |sizeOfMaskPoint| |
|
607 sizeOfMaskPoint := magnification//3. |
|
608 self xoring: [self fillRectangle: (aPoint + sizeOfMaskPoint extent: sizeOfMaskPoint)]. |
|
609 |
|
610 ! ! |
|
611 |
|
612 !ImageEditView methodsFor:'image setting'! |
|
613 |
|
614 image:anImage |
|
615 |
|
616 (anImage isImage and: [image isNil or: [self checkModified]]) |
|
617 ifTrue: |
|
618 [ |
|
619 super image: anImage. |
|
620 image photometric = #palette |
|
621 ifTrue: |
|
622 [ |
|
623 (image usedColors includes: selectColors first) ifFalse: [selectColors at: 1 put: nil]. |
|
624 (image usedColors includes: selectColors last) ifFalse: [selectColors at: 2 put: nil]. |
|
625 ]. |
|
626 ^self |
|
627 ]. |
|
628 ^nil |
|
629 ! |
|
630 |
|
631 loadFromFile: aFileName |
|
632 |
|
633 |fileName newImage| |
|
634 fileName := aFileName asFilename. |
|
635 |
|
636 Object errorSignal handle: |
|
637 [:exeption| |
|
638 WarningBox warn: exeption errorString. |
|
639 ^nil |
|
640 ] |
|
641 do: |
|
642 [ |
|
643 newImage := Image fromFile: fileName name. |
|
644 ]. |
|
645 |
|
646 (self image: newImage) notNil |
|
647 ifTrue: |
|
648 [ |
|
649 imageReaderClass := ImageReader allSubclasses detect: [:cls| cls isValidImageFile:fileName name] ifNone: |
|
650 [WarningBox warn: 'Unknown image file format'. ^nil]. |
|
651 ] |
|
652 ! |
|
653 |
|
654 resourceClass: aClassOrSymbol selector: aStringOrSymbol |
|
655 |
|
656 |aClass| |
|
657 imageReaderClass := nil. |
|
658 self resourceClass: aClassOrSymbol. |
|
659 self resourceSelector: aStringOrSymbol. |
|
660 aClass := Smalltalk at: resourceClass. |
|
661 (aClass isClass and: [aClass class implements: resourceSelector]) |
|
662 ifTrue: |
|
663 [ |
|
664 ^self image: (aClass perform: resourceSelector) copy |
|
665 ]. |
|
666 ^nil |
|
667 ! ! |
|
668 |
|
669 !ImageEditView methodsFor:'initialization'! |
|
670 |
|
671 initialize |
|
672 |
|
673 super initialize. |
|
674 |
|
675 magnification := 1@1. |
|
676 gridMagnification := 8@8. |
|
677 modified := false. |
|
678 mouseKeyColorMode := 1. |
|
679 resourceClass := resourceSelector := ''. |
|
680 selectColors := Array with: nil with: nil. |
|
681 self menuHolder:self; menuPerformer:self; menuMessage:#imageMenu. |
|
682 ! ! |
|
683 |
|
684 !ImageEditView methodsFor:'menu actions'! |
|
685 |
|
686 changeMagnification |
|
687 |b newMag| |
|
688 |
|
689 b := EnterBox new. |
|
690 b title:'magnification (magX @ magY)'. |
|
691 b okText:'apply'. |
|
692 b abortText:'abort'. |
|
693 b action:[:string | newMag := (Object readFromString:string onError:nil)]. |
|
694 b initialText:(magnification printString). |
|
695 b showAtPointer. |
|
696 |
|
697 newMag notNil ifTrue:[ |
|
698 self magnification:newMag. |
|
699 ]. |
|
700 |
|
701 "Modified: 31.7.1997 / 11:43:12 / cg" |
|
702 ! |
|
703 |
|
704 loadFromClass |
|
705 |
|
706 self resourceMessage: (ResourceBrowserView |
|
707 openOnSuperclass: ApplicationModel |
|
708 class: self resourceClass |
|
709 selector: self resourceSelector |
|
710 resourceTypes: #(#image #fileImage)) |
|
711 |
|
712 |
|
713 ! |
|
714 |
|
715 loadFromUser |
|
716 |
|
717 self image: |
|
718 ((Image fromUser) |
|
719 asDitheredTrueColor8FormOn: Display) |
|
720 |
|
721 ! |
|
722 |
|
723 print |
|
724 |stream psgc| |
|
725 |
|
726 image isNil ifTrue: [^nil]. |
|
727 |
|
728 Printer supportsPostscript ifFalse:[ |
|
729 self warn:'need a postscript printer'. |
|
730 ^ self |
|
731 ]. |
|
732 |
|
733 stream := Printer newNative. |
|
734 stream isNil ifTrue:[ |
|
735 self warn:'cannot open printer stream'. |
|
736 ^ nil |
|
737 ]. |
|
738 |
|
739 self withWaitCursorDo:[ |
|
740 psgc := PSGraphicsContext on:stream. "/ extent:(1.0 @ 1.0). |
|
741 psgc displayForm: (image magnifiedBy: magnification) x:0 y:0. |
|
742 psgc close. |
|
743 ] |
|
744 ! |
|
745 |
|
746 save |
|
747 |
|
748 Object errorSignal handle: |
|
749 [:ex| |
|
750 WarningBox warn: ex errorString. |
|
751 ^nil |
|
752 ] |
|
753 do: |
|
754 [ |
|
755 |fileName| |
|
756 image isNil ifTrue: [^self error: 'No image to save!!']. |
|
757 image fileName isNil ifTrue: [^self error: 'No file name for image detected!!']. |
|
758 fileName := image fileName asFilename. |
|
759 (fileName suffix = 'tiff') | (fileName suffix = 'tif') ifTrue: [imageReaderClass := TIFFReader]. |
|
760 fileName suffix = 'xpm' ifTrue: [imageReaderClass := XPMReader]. |
|
761 fileName suffix = 'xbm' ifTrue: [imageReaderClass := XBMReader]. |
|
762 fileName suffix = 'gif' ifTrue: [imageReaderClass := GIFReader]. |
|
763 (fileName suffix = 'jpg') | (fileName suffix = 'jpeg') ifTrue: [imageReaderClass := JPEGReader]. |
|
764 imageReaderClass isNil ifTrue: [imageReaderClass := XPMReader. image fileName: image fileName, '.xpm']. |
|
765 |
|
766 image saveOn: image fileName using: imageReaderClass. |
|
767 modified := false. |
|
768 ] |
|
769 |
|
770 ! |
|
771 |
|
772 saveAs |
|
773 "save contents into a file |
|
774 - ask user for filename using a fileSelectionBox." |
|
775 |
|
776 self saveImageFileAs |
|
777 ! |
|
778 |
|
779 saveAsMethod |
|
780 |
|
781 Object errorSignal handle: |
|
782 [:ex| |
|
783 WarningBox warn: ex errorString. |
|
784 ^nil |
|
785 ] |
|
786 do: |
|
787 [ |
|
788 |compileString stream aClass| |
|
789 stream := WriteStream on: ''. |
|
790 self resourceSelector trimBlanks size = 0 ifTrue: [^self error: 'No image selector detected']. |
|
791 (aClass := Smalltalk at: self resourceClass) isClass ifFalse: [^self error: 'No class for image selector detected']. |
|
792 self image storeOn: stream. |
|
793 compileString := |
|
794 self resourceSelector, |
|
795 '\\' withCRs, |
|
796 ' <resource: #image>\' withCRs, |
|
797 ' ^', |
|
798 stream contents. |
|
799 ByteCodeCompiler compile: compileString forClass: aClass class inCategory: 'resources'. |
|
800 modified := false. |
|
801 ] |
|
802 ! |
|
803 |
|
804 saveImageFileAs |
|
805 |
|
806 |aFileName| |
|
807 |
|
808 (aFileName := (FileBrowserView requestFileName: self image fileName fileFilters: #('*.xpm' '*.gif'))) notNil |
|
809 ifTrue: |
|
810 [ |
|
811 self saveImageFileAs: aFileName |
|
812 ]. |
|
813 ! |
|
814 |
|
815 saveImageFileAs: aFileName |
|
816 |
|
817 image notNil |
|
818 ifTrue: |
|
819 [ |
|
820 image fileName: aFileName. |
|
821 self save |
|
822 ] |
|
823 ifFalse: |
|
824 [ |
|
825 WarningBox warn: 'No image detected' |
|
826 ] |
|
827 ! ! |
|
828 |
|
829 !ImageEditView methodsFor:'queries'! |
|
830 |
306 checkModified |
831 checkModified |
307 |
832 |
308 modified |
833 modified ifTrue: |
309 ifTrue: |
|
310 [ |
834 [ |
311 |aBox| |
835 |aBox| |
312 aBox := YesNoBox title:'Image was modified'. |
836 aBox := YesNoBox title:'Image was modified'. |
313 aBox noText:'abort'. |
837 aBox noText:'abort'. |
314 aBox yesText:'ignore'. |
838 aBox yesText:'ignore'. |
317 modified := false |
841 modified := false |
318 ]. |
842 ]. |
319 ^true |
843 ^true |
320 ! |
844 ! |
321 |
845 |
322 gridMagnification |
|
323 |
|
324 ^gridMagnification |
|
325 |
|
326 ! |
|
327 |
|
328 gridMagnification:aPathName |
|
329 |
|
330 gridMagnification := aPathName |
|
331 ! |
|
332 |
|
333 image:anImage |
|
334 |
|
335 |oldMag| |
|
336 (anImage isImage and: [image isNil or: [self checkModified]]) |
|
337 ifTrue: |
|
338 [ |
|
339 oldMag := magnification. |
|
340 magnification := 1@1. |
|
341 super image: anImage. |
|
342 self magnification:oldMag. |
|
343 ^image |
|
344 ]. |
|
345 ^nil |
|
346 ! |
|
347 |
|
348 imageReaderClass |
|
349 |
|
350 ^imageReaderClass |
|
351 ! |
|
352 |
|
353 magnification |
|
354 |
|
355 ^magnification |
|
356 |
|
357 ! |
|
358 |
|
359 magnification:aMagnificationPoint |
|
360 |
|
361 magnification ~= aMagnificationPoint |
|
362 ifTrue: |
|
363 [ |
|
364 magnification := aMagnificationPoint asPoint. |
|
365 self scrollToTopLeft. |
|
366 self contentsChanged. |
|
367 self invalidate. |
|
368 ]. |
|
369 ! |
|
370 |
|
371 makeRedraw:aBooelean |
|
372 |
|
373 makeRedraw := aBooelean |
|
374 ! |
|
375 |
|
376 openFile: aFileName |
|
377 |
|
378 |fileName newImage| |
|
379 fileName := aFileName asFilename. |
|
380 |
|
381 Object errorSignal handle: |
|
382 [:exeption| |
|
383 WarningBox warn: exeption errorString. |
|
384 ^nil |
|
385 ] |
|
386 do: |
|
387 [ |
|
388 newImage := Image fromFile: fileName name. |
|
389 ]. |
|
390 |
|
391 (self image: newImage) notNil |
|
392 ifTrue: |
|
393 [ |
|
394 imageReaderClass := ImageReader allSubclasses detect: [:cls| cls isValidImageFile:fileName name] ifNone: |
|
395 [WarningBox warn: 'Unknown image file format'. ^nil]. |
|
396 ] |
|
397 ! |
|
398 |
|
399 pixelSelectColor: aColor |
|
400 |
|
401 pixelSelectColor := aColor |
|
402 ! |
|
403 |
|
404 resourceClass |
|
405 |
|
406 ^resourceClass |
|
407 ! |
|
408 |
|
409 resourceClass: aClass |
|
410 |
|
411 resourceClass := aClass |
|
412 ! |
|
413 |
|
414 resourceClass: aClass selector: aSelector |
|
415 |
|
416 resourceClass := aClass. |
|
417 resourceSelector := aSelector. |
|
418 (aClass isClass and: [aClass class implements: aSelector]) |
|
419 ifTrue: |
|
420 [ |
|
421 ^self image: (aClass perform: aSelector) |
|
422 ]. |
|
423 ^nil |
|
424 ! |
|
425 |
|
426 resourceMessage |
|
427 |
|
428 (resourceClass value notNil and: [resourceSelector value notNil]) |
|
429 ifTrue: |
|
430 [ |
|
431 ^resourceClass name, ' ', resourceSelector |
|
432 ]. |
|
433 ^nil |
|
434 ! |
|
435 |
|
436 resourceMessage: aMessage |
|
437 |
|
438 aMessage isNil ifTrue: [^nil]. |
|
439 resourceClass := Smalltalk at: aMessage copy readStream nextWord asSymbol. |
|
440 resourceSelector := aMessage copy reverse readStream nextWord reverse asSymbol. |
|
441 |
|
442 ^self resourceClass: resourceClass selector: resourceSelector |
|
443 |
|
444 |
|
445 ! |
|
446 |
|
447 resourceSelector |
|
448 |
|
449 ^resourceSelector |
|
450 ! |
|
451 |
|
452 resourceSelector: aSelector |
|
453 |
|
454 resourceSelector := aSelector |
|
455 ! ! |
|
456 |
|
457 !ImageEditView methodsFor:'accessing menu'! |
|
458 |
|
459 menuEffects |
|
460 "this window spec was automatically generated by the UI Builder" |
|
461 |
|
462 ^ self class menuEffects |
|
463 |
|
464 |
|
465 ! ! |
|
466 |
|
467 !ImageEditView methodsFor:'drawing'! |
|
468 |
|
469 colorAt: aPoint put: aColor |
|
470 |
|
471 |tempPaint| |
|
472 tempPaint := self paint. |
|
473 aColor redByte = 'mask' |
|
474 ifTrue: |
|
475 [ |
|
476 image restored; colorAt: aPoint//magnification put: Color black. |
|
477 image mask notNil ifTrue: [image mask restored; colorAt: aPoint//magnification put: Color black]. |
|
478 self paint:Color lightGray. |
|
479 ] |
|
480 ifFalse: |
|
481 [ |
|
482 image mask notNil ifTrue: [image mask restored; colorAt: aPoint//magnification put: Color white]. |
|
483 image restored; colorAt: aPoint//magnification put: aColor. |
|
484 self paint:aColor. |
|
485 ]. |
|
486 |
|
487 self fillRectangleX:(aPoint x // magnification x) * magnification x + 1 |
|
488 y:(aPoint y // magnification y) * magnification y + 1 |
|
489 width:magnification x height:magnification y. |
|
490 |
|
491 self paint:tempPaint. |
|
492 magnification > gridMagnification |
|
493 ifTrue: |
|
494 [ |
|
495 self drawGridMagnification |
|
496 ]. |
|
497 |
|
498 ! |
|
499 |
|
500 drawGridMagnification |
|
501 |
|
502 |tempPaint| |
|
503 tempPaint := self paint. |
|
504 self paint:Color black. |
|
505 0 to: (image width * magnification x) by: magnification x do: |
|
506 [:x| |
|
507 self displayLineFromX:x y:0 toX:x y:(image height * magnification y) |
|
508 ]. |
|
509 0 to: (image height * magnification y) by: magnification y do: |
|
510 [:y| |
|
511 self displayLineFromX:0 y:y toX:(image width * magnification x) y:y |
|
512 ]. |
|
513 self paint:tempPaint. |
|
514 ! |
|
515 |
|
516 redrawImageX:x y:y width:w height:h |
|
517 |ih iw dotW dotH minX maxX minY maxY color last lastY runW x0 xI yI| |
|
518 |
|
519 ih := image height. |
|
520 iw := image width. |
|
521 dotW := magnification x. |
|
522 dotH := magnification y. |
|
523 |
|
524 minX := (x // dotW). |
|
525 minX > iw ifTrue:[ |
|
526 minX := iw - 1 |
|
527 ]. |
|
528 |
|
529 minY := (y // dotH) . |
|
530 minY > ih ifTrue:[ |
|
531 minY := ih - 1 |
|
532 ]. |
|
533 maxX := (x + w) // dotW + 1. |
|
534 maxX > iw ifTrue:[ |
|
535 maxX := iw |
|
536 ]. |
|
537 maxY := (y + h) // dotH + 1. |
|
538 maxY > ih ifTrue:[ |
|
539 maxY := ih |
|
540 ]. |
|
541 |
|
542 lastY := -1. |
|
543 |
|
544 x0 := minX. |
|
545 runW := 0. |
|
546 |
|
547 image colorsFromX:minX y:minY toX:maxX-1 y:maxY-1 do:[:xx :yy :color | |
|
548 |
|
549 yy ~~ lastY ifTrue:[ |
|
550 runW ~~ 0 ifTrue:[ |
|
551 self fillRectangleX:(x0 * dotW + margin) |
|
552 y:(lastY * dotH + margin) |
|
553 width:runW height:dotH. |
|
554 runW := 0. |
|
555 ]. |
|
556 x0 := xx. |
|
557 lastY := yy. |
|
558 ]. |
|
559 |
|
560 color ~~ last ifTrue:[ |
|
561 runW ~~ 0 ifTrue:[ |
|
562 self fillRectangleX:(x0 * dotW + margin) |
|
563 y:(yy * dotH + margin) |
|
564 width:runW height:dotH. |
|
565 runW := 0. |
|
566 ]. |
|
567 |
|
568 "self paint:color." |
|
569 (image mask notNil and: [(image mask colorAt: xx@yy) = Color black]) |
|
570 ifTrue: [self paint: Color lightGray] ifFalse: [self paint: color]. |
|
571 last := color. |
|
572 runW := 0. |
|
573 x0 := xx. |
|
574 ]. |
|
575 runW := runW + dotW |
|
576 ]. |
|
577 runW ~~ 0 ifTrue:[ |
|
578 self fillRectangleX:(x0 * dotW + margin) |
|
579 y:(lastY * dotH + margin) |
|
580 width:runW height:dotH. |
|
581 runW := 0. |
|
582 ]. |
|
583 ! |
|
584 |
|
585 redrawX:x y:y width:w height:h |
|
586 |ih iw dotW dotH minX maxX minY maxY color last lastY runW x0 xI yI| |
|
587 |
|
588 image isNil ifTrue:[^self]. |
|
589 |
|
590 magnification = (1@1) ifTrue:[ |
|
591 super redrawX:x y:y width:w height:h. |
|
592 ^ self |
|
593 ]. |
|
594 self clippingRectangle: (x@y extent: w@h). |
|
595 |
|
596 self redrawImageX:x y:y width:w height:h. |
|
597 |
|
598 "/ right of image ? |
|
599 adjust == #center ifTrue:[ |
|
600 xI := (width - (margin * 2) - ih) // 2. |
|
601 yI := (height - (margin * 2) - iw) // 2. |
|
602 ] ifFalse:[ |
|
603 xI := yI := margin |
|
604 ]. |
|
605 (x + w - 1) > (xI + (magnification x * image width)) ifTrue:[ |
|
606 self clearRectangleX:(xI + (magnification x * image width)) |
|
607 y:y |
|
608 width:(x + w - (magnification x * image width) - xI) |
|
609 height:h |
|
610 ]. |
|
611 (y + h - 1) > (yI + (magnification y * image height)) ifTrue:[ |
|
612 self clearRectangleX:margin |
|
613 y:(yI + (magnification y * image height)) |
|
614 width:w |
|
615 height:(y + h - (magnification y * image height) - yI) |
|
616 ]. |
|
617 magnification > gridMagnification |
|
618 ifTrue: |
|
619 [ |
|
620 self drawGridMagnification |
|
621 ]. |
|
622 self clippingRectangle: nil |
|
623 ! ! |
|
624 |
|
625 !ImageEditView methodsFor:'event handling'! |
|
626 |
|
627 buttonMotion:state x:x y:y |
|
628 |
|
629 self showColorAtX:x y:y. |
|
630 ! |
|
631 |
|
632 buttonMultiPress:button x:x y:y |
|
633 button == 1 ifTrue:[ |
|
634 |clr| |
|
635 clr := self getColorAtX:x y:y. |
|
636 ]. |
|
637 super buttonMultiPress:button x:x y:y |
|
638 |
|
639 "Created: 8.5.1996 / 00:18:06 / stefan" |
|
640 ! |
|
641 |
|
642 buttonPress:button x:x y:y |
|
643 button == 1 ifTrue:[ |
|
644 self showColorAtX:x y:y. |
|
645 ^ self |
|
646 ]. |
|
647 super buttonPress:button x:x y:y |
|
648 ! |
|
649 |
|
650 getColorAtX:x y:y |
|
651 |pi| |
|
652 |
|
653 pi := (((x @ y) - margin + 1) / magnification) floor. |
|
654 ((0@0 corner:(image extent) - 1) containsPoint:pi) |
|
655 ifTrue: |
|
656 [ |
|
657 ^ image at:pi |
|
658 ]. |
|
659 ^ nil |
|
660 |
|
661 "Created: 8.5.1996 / 00:15:55 / stefan" |
|
662 ! |
|
663 |
|
664 showColorAtX:x y:y |
|
665 |clr| |
|
666 |
|
667 clr := self getColorAtX:x y:y. |
|
668 clr notNil |
|
669 ifTrue: |
|
670 [ |
|
671 pixelSelectColor isColor" & (image colorMap includes: clr)" |
|
672 ifTrue: |
|
673 [ |
|
674 makeRedraw ifTrue: [self invalidate. makeRedraw := false]. |
|
675 modified := true. |
|
676 self colorAt: x@y put: pixelSelectColor. |
|
677 ] |
|
678 ] |
|
679 ! ! |
|
680 |
|
681 !ImageEditView methodsFor:'image conversion'! |
|
682 |
|
683 convertToColor24 |
|
684 (Depth24Image fromImage:image) inspect |
|
685 |
|
686 "Modified: 3.6.1997 / 18:34:34 / cg" |
|
687 ! |
|
688 |
|
689 convertToColor4 |
|
690 (Depth4Image fromImage:image) inspect |
|
691 |
|
692 "Modified: 3.6.1997 / 18:34:45 / cg" |
|
693 ! |
|
694 |
|
695 convertToColor8 |
|
696 (Depth8Image fromImage:image) inspect |
|
697 |
|
698 "Created: 3.6.1997 / 18:34:08 / cg" |
|
699 "Modified: 3.6.1997 / 18:34:51 / cg" |
|
700 ! |
|
701 |
|
702 convertToGray2 |
|
703 (image asFloydSteinbergDitheredGrayImageDepth:2) inspect |
|
704 |
|
705 "Created: 3.6.1997 / 18:34:02 / cg" |
|
706 "Modified: 3.6.1997 / 18:39:23 / cg" |
|
707 ! |
|
708 |
|
709 convertToGray4 |
|
710 (image asFloydSteinbergDitheredGrayImageDepth:4) inspect |
|
711 |
|
712 "Created: 3.6.1997 / 18:34:04 / cg" |
|
713 "Modified: 3.6.1997 / 18:39:20 / cg" |
|
714 ! |
|
715 |
|
716 convertToGray8 |
|
717 (image asFloydSteinbergDitheredGrayImageDepth:8) inspect |
|
718 |
|
719 "Created: 3.6.1997 / 18:34:05 / cg" |
|
720 "Modified: 3.6.1997 / 18:39:16 / cg" |
|
721 ! |
|
722 |
|
723 convertToMono |
|
724 (image asFloydSteinbergDitheredGrayImageDepth:1) inspect |
|
725 |
|
726 "Created: 3.6.1997 / 18:33:42 / cg" |
|
727 "Modified: 3.6.1997 / 18:39:26 / cg" |
|
728 ! ! |
|
729 |
|
730 !ImageEditView methodsFor:'image processing'! |
|
731 |
|
732 flipHorizontal |
|
733 self performImageOperation:#flipHorizontal withArguments:nil |
|
734 ! |
|
735 |
|
736 flipVertical |
|
737 self performImageOperation:#flipVertical withArguments:nil |
|
738 ! |
|
739 |
|
740 negative |
|
741 self performImageOperation:#negative withArguments:nil |
|
742 ! |
|
743 |
|
744 performImageOperation:operation withArguments:args |
|
745 |oldMag newImage| |
|
746 |
|
747 windowGroup withCursor:Cursor wait do:[ |
|
748 oldMag := magnification. |
|
749 magnification := 1@1. |
|
750 newImage := image perform:operation withArguments:args. |
|
751 newImage isNil ifTrue:[ |
|
752 self information:'conversion failed - revert to original'. |
|
753 ^ self |
|
754 ]. |
|
755 image := newImage. |
|
756 self clear. |
|
757 (oldMag isNil or:[oldMag = magnification]) ifTrue:[ |
|
758 self invalidate |
|
759 ] ifFalse:[ |
|
760 self magnification:oldMag. |
|
761 ] |
|
762 ] |
|
763 |
|
764 "Modified: 23.6.1997 / 09:49:26 / cg" |
|
765 ! |
|
766 |
|
767 resizeImage |
|
768 |b newSize newImage wNew hNew bits| |
|
769 |
|
770 b := EnterBox new. |
|
771 b title:'new size (x @ y) contents will be located at top-left'. |
|
772 b okText:'apply'. |
|
773 b abortText:'abort'. |
|
774 b action:[:string | newSize := Object readFromString:string onError:nil]. |
|
775 b initialText:(image extent printString). |
|
776 b showAtPointer. |
|
777 |
|
778 newSize notNil ifTrue:[ |
|
779 wNew := image width min:newSize x. |
|
780 hNew := image height min:newSize y. |
|
781 |
|
782 newImage := Image width:(newSize x) height:(newSize y) depth:(image depth). |
|
783 newImage photometric:image photometric. |
|
784 newImage colorMap:image colorMap copy. |
|
785 newImage bits:(ByteArray new:(newImage bytesPerRow * newSize y)). |
|
786 |
|
787 newImage copyFrom:image x:0 y:0 toX:0 y:0 width:wNew height:hNew. |
|
788 |
|
789 self image: newImage |
|
790 ]. |
|
791 |
|
792 "Created: 31.7.1997 / 11:41:14 / cg" |
|
793 "Modified: 31.7.1997 / 13:45:47 / cg" |
|
794 ! |
|
795 |
|
796 rotateCCW |
|
797 self performImageOperation:#rotated: withArguments:#(270) |
|
798 ! |
|
799 |
|
800 rotateCW |
|
801 self performImageOperation:#rotated: withArguments:#(90) |
|
802 ! ! |
|
803 |
|
804 !ImageEditView methodsFor:'initialization'! |
|
805 |
|
806 initialize |
|
807 |
|
808 super initialize. |
|
809 magnification := 1@1. |
|
810 gridMagnification := 5@5. |
|
811 makeRedraw := modified := antiAlias := false. |
|
812 |
|
813 self menuHolder:self; menuPerformer:self; menuMessage:#imageMenu. |
|
814 |
|
815 "Modified: 2.6.1997 / 15:49:00 / cg" |
|
816 ! ! |
|
817 |
|
818 !ImageEditView methodsFor:'menu'! |
|
819 |
|
820 imageMenu |
|
821 |m convertMenu labels selectors| |
|
822 |
|
823 image mask notNil ifTrue:[ |
|
824 labels := #( |
|
825 'save as ...' |
|
826 'save mask as ...' |
|
827 ). |
|
828 selectors := #( |
|
829 saveAs |
|
830 saveMaskAs |
|
831 ). |
|
832 magnification ~~ (1@1) notNil ifTrue:[ |
|
833 labels := labels , #( |
|
834 '-' |
|
835 'save magnified as ...' |
|
836 'save magnified mask as ...' |
|
837 ). |
|
838 |
|
839 selectors := selectors , #( |
|
840 nil |
|
841 saveMagnifiedAs |
|
842 saveMagnifiedMaskAs |
|
843 ). |
|
844 ] |
|
845 ] ifFalse:[ |
|
846 labels := #( |
|
847 'save as ...' |
|
848 ). |
|
849 selectors := #( |
|
850 saveAs |
|
851 ). |
|
852 magnification ~~ (1@1) ifTrue:[ |
|
853 labels := labels , #( |
|
854 '-' |
|
855 'save magnified as ...' |
|
856 ). |
|
857 |
|
858 selectors := selectors , #( |
|
859 nil |
|
860 saveMagnifiedAs |
|
861 ). |
|
862 ] |
|
863 ]. |
|
864 |
|
865 labels := labels , #( |
|
866 '-' |
|
867 'print' |
|
868 'print magnified' |
|
869 '-' |
|
870 'magnification' |
|
871 'magnify & antiAlias' |
|
872 "/ 'colors' |
|
873 'effects' |
|
874 'convert to' |
|
875 ). |
|
876 selectors := selectors , #( |
|
877 nil |
|
878 doPrint |
|
879 doPrintMagnified |
|
880 nil |
|
881 changeMagnification |
|
882 changeMagnificationAndAntiAlias |
|
883 "/ showColors |
|
884 effects |
|
885 convert |
|
886 ). |
|
887 |
|
888 m := PopUpMenu |
|
889 labels:(resources array:labels) |
|
890 selectors:selectors |
|
891 receiver:self |
|
892 for:self. |
|
893 |
|
894 magnification = 1 ifTrue:[ |
|
895 m disable:#doPrintMagnified |
|
896 ]. |
|
897 |
|
898 m subMenuAt:#effects put:( |
|
899 PopUpMenu labels:(resources array:#( |
|
900 'flip - vertical' |
|
901 'flip - horizontal' |
|
902 '-' |
|
903 'rotate - clockwise' |
|
904 'rotate - counter clockwise' |
|
905 '-' |
|
906 'negative' |
|
907 '-' |
|
908 'resize' |
|
909 " |
|
910 'blurr' |
|
911 " |
|
912 )) |
|
913 selectors:#( |
|
914 flipVertical |
|
915 flipHorizontal |
|
916 nil |
|
917 rotateCW |
|
918 rotateCCW |
|
919 nil |
|
920 negative |
|
921 nil |
|
922 resizeImage |
|
923 " |
|
924 blurr |
|
925 " |
|
926 ) |
|
927 receiver:self |
|
928 for:self |
|
929 |
|
930 ). |
|
931 |
|
932 m subMenuAt:#convert put:( |
|
933 convertMenu := |
|
934 PopUpMenu labels:(resources array:#( |
|
935 'monochrome (dither)' |
|
936 '-' |
|
937 'gray 2-plane (dither)' |
|
938 'gray 4-plane (dither) ' |
|
939 'gray 8-plane ' |
|
940 '-' |
|
941 "/ 'color 4-plane (dither)' |
|
942 "/ 'color 8-plane (dither)' |
|
943 'color 24-plane' |
|
944 )) |
|
945 selectors:#( |
|
946 convertToMono |
|
947 nil |
|
948 convertToGray2 |
|
949 convertToGray4 |
|
950 convertToGray8 |
|
951 nil |
|
952 "/ convertToColor4 |
|
953 "/ convertToColor8 |
|
954 convertToColor24 |
|
955 ) |
|
956 receiver:self |
|
957 for:self |
|
958 ). |
|
959 |
|
960 image depth == 1 ifTrue:[ |
|
961 convertMenu disable:#convertToMono |
|
962 ]. |
|
963 image depth == 2 ifTrue:[ |
|
964 (image photometric ~~ #palette |
|
965 and:[image photometric ~~ #rgb]) ifTrue:[ |
|
966 convertMenu disable:#convertToGray2 |
|
967 ] |
|
968 ]. |
|
969 image depth == 4 ifTrue:[ |
|
970 (image photometric ~~ #palette |
|
971 and:[image photometric ~~ #rgb]) ifTrue:[ |
|
972 convertMenu disable:#convertToGray4 |
|
973 ] ifFalse:[ |
|
974 convertMenu disable:#convertToColor4 |
|
975 ] |
|
976 ]. |
|
977 image depth == 8 ifTrue:[ |
|
978 (image photometric ~~ #palette |
|
979 and:[image photometric ~~ #rgb]) ifTrue:[ |
|
980 convertMenu disable:#convertToGray8 |
|
981 ] ifFalse:[ |
|
982 convertMenu disable:#convertToColor8 |
|
983 ] |
|
984 ]. |
|
985 image depth == 24 ifTrue:[ |
|
986 image photometric == #rgb ifTrue:[ |
|
987 convertMenu disable:#convertToColor24 |
|
988 ] |
|
989 ]. |
|
990 |
|
991 ^ m |
|
992 |
|
993 " |
|
994 ImageEditView openOn:'bitmaps/SBrowser.xbm' |
|
995 ImageEditView openOn:'bitmaps/garfield.gif' |
|
996 " |
|
997 |
|
998 "Created: 20.2.1997 / 18:47:17 / cg" |
|
999 "Modified: 31.7.1997 / 11:41:26 / cg" |
|
1000 ! ! |
|
1001 |
|
1002 !ImageEditView methodsFor:'menu actions'! |
|
1003 |
|
1004 changeMagnification |
|
1005 |b newMag| |
|
1006 |
|
1007 b := EnterBox new. |
|
1008 b title:'magnification (magX @ magY)'. |
|
1009 b okText:'apply'. |
|
1010 b abortText:'abort'. |
|
1011 b action:[:string | newMag := (Object readFromString:string onError:nil)]. |
|
1012 b initialText:(magnification printString). |
|
1013 b showAtPointer. |
|
1014 |
|
1015 newMag notNil ifTrue:[ |
|
1016 antiAlias ifTrue:[ |
|
1017 magnification := nil. |
|
1018 ]. |
|
1019 antiAlias := false. |
|
1020 self magnification:newMag. |
|
1021 ]. |
|
1022 |
|
1023 "Modified: 31.7.1997 / 11:43:12 / cg" |
|
1024 ! |
|
1025 |
|
1026 changeMagnificationAndAntiAlias |
|
1027 |b newMag| |
|
1028 |
|
1029 b := EnterBox new. |
|
1030 b title:'magnification (magX @ magY)'. |
|
1031 b okText:'apply'. |
|
1032 b abortText:'abort'. |
|
1033 b action:[:string | newMag := (Object readFromString:string onError:nil)]. |
|
1034 b initialText:(magnification printString). |
|
1035 b showAtPointer. |
|
1036 |
|
1037 newMag notNil ifTrue:[ |
|
1038 antiAlias ifFalse:[ |
|
1039 magnification := nil. |
|
1040 ]. |
|
1041 antiAlias := true. |
|
1042 self magnification:newMag |
|
1043 ]. |
|
1044 |
|
1045 "Created: 2.6.1997 / 15:51:01 / cg" |
|
1046 "Modified: 31.7.1997 / 11:43:47 / cg" |
|
1047 ! |
|
1048 |
|
1049 createFileName |
|
1050 |
|
1051 image fileName notNil |
|
1052 ifFalse: |
|
1053 [ |
|
1054 |fileName| |
|
1055 (fileName := FileBrowserView requestFileName) notNil |
|
1056 ifTrue: |
|
1057 [ self halt. |
|
1058 image fileName: fileName. |
|
1059 ^true |
|
1060 ]. |
|
1061 ]. |
|
1062 ^true. |
|
1063 ! |
|
1064 |
|
1065 createResourceMessage |
|
1066 |
|
1067 (self resourceClass class implements: self resourceSelector) |
|
1068 ifFalse: |
|
1069 [ |
|
1070 ((ResourceBrowserView |
|
1071 openOnSuperclass: #ApplicationModel |
|
1072 class: resourceClass |
|
1073 selector: resourceSelector |
|
1074 resourceTypes: #(#image #fileImage))) notNil |
|
1075 ifTrue: |
|
1076 [ |
|
1077 ^true |
|
1078 ]. |
|
1079 ]. |
|
1080 ^false. |
|
1081 ! |
|
1082 |
|
1083 doPrint |
|
1084 self doPrint:image |
|
1085 |
|
1086 "Modified: 2.6.1997 / 18:32:11 / cg" |
|
1087 ! |
|
1088 |
|
1089 doPrint:anImage |
|
1090 |stream psgc| |
|
1091 |
|
1092 Printer supportsPostscript ifFalse:[ |
|
1093 self warn:'need a postscript printer'. |
|
1094 ^ self |
|
1095 ]. |
|
1096 |
|
1097 stream := Printer newNative. |
|
1098 stream isNil ifTrue:[ |
|
1099 self warn:'cannot open printer stream'. |
|
1100 ^ nil |
|
1101 ]. |
|
1102 |
|
1103 self withWaitCursorDo:[ |
|
1104 psgc := PSGraphicsContext on:stream. "/ extent:(1.0 @ 1.0). |
|
1105 psgc displayForm:anImage x:0 y:0. |
|
1106 psgc close. |
|
1107 ] |
|
1108 |
|
1109 "Modified: 28.5.1997 / 10:54:11 / cg" |
|
1110 "Created: 2.6.1997 / 18:32:03 / cg" |
|
1111 ! |
|
1112 |
|
1113 doPrintMagnified |
|
1114 "self doPrint:(magnifiedImage ? image)" |
|
1115 |
|
1116 "Modified: 2.6.1997 / 18:31:54 / cg" |
|
1117 ! |
|
1118 |
|
1119 doSaveImageAs:anImage title:aTitle |
|
1120 "save contents into a file |
|
1121 - ask user for filename using a fileSelectionBox." |
|
1122 |
|
1123 |fileName imgFileName defaultName rdr i txt suffix| |
|
1124 |
|
1125 defaultName := pathName ? ''. |
|
1126 |
|
1127 pathName isNil ifTrue:[ |
|
1128 suffix := 'tiff'. |
|
1129 (imgFileName := image fileName) notNil ifTrue:[ |
|
1130 suffix := imgFileName asFilename suffix. |
|
1131 defaultName := imgFileName asFilename baseName |
|
1132 ] |
|
1133 ] ifFalse:[ |
|
1134 suffix := pathName asFilename suffix. |
|
1135 "/ a supported suffix ? |
|
1136 ((rdr := Image imageReaderClassForSuffix:suffix) isNil |
|
1137 or:[(rdr canRepresent:anImage) not]) ifTrue:[ |
|
1138 suffix := 'tiff'. |
|
1139 defaultName := (pathName asFilename withSuffix:suffix) pathName |
|
1140 ]. |
|
1141 ]. |
|
1142 |
|
1143 Image cannotRepresentImageSignal handle:[:ex | |
|
1144 self warn:('cannot represent this image in that format.\\(%1)' bindWith:ex errorString) withCRs. |
|
1145 fileName := nil. |
|
1146 ex restart |
|
1147 ] do:[ |
|
1148 fileName := Dialog |
|
1149 requestFileName:(resources string:aTitle) |
|
1150 default:defaultName |
|
1151 ok:(resources string:'save') |
|
1152 abort:(resources string:'abort') |
|
1153 pattern:('*.' , suffix). |
|
1154 |
|
1155 fileName notNil ifTrue:[ |
|
1156 anImage saveOn:fileName. |
|
1157 ]. |
|
1158 ]. |
|
1159 pathName := fileName. |
|
1160 |
|
1161 "Created: / 20.2.1997 / 18:52:08 / cg" |
|
1162 "Modified: / 3.11.1997 / 15:02:27 / cg" |
|
1163 ! |
|
1164 |
|
1165 generateFileAccess |
|
1166 |
|
1167 self createFileName |
|
1168 ifTrue: |
|
1169 [ |
|
1170 |compileString stream| |
|
1171 stream := WriteStream on: ''. |
|
1172 self image storeOn: stream. |
|
1173 compileString := |
|
1174 self resourceSelector, |
|
1175 '\\' withCRs, |
|
1176 ' <resource: #fileImage>\' withCRs, |
|
1177 ' ^Image fromFile:''', |
|
1178 image fileName, ''''. |
|
1179 ByteCodeCompiler compile: compileString forClass: self resourceClass class inCategory: 'image specs'. |
|
1180 ] |
|
1181 ! |
|
1182 |
|
1183 generateImage |
|
1184 |
|
1185 "self createResourceMessage |
|
1186 ifTrue: |
|
1187 [" |
|
1188 |compileString stream| |
|
1189 stream := WriteStream on: ''. |
|
1190 self image storeOn: stream. |
|
1191 compileString := |
|
1192 self resourceSelector, |
|
1193 '\\' withCRs, |
|
1194 ' <resource: #image>\' withCRs, |
|
1195 ' ^', |
|
1196 stream contents. |
|
1197 ByteCodeCompiler compile: compileString forClass: self resourceClass class inCategory: 'image specs'. |
|
1198 "]" |
|
1199 ! |
|
1200 |
|
1201 loadFromClass |
|
1202 |
|
1203 self resourceMessage: (ResourceBrowserView |
|
1204 openOnSuperclass: ApplicationModel |
|
1205 class: self resourceClass |
|
1206 selector: self resourceSelector |
|
1207 resourceTypes: #(#image #fileImage)) |
|
1208 |
|
1209 |
|
1210 ! |
|
1211 |
|
1212 save |
|
1213 |
|
1214 |fileName| |
|
1215 fileName := image fileName. |
|
1216 Object errorSignal handle: |
|
1217 [:exeption| |
|
1218 WarningBox warn: exeption errorString. |
|
1219 ^nil |
|
1220 ] |
|
1221 do: |
|
1222 [ |
|
1223 (fileName suffix = 'tiff') | (fileName suffix = 'tif') ifTrue: [imageReaderClass := TIFFReader]. |
|
1224 fileName suffix = 'xpm' ifTrue: [imageReaderClass := XPMReader]. |
|
1225 fileName suffix = 'xbm' ifTrue: [imageReaderClass := XBMReader]. |
|
1226 fileName suffix = 'gif' ifTrue: [imageReaderClass := GIFReader]. |
|
1227 (fileName suffix = 'jpg') | (fileName suffix = 'jpeg') ifTrue: [imageReaderClass := JPEGReader]. |
|
1228 imageReaderClass isNil ifTrue: [^self error: 'no appropriate image reader found']. |
|
1229 image saveOn: fileName using: imageReaderClass. |
|
1230 modified := false. |
|
1231 ] |
|
1232 |
|
1233 ! |
|
1234 |
|
1235 saveAs |
|
1236 "save contents into a file |
|
1237 - ask user for filename using a fileSelectionBox." |
|
1238 |
|
1239 self doSaveImageAs:image title:'save image in:' |
|
1240 |
|
1241 "Modified: 20.2.1997 / 18:52:37 / cg" |
|
1242 ! |
|
1243 |
|
1244 saveMagnifiedAs |
|
1245 "save contents into a file |
|
1246 - ask user for filename using a fileSelectionBox." |
|
1247 |
|
1248 "self doSaveImageAs:magnifiedImage title:'save magnified image in:' " |
|
1249 |
|
1250 "Created: 20.2.1997 / 18:52:53 / cg" |
|
1251 ! |
|
1252 |
|
1253 saveMagnifiedMaskAs |
|
1254 "save contents into a file |
|
1255 - ask user for filename using a fileSelectionBox." |
|
1256 |
|
1257 "self doSaveImageAs:(magnifiedImage mask) title:'save magnified mask in:'" |
|
1258 |
|
1259 "Created: 20.2.1997 / 18:53:31 / cg" |
|
1260 "Modified: 20.2.1997 / 18:56:48 / cg" |
|
1261 ! |
|
1262 |
|
1263 saveMaskAs |
|
1264 "save contents into a file |
|
1265 - ask user for filename using a fileSelectionBox." |
|
1266 |
|
1267 self doSaveImageAs:(image mask) title:'save mask in:' |
|
1268 |
|
1269 "Created: 20.2.1997 / 18:51:06 / cg" |
|
1270 "Modified: 20.2.1997 / 18:56:54 / cg" |
|
1271 ! ! |
|
1272 |
|
1273 !ImageEditView methodsFor:'queries'! |
|
1274 |
|
1275 heightOfContents |
846 heightOfContents |
1276 "return the images height" |
847 "return the images height" |
1277 |
848 |
1278 image isNil ifTrue:[^ 0]. |
849 image isNil ifTrue:[^ 0]. |
1279 ^ (image height * magnification y) rounded |
850 ^ (image height * magnification y) rounded |
1280 ! |
851 ! |
1281 |
852 |
|
853 imageContainsPoint: aPoint |
|
854 |pi| |
|
855 image isNil ifTrue: [^false]. |
|
856 pi := ((aPoint - margin + 1) / magnification) floor. |
|
857 ^((0@0 corner:(image extent) - 1) containsPoint:pi) |
|
858 ! |
|
859 |
1282 widthOfContents |
860 widthOfContents |
1283 "return the images width" |
861 "return the images width" |
1284 |
862 |
1285 image isNil ifTrue:[^ 0]. |
863 image isNil ifTrue:[^ 0]. |
1286 ^ (image width * magnification x) rounded |
864 ^ (image width * magnification x) rounded |
1287 ! ! |
865 ! ! |
1288 |
866 |
|
867 !ImageEditView methodsFor:'release'! |
|
868 |
|
869 destroy |
|
870 |
|
871 undoImage := nil. |
|
872 Clipboard := nil. |
|
873 super destroy. |
|
874 |
|
875 ! ! |
|
876 |
1289 !ImageEditView class methodsFor:'documentation'! |
877 !ImageEditView class methodsFor:'documentation'! |
1290 |
878 |
1291 version |
879 version |
1292 ^ '$Header: /cvs/stx/stx/libwidg2/ImageEditView.st,v 1.48 1997-11-26 18:53:45 tz Exp $' |
880 ^ '$Header: /cvs/stx/stx/libwidg2/ImageEditView.st,v 1.49 1997-12-03 13:34:40 tz Exp $' |
1293 ! ! |
881 ! ! |