App

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

Image.java
Go to the documentation of this file.
1 package mhr.appcore.image;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.ArrayList;
6 import java.util.LinkedList;
7
8 import org.w3c.dom.Document;
9 import org.w3c.dom.Element;
10 import org.w3c.dom.NodeList;
11
12 import mhr.appcore.bitmap.BitmapInfo;
13 import mhr.appcore.bitmap.ChannelCount;
14 import mhr.appcore.bitmap.ColorMode;
15 import mhr.appcore.bitmap.Depth;
16 import mhr.appcore.bitmap.NBitmap;
17 import mhr.appcore.bitmap.exceptions.BitmapAllocationException;
18 import mhr.appcore.bitmap.exceptions.UnsupportedBitmapException;
19 import mhr.appcore.blending.BlendMode;
20 import mhr.appcore.blending.Blender;
21 import mhr.appcore.exceptions.AllocationException;
22 import mhr.appcore.tools.Tool;
23 import mhr.appcore.image.exceptions.ImageException;
24 import mhr.appcore.image.exceptions.ImageLoadingException;
25 import mhr.appcore.image.exceptions.ImageSavingException;
26 import mhr.appcore.image.exceptions.ImageStateException;
27 import mhr.appcore.image.exceptions.LayerCreationException;
28 import mhr.appcore.image.exceptions.LayerNotFoundException;
29 import mhr.appcore.image.layers.ColorLayer;
30 import mhr.appcore.image.layers.Layer;
31 import mhr.appcore.image.layers.LayerPDInfo;
32 import mhr.appcore.image.layers.LayerType;
33 import mhr.appcore.image.layers.RasterLayer;
34 import mhr.appcore.image.layers.filter.DifferenceOfGaussianSharpenFilterLayer;
35 import mhr.appcore.image.layers.filter.GaussianBlurFilterLayer;
36 import mhr.appcore.image.layers.filter.GaussianSharpenFilterLayer;
37 import mhr.appcore.image.layers.filter.LaplaceSharpenFilterLayer;
38 import mhr.appcore.image.layers.filter.LaplacianOfGaussianSharpenFilterLayer;
39 import mhr.appcore.image.layers.lut.BrightnessLUTLayer;
40 import mhr.appcore.image.layers.lut.ContrastLUTLayer;
41 import mhr.appcore.image.layers.lut.CurvesLUTLayer;
42 import mhr.appcore.image.layers.lut.GammaLUTLayer;
43 import mhr.appcore.interfaces.ImageFile;
44 import mhr.appcore.interfaces.PDBitmap;
45 import mhr.appcore.interfaces.PDImageDataPresentation;
46 import mhr.appcore.interpolators.Interpolator;
47 import mhr.appcore.interpolators.InterpolatorType;
48 import mhr.appcore.utils.Rect;
49
54 public class Image {
55
56 //===== INTERFACES, CLASSES, ENUMS ==========================================================================================================//
57 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
61 protected class FileConstants {
62 public static final String ROOT_NODE = "Image";
63 public static final String INFO_NODE = "ImageInfo";
64 public static final String WIDTH_NODE = "Width";
65 public static final String HEIGHT_NODE = "Height";
66 public static final String DEPTH_NODE = "Depth";
67 public static final String NEXT_ID_NODE = "NextId";
68 public static final String SELECTED_STATE_NODE = "SelectedState";
69 public static final String SELECTED_LAYER_ID_NODE = "SelectedLayerId";
70 public static final String MASTER_MASK_ACTIVE_NODE = "MasterMaskActive";
71 public static final String IMAGE_LAYERS_NODE = "ImageLayers";
72 public static final String LAYER_NODE = "Layer";
73 public static final String LAYER_TYPE_NODE = "LayerType";
74
75 public static final String MASTER_MASK_FILE_NAME = "master_mask";
76 }
77
81 protected class UndoPatch {
82 protected ImageSelectedState state = ImageSelectedState.SELECTED_NONE;
83 protected int id;
84 protected Rect area;
85 protected NBitmap patch = null;
86
91 public Rect getArea() {
92 return new Rect(area);
93 }
94
99 public int getId() {
100 return id;
101 }
102
107 public ImageSelectedState getState() {
108 return state;
109 }
110
118 public UndoPatch(NBitmap from) {
119 state = selectedState;
120 id = selectedLayerId;
121 if (canvasChangedArea.getWidth() > 0 && canvasChangedArea.getHeight() > 0) { // Jinak se nealokuje bitmapa
122 area = new Rect(canvasChangedArea);
123 BitmapInfo i = from.getInfo();
124 patch = new NBitmap(new BitmapInfo(area.getWidth(), area.getHeight(), i.channelCount, i.depth, i.colorMode, i.premultiplied));
125 from.copyTo(patch, area, 0, 0);
126 }
127 }
128
136 public UndoPatch(NBitmap from, Rect fromArea, ImageSelectedState state, int id) {
137 this.state = state;
138 this.id = id;
139 if (fromArea.getWidth() > 0 && fromArea.getHeight() > 0) { // Jinak se nealokuje bitmapa
140 area = new Rect(fromArea);
141 BitmapInfo i = from.getInfo();
142 patch = new NBitmap(new BitmapInfo(area.getWidth(), area.getHeight(), i.channelCount, i.depth, i.colorMode, i.premultiplied));
143 from.copyTo(patch, area, 0, 0);
144 }
145 }
146
151 public boolean apply() {
152 if (patch == null || canvasOwner != null) {
153 return false;
154 }
155 NBitmap target = null;
156 switch (state) {
157 case SELECTED_LAYER:
158 try {
159 Layer l = getLayer(id);
160 target = ((RasterLayer)l).getBitmap();
161 } catch (LayerNotFoundException e) {
162 return false;
163 } catch (ClassCastException e) {
164 throw new ImageException("Bad undo action - not RasterLayer");
165 }
166 break;
167
168 case SELECTED_MASK:
169 try {
170 Layer l = getLayer(id);
171 target = l.getMask(false);
172 } catch (LayerNotFoundException e) {
173 return false;
174 }
175
176 break;
177
178 case SELECTED_MASTER_MASK:
179 target = masterMask;
180 break;
181
182 case SELECTED_NONE:
183 return false;
184 }
185
186 if (target == null ) {
187 return false;
188 }
189
190 NBitmap tmp = new NBitmap(patch.getInfo());
191 target.copyTo(tmp, area, 0, 0);
192 patch.copyTo(target, patch.getRect(), area.tlx, area.tly);
193 patch.dispose();
194 patch = tmp;
195 return true;
196 }
200 public void dispose() {
201 if (patch != null) {
202 patch.dispose();
203 patch = null;
204 }
205 }
206 }
207
208 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
209
210
211
212 //===== FIELDS ==============================================================================================================================//
213 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
214 protected int width;
215 protected int height;
216 protected Depth depth;
217 protected ArrayList<Layer> layers = new ArrayList<Layer>();
218 protected int nextId = 0;
219 protected NBitmap canvas;
220 protected RasterLayer tmpLayer;
221 protected NBitmap masterMask;
222 protected ImageSelectedState selectedState;
223 protected int selectedLayerId;
224 protected boolean masterMaskActive;
225 protected Tool canvasOwner = null;
226
232 protected LinkedList<Rect> toBeRendered = new LinkedList<Rect>();
233 protected Rect canvasChangedArea;
234 protected PDImageDataPresentation pres;
235
239 protected int extraMargins;
240 protected UndoPatch patch = null;
241 protected NBitmap clipBoard = null;
242
243 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
244
245
246 //===== CONSTRUCTORS, DESTRUCTORS, RELATED METHODS ==========================================================================================//
247 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
248 @Override
249 protected void finalize() throws Throwable {
250 dispose();
251 super.finalize();
252 }
253
254 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
261 public Image(PDBitmap from) throws UnsupportedBitmapException, BitmapAllocationException {
262 BitmapInfo i = from.getInfo();
263 if (i.channelCount != ChannelCount.FOUR_CHANNEL) {
264 throw new UnsupportedBitmapException("Could not create image from supplied bitmap");
265 }
266 this.width = i.width;
267 this.height = i.height;
268 this.depth = i.depth;
269
270 RasterLayer l = (RasterLayer) createLayer(RasterLayer.class);
271 NBitmap tmp = new NBitmap(from);
272 tmp.copyTo(l.getBitmap(), tmp.getRect(), 0, 0);
273 tmp.dispose();
274
275 layers.add(l);
276 selectedLayerId = getLastAssignedId();
277 selectedState = ImageSelectedState.SELECTED_LAYER;
278
279 tmpLayer = (RasterLayer) createLayer(RasterLayer.class);
280 masterMask = new NBitmap(new BitmapInfo(width, height, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
281 masterMask.fill(masterMask.getRect(), 0x00);
282
283 canvas = new NBitmap(new BitmapInfo(width, height, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
284 }
285
291 public Image(ImageFile f) throws ImageLoadingException {
292 try {
293
294 FileConstants c = new FileConstants();
295 Document d = null;
296 Element r = null;
297 Element ii = null;
298 Element il = null;
299
300 try {
301 d = f.getDocument();
302 r = (Element) d.getElementsByTagName(c.ROOT_NODE).item(0);
303 ii = (Element) r.getElementsByTagName(c.INFO_NODE).item(0);
304 il = (Element) r.getElementsByTagName(c.IMAGE_LAYERS_NODE).item(0);
305 width = Integer.parseInt(ii.getElementsByTagName(c.WIDTH_NODE).item(0).getTextContent());
306 height = Integer.parseInt(ii.getElementsByTagName(c.HEIGHT_NODE).item(0).getTextContent());
307 depth = Depth.valueOf(ii.getElementsByTagName(c.DEPTH_NODE).item(0).getTextContent());
308 nextId = Integer.parseInt(ii.getElementsByTagName(c.NEXT_ID_NODE).item(0).getTextContent());
309 selectedState = ImageSelectedState.valueOf(ii.getElementsByTagName(c.SELECTED_STATE_NODE).item(0).getTextContent());
310 selectedLayerId = Integer.parseInt(ii.getElementsByTagName(c.SELECTED_LAYER_ID_NODE).item(0).getTextContent());
311 masterMaskActive = Boolean.parseBoolean(ii.getElementsByTagName(c.MASTER_MASK_ACTIVE_NODE).item(0).getTextContent());
312 } catch (ClassCastException e) {
313 throw new ImageLoadingException("Supplied xml doesn't describe image");
314 } catch (NullPointerException e) {
315 throw new ImageLoadingException("Supplied xml doesn't describe image");
316 }
317
318 try {
319 tmpLayer = (RasterLayer) createLayer(RasterLayer.class);
320
321 PDBitmap tmpMask = null;
322 NBitmap tmp = null;
323 try {
324 tmpMask = f.loadBitmap(c.MASTER_MASK_FILE_NAME);
325 tmp = new NBitmap(tmpMask);
326 masterMask = tmp.getChannel(3);
327 tmp.dispose();
328 tmpMask.dispose();
329 } catch (Exception e) {
330 if (tmp != null) {
331 tmp.dispose();
332 }
333 if (tmpMask != null) {
334 tmpMask.dispose();
335 }
336 throw new ImageLoadingException(e);
337 }
338 canvas = new NBitmap(new BitmapInfo(width, height, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
339 } catch (AllocationException e){
340 throw new ImageLoadingException(e);
341 } catch (UnsupportedBitmapException e) {
342 throw new ImageLoadingException(e);
343 }
344
345 NodeList ll = il.getElementsByTagName(c.LAYER_NODE);
346
347 int iMax = ll.getLength();
348
349 if (iMax < 1) {
350 throw new ImageLoadingException("Supplied image file doesn't have layers.");
351 }
352
353 Element li = null;
354 Layer l = null;
355 try {
356 for (int i = 0; i < iMax; i++) {
357 li = (Element) ll.item(i);
358 l = createLayer(getClassFor(LayerType.valueOf(li.getElementsByTagName(c.LAYER_TYPE_NODE).item(0).getTextContent())), li, f);
359 layers.add(l);
360 }
361 } catch (AllocationException e) {
362 throw new ImageLoadingException(e);
363 } catch (LayerCreationException e) {
364 throw new ImageLoadingException(e);
365 }
366 requeryExrtaMargins();
367 } catch (ImageLoadingException e) {
368 dispose();
369 throw new ImageLoadingException("Could not load image.", e);
370 }
371 }
372
377 public int dispose() {
378 for (Layer l : layers) {
379 l.dispose();
380 }
381 layers.clear();
382 masterMask.dispose();
383 canvas.dispose();
384 tmpLayer.dispose();
385 if (patch != null) {
386 patch.dispose();
387 }
388 if (clipBoard != null) {
389 clipBoard.dispose();
390 }
391 return 0;
392 }
393
394
395 //===== METHODS =============================================================================================================================//
396 //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
401 protected int assignId() {
402 return nextId++;
403 }
404
409 protected int getLastAssignedId() {
410 return nextId - 1;
411 }
412
417 protected void addChangedArea(Rect area) {
418 synchronized (toBeRendered) {
419 toBeRendered.add(area);
420 toBeRendered.notifyAll();
421 }
422 }
423
430 protected int getLayerPosition(int id) throws LayerNotFoundException {
431 Layer l = getLayer(id);
432 return layers.indexOf(l);
433 }
434
440 protected Class<? extends Layer> getClassFor(LayerType type) {
441 switch (type) {
442 case LAYER_RASTER:
443 return RasterLayer.class;
444 case LAYER_COLOR:
445 return ColorLayer.class;
446 case LAYER_BRIGHTNESS:
447 return BrightnessLUTLayer.class;
448 case LAYER_CONTRAST:
449 return ContrastLUTLayer.class;
450 case LAYER_GAMMA:
451 return GammaLUTLayer.class;
452 case LAYER_CURVES:
453 return CurvesLUTLayer.class;
454 case LAYER_GAUSSIAN_BLUR:
455 return GaussianBlurFilterLayer.class;
456 case LAYER_LAPLACE_SHARPEN:
457 return LaplaceSharpenFilterLayer.class;
458 case LAYER_GAUSSIAN_SHARPEN:
459 return GaussianSharpenFilterLayer.class;
460 case LAYER_LAPLACIAN_OF_GAUSSIAN_SHARPEN:
461 return LaplacianOfGaussianSharpenFilterLayer.class;
462 case LAYER_DIFFERENCE_OF_GAUSSIAN_SHARPEN:
463 return DifferenceOfGaussianSharpenFilterLayer.class;
464 default:
465 return null;
466 }
467 }
468
479 protected Layer createLayer(Class<? extends Layer> cls) throws ImageException {
480 try {
481 Constructor<? extends Layer> ctor = cls.getConstructor(new Class[] { Image.class, int.class });
482 return ctor.newInstance(new Object[] { this, assignId() });
483 } catch (NoSuchMethodException exc) {
484 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
485 } catch (IllegalAccessException exc) {
486 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
487 } catch (IllegalArgumentException exc) {
488 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
489 } catch (InstantiationException exc) {
490 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
491 } catch (InvocationTargetException exc) {
492 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
493 } catch (ExceptionInInitializerError exc) {
494 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
495 }
496 }
497
506 protected Layer createLayer(Class<? extends Layer> cls, Element info, ImageFile file) throws ImageException {
507 try {
508 Constructor<? extends Layer> ctor = cls.getConstructor(new Class[] { Image.class, Element.class, ImageFile.class });
509 return ctor.newInstance(new Object[] { this, info, file});
510 } catch (NoSuchMethodException exc) {
511 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
512 } catch (IllegalAccessException exc) {
513 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
514 } catch (IllegalArgumentException exc) {
515 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
516 } catch (InstantiationException exc) {
517 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
518 } catch (InvocationTargetException exc) {
519 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
520 } catch (ExceptionInInitializerError exc) {
521 throw new ImageException("Layer not created, reflection failed due to: " + exc.toString() + " " + exc.getMessage());
522 }
523 }
524
532 protected void appendLeafElement(Document d, Element parent, String eName, String eContetnt) {
533 Element e = d.createElement(eName);
534 e.setTextContent(eContetnt);
535 parent.appendChild(e);
536 }
537
538 //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
539
543 public void mergeAll() {
544 if (canvasOwner != null) {
545 return;
546 }
547 RasterLayer merged = new RasterLayer(this, assignId());
548 NBitmap dst = merged.getBitmap();
549 for (Layer l : layers) {
550 l.applyTo(dst, getRect(), 0, 0);
551 l.dispose();
552 }
553 layers = new ArrayList<Layer>();
554 layers.add(merged);
555
556 selectedLayerId = merged.getId();
557
558 setPresentation(pres);
559
560 if (pres != null) {
561 pres.hasChanged();
562 }
563
564 }
565
571 public void clear(ImageSelectedState item, int itemId) {
572 if (canvasOwner != null) {
573 return;
574 }
575
576 NBitmap target = null;
577 switch (item) {
578 case SELECTED_LAYER:
579 try {
580 Layer l = getLayer(itemId);
581 target = ((RasterLayer)l).getBitmap();
582 } catch (LayerNotFoundException e) {
583 return;
584 } catch (ClassCastException e) {
585 return;
586 }
587 break;
588
589 case SELECTED_MASK:
590 try {
591 Layer l = getLayer(itemId);
592 target = l.getMask(true);
593 } catch (LayerNotFoundException e) {
594 return;
595 }
596
597 break;
598
599 case SELECTED_MASTER_MASK:
600 target = masterMask;
601 break;
602
603 case SELECTED_NONE:
604 return;
605 }
606
607 if (target == null ) {
608 return; // maska neexistuje, jiny problem
609 }
610
611 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
612
613 try {
614 if (masterMaskActive) {
615 if (item == ImageSelectedState.SELECTED_LAYER) {
616 Blender.removeFrom4ch(target, masterMask, target.getRect(), 0, 0);
617 } else {
618 Blender.removeFrom(target, masterMask, target.getRect(), 0, 0);
619 }
620 } else {
621 target.fill(target.getRect(), 0x00);
622 }
623 } catch (IllegalArgumentException e) {
624 tmpPatch.dispose();
625 return;
626 }
627
628 if (patch != null) {
629 patch.dispose();
630 patch = tmpPatch;
631 }
632
633 addChangedArea(getRect());
634
635 if (pres != null) {
636 synchronized (pres) {
637 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
638 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
639 pres.hasChanged();
640 } else {
641 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
642 Interpolator.resampleTo(masterMask, mskThumbWrap);
643 mskThumbWrap.dispose();
644 }
645 }
646 }
647 return;
648 }
649
655 public void fill(ImageSelectedState item, int itemId) {
656 if (canvasOwner != null) {
657 return;
658 }
659
660 NBitmap target = null;
661 switch (item) {
662 case SELECTED_LAYER:
663 return;
664
665 case SELECTED_MASK:
666 try {
667 Layer l = getLayer(itemId);
668 target = l.getMask(true);
669 } catch (LayerNotFoundException e) {
670 return;
671 }
672
673 break;
674
675 case SELECTED_MASTER_MASK:
676 target = masterMask;
677 break;
678
679 case SELECTED_NONE:
680 return;
681 }
682
683 if (target == null ) {
684 return; // maska neexistuje, jiny problem
685 }
686
687 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
688
689 try {
690 if (masterMaskActive) {
691 Blender.addTo(target, masterMask, target.getRect(), 0, 0);
692 } else {
693 target.fill(target.getRect(), 0xFFFFFFFF);
694 }
695 } catch (IllegalArgumentException e) {
696 tmpPatch.dispose();
697 return;
698 }
699
700 if (patch != null) {
701 patch.dispose();
702 patch = tmpPatch;
703 }
704
705 addChangedArea(getRect());
706
707 if (pres != null) {
708 synchronized (pres) {
709 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
710 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
711 pres.hasChanged();
712 } else {
713 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
714 Interpolator.resampleTo(masterMask, mskThumbWrap);
715 mskThumbWrap.dispose();
716 }
717 }
718 }
719 return;
720 }
721
727 public void invertMask(ImageSelectedState item, int itemId) {
728 if (canvasOwner != null) {
729 return;
730 }
731
732 NBitmap target = null;
733 switch (item) {
734 case SELECTED_LAYER:
735 return;
736
737 case SELECTED_MASK:
738 try {
739 Layer l = getLayer(itemId);
740 target = l.getMask(true);
741 } catch (LayerNotFoundException e) {
742 return;
743 }
744
745 break;
746
747 case SELECTED_MASTER_MASK:
748 target = masterMask;
749 break;
750
751 case SELECTED_NONE:
752 return;
753 }
754
755 if (target == null ) {
756 return; // maska neexistuje, jiny problem
757 }
758
759 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
760
761 try {
762 if (masterMaskActive) {
763 NBitmap tmp = null;
764 try {
765 tmp = new NBitmap(target);
766 Blender.addTo(target, masterMask, target.getRect(), 0, 0);
767 Blender.removeFrom(target, masterMask, tmp, target.getRect(), 0, 0, 0, 0);
768 } finally {
769 if (tmp != null) {
770 tmp.dispose();
771 }
772 }
773 } else {
774 NBitmap tmp = null;
775 try {
776 tmp = new NBitmap(target);
777 target.fill(target.getRect(), 0xFFFFFFFF);
778 Blender.removeFrom(target, tmp, target.getRect(), 0, 0);
779 } finally {
780 if (tmp != null) {
781 tmp.dispose();
782 }
783 }
784 }
785 } catch (IllegalArgumentException e) {
786 tmpPatch.dispose();
787 return;
788 }
789
790 if (patch != null) {
791 patch.dispose();
792 patch = tmpPatch;
793 }
794
795 addChangedArea(getRect());
796
797 if (pres != null) {
798 synchronized (pres) {
799 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
800 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
801 pres.hasChanged();
802 } else {
803 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
804 Interpolator.resampleTo(masterMask, mskThumbWrap);
805 mskThumbWrap.dispose();
806 }
807 }
808 }
809 return;
810 }
811
817 public void toClipBoard(ImageSelectedState item, int itemId) {
818 if (clipBoard != null) {
819 clipBoard.dispose();
820 clipBoard = null;
821 }
822
823 NBitmap source = null;
824 switch (item) {
825 case SELECTED_LAYER:
826 try {
827 Layer l = getLayer(itemId);
828 source = ((RasterLayer)l).getBitmap();
829 } catch (LayerNotFoundException e) {
830 return;
831 } catch (ClassCastException e) {
832 return;
833 }
834 break;
835
836 case SELECTED_MASK:
837 try {
838 Layer l = getLayer(itemId);
839 source = l.getMask(false);
840 } catch (LayerNotFoundException e) {
841 return;
842 }
843
844 break;
845
846 case SELECTED_MASTER_MASK:
847 source = masterMask;
848 break;
849
850 case SELECTED_NONE:
851 return;
852 }
853
854 if (source == null ) {
855 return;
856 }
857
858 if (masterMaskActive) {
859 BitmapInfo i = source.getInfo();
860 clipBoard = new NBitmap(i);
861 clipBoard.fill(clipBoard.getRect(), 0x0);
862 if (i.channelCount == ChannelCount.SINGLE_CHANNEL) {
863 Blender.addTo(clipBoard, masterMask, source, masterMask.getRect(), 0, 0, 0, 0);
864 } else if (i.channelCount == ChannelCount.FOUR_CHANNEL) {
865 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, clipBoard, masterMask, source, masterMask.getRect(), 0, 0, 0, 0);
866 }
867 } else {
868 clipBoard = new NBitmap(source);
869 }
870 return;
871 }
872
878 public void fromClipBoard(ImageSelectedState item, int itemId) {
879 if (clipBoard == null || canvasOwner != null) {
880 return;
881 }
882
883 NBitmap target = null;
884 switch (item) {
885 case SELECTED_LAYER:
886 try {
887 Layer l = getLayer(itemId);
888 target = ((RasterLayer)l).getBitmap();
889 } catch (LayerNotFoundException e) {
890 return;
891 } catch (ClassCastException e) {
892 return;
893 }
894 break;
895
896 case SELECTED_MASK:
897 try {
898 Layer l = getLayer(itemId);
899 target = l.getMask(true);
900 } catch (LayerNotFoundException e) {
901 return;
902 }
903
904 break;
905
906 case SELECTED_MASTER_MASK:
907 target = masterMask;
908 break;
909
910 case SELECTED_NONE:
911 return;
912 }
913
914 if (target == null ) {
915 return; // maska neexistuje, jiny problem
916 }
917
918 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
919
920 try {
921 if (masterMaskActive) {
922 if (item == ImageSelectedState.SELECTED_LAYER) {
923 if (clipBoard.getInfo().channelCount != ChannelCount.FOUR_CHANNEL) {
924 tmpPatch.dispose();
925 return;
926 }
927 Blender.removeFrom4ch(target, masterMask, target.getRect(), 0, 0);
928 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
929 } else {
930 if (clipBoard.getInfo().channelCount != ChannelCount.SINGLE_CHANNEL) {
931 tmpPatch.dispose();
932 return;
933 }
934 Blender.removeFrom(target, masterMask, target.getRect(), 0, 0);
935 Blender.addTo(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
936 }
937 } else {
938 clipBoard.copyTo(target, getRect(), 0, 0);
939 }
940 } catch (IllegalArgumentException e) {
941 tmpPatch.dispose();
942 return;
943 }
944
945 if (patch != null) {
946 patch.dispose();
947 patch = tmpPatch;
948 }
949
950 addChangedArea(getRect());
951
952 if (pres != null) {
953 synchronized (pres) {
954 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
955 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
956 pres.hasChanged();
957 } else {
958 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
959 Interpolator.resampleTo(masterMask, mskThumbWrap);
960 mskThumbWrap.dispose();
961 }
962 }
963 }
964 return;
965 }
966
972 public void addClipBoard(ImageSelectedState item, int itemId) {
973 if (clipBoard == null || canvasOwner != null) {
974 return;
975 }
976
977 NBitmap target = null;
978 switch (item) {
979 case SELECTED_LAYER:
980 try {
981 Layer l = getLayer(itemId);
982 target = ((RasterLayer)l).getBitmap();
983 } catch (LayerNotFoundException e) {
984 return;
985 } catch (ClassCastException e) {
986 return;
987 }
988 break;
989
990 case SELECTED_MASK:
991 try {
992 Layer l = getLayer(itemId);
993 target = l.getMask(true);
994 } catch (LayerNotFoundException e) {
995 return;
996 }
997
998 break;
999
1000 case SELECTED_MASTER_MASK:
1001 target = masterMask;
1002 break;
1003
1004 case SELECTED_NONE:
1005 return;
1006 }
1007
1008 if (target == null ) {
1009 return; // maska neexistuje, jiny problem
1010 }
1011
1012 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1013
1014 try {
1015 if (masterMaskActive) {
1016 if (item == ImageSelectedState.SELECTED_LAYER) {
1017 Blender.addTo4ch(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1018 } else {
1019 Blender.addTo(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1020 }
1021 } else {
1022 if (item == ImageSelectedState.SELECTED_LAYER) {
1023 Blender.addTo4ch(target, clipBoard, target.getRect(), 0, 0);
1024 } else {
1025 Blender.addTo(target, clipBoard, target.getRect(), 0, 0);
1026 }
1027 }
1028 } catch (IllegalArgumentException e) {
1029 tmpPatch.dispose();
1030 return;
1031 }
1032
1033 if (patch != null) {
1034 patch.dispose();
1035 patch = tmpPatch;
1036 }
1037
1038 addChangedArea(getRect());
1039
1040 if (pres != null) {
1041 synchronized (pres) {
1042 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
1043 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1044 pres.hasChanged();
1045 } else {
1046 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1047 Interpolator.resampleTo(masterMask, mskThumbWrap);
1048 mskThumbWrap.dispose();
1049 }
1050 }
1051 }
1052 return;
1053 }
1054
1060 public void removeClipBoard(ImageSelectedState item, int itemId) {
1061 if (clipBoard == null || canvasOwner != null) {
1062 return;
1063 }
1064
1065 NBitmap target = null;
1066 switch (item) {
1067 case SELECTED_LAYER:
1068 try {
1069 Layer l = getLayer(itemId);
1070 target = ((RasterLayer)l).getBitmap();
1071 } catch (LayerNotFoundException e) {
1072 return;
1073 } catch (ClassCastException e) {
1074 return;
1075 }
1076 break;
1077
1078 case SELECTED_MASK:
1079 try {
1080 Layer l = getLayer(itemId);
1081 target = l.getMask(true);
1082 } catch (LayerNotFoundException e) {
1083 return;
1084 }
1085
1086 break;
1087
1088 case SELECTED_MASTER_MASK:
1089 target = masterMask;
1090 break;
1091
1092 case SELECTED_NONE:
1093 return;
1094 }
1095
1096 if (target == null ) {
1097 return; // maska neexistuje, jiny problem
1098 }
1099
1100 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1101
1102 try {
1103 if (masterMaskActive) {
1104 if (item == ImageSelectedState.SELECTED_LAYER) {
1105 Blender.removeFrom4ch(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1106 } else {
1107 Blender.removeFrom(target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1108 }
1109 } else {
1110 if (item == ImageSelectedState.SELECTED_LAYER) {
1111 Blender.removeFrom4ch(target, clipBoard, target.getRect(), 0, 0);
1112 } else {
1113 Blender.removeFrom(target, clipBoard, target.getRect(), 0, 0);
1114 }
1115 }
1116 } catch (IllegalArgumentException e) {
1117 tmpPatch.dispose();
1118 return;
1119 }
1120
1121 if (patch != null) {
1122 patch.dispose();
1123 patch = tmpPatch;
1124 }
1125
1126 addChangedArea(getRect());
1127
1128 if (pres != null) {
1129 synchronized (pres) {
1130 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
1131 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1132 pres.hasChanged();
1133 } else {
1134 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1135 Interpolator.resampleTo(masterMask, mskThumbWrap);
1136 mskThumbWrap.dispose();
1137 }
1138 }
1139 }
1140 return;
1141 }
1142
1148 public void blendClipBoard(ImageSelectedState item, int itemId) {
1149 if (clipBoard == null || canvasOwner != null) {
1150 return;
1151 }
1152
1153 NBitmap target = null;
1154 switch (item) {
1155 case SELECTED_LAYER:
1156 try {
1157 Layer l = getLayer(itemId);
1158 target = ((RasterLayer)l).getBitmap();
1159 } catch (LayerNotFoundException e) {
1160 return;
1161 } catch (ClassCastException e) {
1162 return;
1163 }
1164 break;
1165
1166 case SELECTED_MASK:
1167 return;
1168
1169 case SELECTED_MASTER_MASK:
1170 return;
1171
1172 case SELECTED_NONE:
1173 return;
1174 }
1175
1176 if (target == null ) {
1177 return; // maska neexistuje, jiny problem
1178 }
1179
1180 UndoPatch tmpPatch = new UndoPatch(target, target.getRect(), selectedState, itemId);
1181
1182 try {
1183 if (masterMaskActive) {
1184 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, target, masterMask, clipBoard, target.getRect(), 0, 0, 0, 0);
1185 } else {
1186 Blender.blendTo(BlendMode.BLEND_MODE_NORMAL, target, clipBoard, target.getRect(), 0, 0);
1187 }
1188 } catch (IllegalArgumentException e) {
1189 tmpPatch.dispose();
1190 return;
1191 }
1192
1193 if (patch != null) {
1194 patch.dispose();
1195 patch = tmpPatch;
1196 }
1197
1198 addChangedArea(getRect());
1199
1200 if (pres != null) {
1201 synchronized (pres) {
1202 if (item != ImageSelectedState.SELECTED_MASTER_MASK) {
1203 getLayer(itemId).updateInfo(pres.getLayerInfo(itemId));
1204 pres.hasChanged();
1205 } else {
1206 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1207 Interpolator.resampleTo(masterMask, mskThumbWrap);
1208 mskThumbWrap.dispose();
1209 }
1210 }
1211 }
1212 return;
1213 }
1214
1215
1216
1226 public void resizeTo(int nWidth, int nHeight, InterpolatorType iType, double force) throws ImageStateException, BitmapAllocationException {
1227 if (canvasOwner != null) {
1228 throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1229 }
1230 NBitmap tmp;
1231 tmp = new NBitmap(new BitmapInfo(nWidth, nHeight, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
1232 Interpolator.resampleTo(canvas, tmp, iType, force);
1233 canvas.dispose();
1234 canvas = tmp;
1235
1236 tmp = new NBitmap(new BitmapInfo(nWidth, nHeight, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
1237 Interpolator.resampleTo(masterMask, tmp, iType, force);
1238 masterMask.dispose();
1239 masterMask = tmp;
1240
1241 tmpLayer.resizeTo(nWidth, nHeight, iType, force);
1242
1243 for (Layer l : layers) {
1244 l.resizeTo(nWidth, nHeight, iType, force);
1245 }
1246
1247 width = tmpLayer.getWidth();
1248 height = tmpLayer.getHeight();
1249
1250 if (patch != null) {
1251 patch.dispose();
1252 patch = null;
1253 }
1254
1255 if (clipBoard != null) {
1256 clipBoard.dispose();
1257 clipBoard = null;
1258 }
1259
1260 addChangedArea(getRect());
1261
1262 if (pres != null) {
1263 synchronized (pres) {
1264 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1265 Interpolator.resampleTo(masterMask, mskThumbWrap);
1266 mskThumbWrap.dispose();
1267
1268 for (int i = 0; i < layers.size(); i++) {
1269 Layer l = layers.get(i);
1270 l.updateInfo(pres.getLayerInfo(l.getId()));
1271 }
1272 pres.hasChanged();
1273 }
1274 }
1275 }
1276
1283 public void cropTo(Rect r) throws ImageStateException, BitmapAllocationException {
1284 if (canvasOwner != null) {
1285 throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1286 }
1287
1288 Rect crop = r.cropBy(getRect());
1289
1290 if (crop.getWidth() <= 0 || crop.getHeight() <= 0) {
1291 return;
1292 }
1293
1294 canvas.cropTo(r);
1295 masterMask.cropTo(r);
1296 tmpLayer.cropTo(r);
1297
1298 for (Layer l : layers) {
1299 l.cropTo(r);
1300 }
1301
1302 width = tmpLayer.getWidth();
1303 height = tmpLayer.getHeight();
1304
1305 if (patch != null) {
1306 patch.dispose();
1307 patch = null;
1308 }
1309
1310 if (clipBoard != null) {
1311 clipBoard.dispose();
1312 clipBoard = null;
1313 }
1314
1315 addChangedArea(getRect());
1316
1317 if (pres != null) {
1318 synchronized (pres) {
1319 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1320 Interpolator.resampleTo(masterMask, mskThumbWrap);
1321 mskThumbWrap.dispose();
1322
1323 for (int i = 0; i < layers.size(); i++) {
1324 Layer l = layers.get(i);
1325 l.updateInfo(pres.getLayerInfo(l.getId()));
1326 }
1327 pres.hasChanged();
1328 }
1329 }
1330 }
1331
1336 public void exportToFile(ImageFile f) {
1337 FileConstants c = new FileConstants();
1338 Document d = null;
1339 Element r = null;
1340 Element e = null;
1341
1342 Element ii = null;
1343 Element il = null;
1344 try {
1345 d = f.getDocument();
1346
1347 r = d.createElement(c.ROOT_NODE);
1348 d.appendChild(r);
1349
1350 ii = d.createElement(c.INFO_NODE);
1351 r.appendChild(ii);
1352
1353 il = d.createElement(c.IMAGE_LAYERS_NODE);
1354 r.appendChild(il);
1355
1356 appendLeafElement(d, ii, c.WIDTH_NODE, Integer.toString(width));
1357 appendLeafElement(d, ii, c.HEIGHT_NODE, Integer.toString(height));
1358 appendLeafElement(d, ii, c.DEPTH_NODE, depth.toString());
1359 appendLeafElement(d, ii, c.NEXT_ID_NODE, Integer.toString(nextId));
1360 appendLeafElement(d, ii, c.SELECTED_STATE_NODE, selectedState.toString());
1361 appendLeafElement(d, ii, c.SELECTED_LAYER_ID_NODE, Integer.toString(selectedLayerId));
1362 appendLeafElement(d, ii, c.MASTER_MASK_ACTIVE_NODE, Boolean.toString(masterMaskActive));
1363 } catch (Exception exc) {
1364 throw new ImageSavingException(exc);
1365 }
1366 try {
1367 for (Layer l : layers) {
1368 e = d.createElement(c.LAYER_NODE);
1369 l.fillLayerElement(d, f, e);
1370 il.appendChild(e);
1371 }
1372 } catch (Exception exc) {
1373 throw new ImageSavingException(exc);
1374 }
1375 PDBitmap tmpBitmap = null;
1376 NBitmap tmpWrap = null;
1377 try {
1378 tmpBitmap = f.createBitmap(new BitmapInfo(width, height, ChannelCount.SINGLE_CHANNEL, depth, ColorMode.MONO, false));
1379 tmpWrap = new NBitmap(tmpBitmap);
1380 masterMask.copyTo(tmpWrap, masterMask.getRect(), 0, 0);
1381 tmpWrap.dispose();
1382 f.writeMask(tmpBitmap, c.MASTER_MASK_FILE_NAME);
1383 tmpBitmap.dispose();
1384 } catch (Exception exc) {
1385 if (tmpWrap != null) {
1386 tmpWrap.dispose();
1387 }
1388 if (tmpBitmap != null) {
1389 tmpBitmap.dispose();
1390 }
1391 throw new ImageSavingException(exc);
1392 }
1393 try {
1394 f.writeDocument();
1395 } catch (Exception exc) {
1396 throw new ImageSavingException(exc);
1397 }
1398 }
1399
1403 public void applyUndoPatch() {
1404 if (patch != null) {
1405 if (patch.apply()) {
1406 addChangedArea(patch.getArea());
1407
1408 if (pres != null) {
1409 synchronized (pres) {
1410 if (patch.getState() != ImageSelectedState.SELECTED_MASTER_MASK) {
1411 getLayer(patch.getId()).updateInfo(pres.getLayerInfo(patch.getId()));
1412 pres.hasChanged();
1413 } else {
1414 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1415 Interpolator.resampleTo(masterMask, mskThumbWrap);
1416 mskThumbWrap.dispose();
1417 }
1418 }
1419 }
1420 }
1421 }
1422 }
1423
1424
1429 public int getWidth() {
1430 return width;
1431 }
1432
1437 public int getHeight() {
1438 return height;
1439 }
1440
1445 public Depth getDepth() {
1446 return depth;
1447 }
1448
1453 public Rect getRect() {
1454 return new Rect(width, height);
1455 }
1456
1461 public PDImageDataPresentation getPresentation() {
1462 return pres;
1463 }
1464
1469 public void setPresentation(PDImageDataPresentation pres) {
1470 this.pres = pres;
1471 if (pres == null) {
1472 return;
1473 }
1474 synchronized (pres) {
1475 pres.selectedLayerId = selectedLayerId;
1476 pres.selectedState = selectedState;
1477
1478 pres.masterMaskActive = masterMaskActive;
1479 pres.masterMask = pres.createMaskThumb();
1480 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1481 Interpolator.resampleTo(masterMask, mskThumbWrap);
1482 mskThumbWrap.dispose();
1483
1484 pres.getLayers().clear();
1485 for (int i = 0; i < layers.size(); i++) {
1486 Layer l = layers.get(i);
1487 LayerPDInfo inf = new LayerPDInfo(pres);
1488 l.updateInfo(inf);
1489 pres.addLayerInfo(inf);
1490 }
1491 }
1492 }
1493
1498 public ImageSelectedState getSelectedState() {
1499 return selectedState;
1500 }
1501
1502 public Tool getCanvasOwner() {
1503 return canvasOwner;
1504 }
1505
1512 public int setSelectedState(ImageSelectedState state, int layerId) throws LayerNotFoundException {
1513 if (canvasOwner != null) {
1514 throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1515 }
1516 if (state != selectedState) {
1517 addChangedArea(getRect());
1518 }
1519 switch (state) {
1520 case SELECTED_NONE:
1521 // Toto by nemel byt spravny zpusob uziti
1522 selectedLayerId = -1;
1523 break;
1524 case SELECTED_LAYER: {
1525 Layer l = getLayer(layerId);
1526 selectedLayerId = layerId;
1527 break;
1528 }
1529 case SELECTED_MASK: {
1530 Layer l = getLayer(layerId);
1531 selectedLayerId = layerId;
1532 addChangedArea(getRect()); // Kvůli náhledu masky
1533 break;
1534 }
1535 case SELECTED_MASTER_MASK:
1536 selectedLayerId = -1;
1537 addChangedArea(getRect()); // Kvůli náhledu masky
1538 break;
1539 default:
1540 }
1541 selectedState = state;
1542 if (pres != null) {
1543 synchronized (pres) {
1544 pres.selectedState = state;
1545 pres.selectedLayerId = selectedLayerId;
1546 pres.hasChanged();
1547 }
1548 }
1549 return 0;
1550 }
1551
1558 public Layer getLayer(int id) throws LayerNotFoundException {
1559 for (Layer l : layers) {
1560 if (l.getId() == id) {
1561 return l;
1562 }
1563 }
1564 throw new LayerNotFoundException("Layer with id " + id + " doesn't exist");
1565 }
1566
1567 // Musí mít zastavený displayer - pokud se změní uprostřed vykonávání, může posunout výstup
1568 public void requeryExrtaMargins() {
1569 int extra = 0;
1570 int tmp;
1571 for (Layer l : layers) {
1572 tmp = l.getExtraMargin();
1573 extra = Math.max(extra, tmp);
1574 }
1575 extraMargins = extra;
1576 }
1577
1582 public boolean isMasterMaskActive() {
1583 return masterMaskActive;
1584 }
1585
1590 public void setMasterMaskActive(boolean active) {
1591 masterMaskActive = active;
1592 if (pres != null) {
1593 pres.masterMaskActive = active;
1594 pres.hasChanged();
1595 }
1596 }
1597
1602 public NBitmap getMasterMask() {
1603 return masterMask;
1604 }
1605
1612 public void setLayerMaskActive(int layerId, boolean active) throws LayerNotFoundException {
1613 Layer l = getLayer(layerId);
1614 l.setMaskActive(active);
1615 if (pres != null) {
1616 LayerPDInfo i = pres.getLayerInfo(layerId);
1617 l.updateInfo(i);
1618 pres.hasChanged();
1619 }
1620 addChangedArea(getRect());
1621 }
1622
1630 public void setLayerOpacity(int layerId, double opacity) throws LayerNotFoundException {
1631 Layer l = getLayer(layerId);
1632 l.setOpacity(opacity);
1633 if (pres != null) {
1634 LayerPDInfo i = pres.getLayerInfo(layerId);
1635 l.updateInfo(i);
1636 pres.hasChanged();
1637 }
1638 if (l.isVisible()) {
1639 addChangedArea(getRect());
1640 }
1641 }
1642
1650 public int setLayerVisibility(int layerId, boolean visibility) throws LayerNotFoundException {
1651 Layer l = getLayer(layerId);
1652 l.setVisible(visibility);
1653 if (pres != null) {
1654 synchronized (pres) {
1655 LayerPDInfo inf = pres.getLayerInfo(layerId);
1656 l.updateInfo(inf);
1657 pres.hasChanged();
1658 }
1659 }
1660 addChangedArea(getRect());
1661 return 0;
1662 }
1663
1671 public int createLayer(LayerType type, int overLayerWithId) throws LayerNotFoundException {
1672 if (selectedState == ImageSelectedState.SELECTED_MASTER_MASK) {
1673 overLayerWithId = layers.get(layers.size() - 1).getId();
1674 }
1675 Layer l = createLayer(getClassFor(type));
1676 layers.add(getLayerPosition(overLayerWithId) + 1, l);
1677 if (pres != null) {
1678 synchronized (pres) {
1679 LayerPDInfo inf = new LayerPDInfo(pres);
1680 l.updateInfo(inf);
1681 pres.addLayerInfo(inf, overLayerWithId);
1682 pres.hasChanged();
1683 }
1684 }
1685 return 0;
1686 }
1687
1688 public int duplicateLayer(int layerId) {
1689 Layer ol = getLayer(layerId);
1690 Layer nl = ol.duplicate(assignId());
1691 layers.add(getLayerPosition(layerId) + 1, nl);
1692 addChangedArea(getRect());
1693 if (pres != null) {
1694 synchronized (pres) {
1695 LayerPDInfo inf = new LayerPDInfo(pres);
1696 nl.updateInfo(inf);
1697 pres.addLayerInfo(inf, layerId);
1698 pres.hasChanged();
1699 }
1700 }
1701 return 0;
1702 }
1703
1711 public int deleteLayer(int layerId) throws LayerNotFoundException, ImageStateException {
1712 if (layers.size() == 1) {
1713 // Nelze odstranit poslední vrstvu.
1714 throw new ImageStateException("Could not deleta last layer");
1715 }
1716 Layer l = getLayer(layerId);
1717 // Aktivujeme vrstvu, ktera byla pod ni, pokud byla vrstva vubec vybrana... ID je platne, ptz jinak getLayer hodi vyjimku
1718 if (layerId == selectedLayerId) {
1719 if (canvasOwner != null) {
1720 throw new ImageStateException("Canvas transaction already pending"); // Nastroj by se aplikoval na vrstvu, na kterou nemusi byt pouzitelny
1721 }
1722 int oldIndex = layers.indexOf(l);
1723 if (oldIndex > 0) {
1724 selectedLayerId = layers.get(oldIndex - 1).getId();
1725 } else {
1726 selectedLayerId = layers.get(1).getId();
1727 }
1728 }
1729 l.dispose();
1730 layers.remove(l);
1731 addChangedArea(getRect());
1732 requeryExrtaMargins();
1733 if (pres != null) {
1734 synchronized (pres) {
1735 pres.removeLayer(layerId);
1736 pres.selectedLayerId = selectedLayerId;
1737 pres.hasChanged();
1738 }
1739 }
1740 return 0;
1741 }
1742
1750 public int moveLayer(int layerId, int beforeLayerWithId) throws LayerNotFoundException {
1751 Layer l = getLayer(layerId);
1752 int oldIndex = layers.indexOf(l);
1753 int newIndex = (beforeLayerWithId < 0) ? layers.size() : layers.indexOf(getLayer(beforeLayerWithId));
1754 layers.remove(l);
1755 if (oldIndex < newIndex) {
1756 newIndex--;
1757 }
1758 layers.add(newIndex, l);
1759 if (pres != null) {
1760 synchronized (pres) {
1761 pres.moveLayer(layerId, beforeLayerWithId);
1762 pres.hasChanged();
1763 }
1764 }
1765 addChangedArea(getRect());
1766 return 0;
1767 }
1768
1773 public void updateLayerFromSpecificPresentation(int layerId) {
1774 Layer l = getLayer(layerId);
1775 synchronized (pres) {
1776 l.updateFromSpecificPresentation(pres.getLayerInfo(layerId));
1777 pres.hasChanged();
1778 }
1779 addChangedArea(getRect());
1780 }
1781
1791 public NBitmap prepareCanvas(Tool tool, ChannelCount chCount) throws IllegalStateException, ImageException, ImageStateException{
1792 if (canvasOwner != null) {
1793 throw new IllegalStateException("Canvas is already pending.");
1794 }
1795 if (selectedState == ImageSelectedState.SELECTED_LAYER || selectedState == ImageSelectedState.SELECTED_MASK) {
1796 Layer l = getLayer(selectedLayerId);
1797 if (selectedState == ImageSelectedState.SELECTED_LAYER) {
1798 if (!(l instanceof RasterLayer)) {
1799 throw new ImageStateException("Selected layer doesn't support canvas"); // Pouze RasterLayer muze ziskat canvas, ostatni vrstvy nemaji co reagovat na kresleni...
1800 }
1801 tmpLayer.setMode(((RasterLayer) l).getMode());
1802 }
1803 if (selectedState == ImageSelectedState.SELECTED_LAYER ) {
1804 if (!l.isVisible()) {
1805 throw new ImageStateException("Selected layer is invisible");
1806 }
1807 }
1808 tmpLayer.setVisible(l.isVisible());
1809 tmpLayer.setMaskActive(l.isMaskActive());
1810 tmpLayer.setOpacity(l.getOpacity());
1811 }
1812 canvasOwner = tool;
1813 canvas.fill(canvas.getRect(), 0x00);
1814 canvasChangedArea = null;
1815 return canvas;
1816 }
1817
1824 public NBitmap getCanvas(Tool tool) throws IllegalStateException {
1825 if (canvasOwner != tool) {
1826 throw new IllegalStateException("Tool is not canvas owner");
1827 }
1828 return canvas;
1829 }
1830
1836 public void addCanvasChangedArea(Rect area) throws IllegalStateException {
1837 if (canvasOwner == null) {
1838 throw new IllegalStateException("Canvas is not prepared.");
1839 }
1840 if (canvasChangedArea == null) {
1841 canvasChangedArea = new Rect(area);
1842 } else {
1843 canvasChangedArea.cover(area);
1844 }
1845 addChangedArea(area);
1846 }
1847
1855 public void submitCanvas(Tool tool, boolean commit) throws IllegalStateException, LayerNotFoundException {
1856 if (tool != canvasOwner) {
1857 throw new IllegalStateException("Canvas is not prepared.");
1858 }
1859 canvasChangedArea.cropBy(getRect());
1860 if (commit) {
1861 if (patch != null) {
1862 patch.dispose();
1863 patch = null;
1864 }
1865 switch (selectedState) {
1866 case SELECTED_LAYER: {
1867 RasterLayer l = (RasterLayer) getLayer(selectedLayerId);
1868 NBitmap m = (masterMaskActive) ? masterMask : null;
1869 patch = new UndoPatch(l.getBitmap());
1870 canvasOwner.onCommit(this, canvas, tmpLayer.getBitmap(), l.getBitmap(), m, canvasChangedArea, canvasChangedArea.tlx, canvasChangedArea.tly);
1871
1872 break;
1873 }
1874 case SELECTED_MASK: {
1875 Layer l = getLayer(selectedLayerId);
1876 NBitmap m = (masterMaskActive) ? masterMask : null;
1877 patch = new UndoPatch(l.getMask(true));
1878 canvasOwner.onCommit(this, canvas, tmpLayer.getMask(true), l.getMask(true), m, canvasChangedArea, canvasChangedArea.tlx, canvasChangedArea.tly);
1879 break;
1880 }
1881 case SELECTED_MASTER_MASK: {
1882 patch = new UndoPatch(masterMask);
1883 canvasOwner.onCommit(this, canvas, masterMask, masterMask, null, canvasChangedArea, canvasChangedArea.tlx, canvasChangedArea.tly);
1884 break;
1885 }
1886 default:
1887 break;
1888 }
1889 } else {
1890 addChangedArea(canvasChangedArea);
1891 }
1892 canvasOwner = null;
1893 if (pres != null) {
1894 synchronized (pres) {
1895 if (selectedState != ImageSelectedState.SELECTED_MASTER_MASK) {
1896 getLayer(selectedLayerId).updateInfo(pres.getLayerInfo(selectedLayerId));
1897 pres.hasChanged();
1898 } else {
1899 pres.masterMaskActive = masterMaskActive;
1900 NBitmap mskThumbWrap = new NBitmap(pres.masterMask);
1901 Interpolator.resampleTo(masterMask, mskThumbWrap);
1902 mskThumbWrap.dispose();
1903 }
1904 }
1905 }
1906 }
1907
1916 public int exportTo(NBitmap dst, Rect srcRect, int srcOrigX, int srcOrigY) {
1917 BitmapInfo dstInfo = dst.getInfo();
1918 if (dstInfo.channelCount == ChannelCount.FOUR_CHANNEL && dstInfo.depth == this.depth) {
1919
1920 Rect tmpRect = new Rect(srcRect);
1921 tmpRect.growBy(2 * extraMargins);
1922 tmpRect.cropBy(getRect());
1923 srcOrigX = tmpRect.tlx;
1924 srcOrigY = tmpRect.tly;
1925
1926 srcRect.growBy(extraMargins);
1927 srcRect.cropBy(getRect());
1928
1929 dst.fill(tmpRect, 0xFF000000);
1930
1931 for (Layer l : layers) {
1932 if (l.getId() == selectedLayerId) {
1933 if (canvasOwner != null) {
1934 NBitmap m = (masterMaskActive) ? masterMask : null;
1935 switch (selectedState) {
1936 case SELECTED_LAYER:
1937 canvasOwner.onRender(this, canvas, tmpLayer.getBitmap(), ((RasterLayer) l).getBitmap(), m, tmpRect, srcOrigX, srcOrigY);
1938 tmpLayer.applyTo(dst, tmpRect, srcOrigX, srcOrigY, l.getMask(false));
1939 break;
1940 case SELECTED_MASK:
1941 canvasOwner.onRender(this, canvas, tmpLayer.getMask(true), l.getMask(true), m, tmpRect, srcOrigX, srcOrigY);
1942 l.applyTo(dst, tmpRect, srcOrigX, srcOrigY, tmpLayer.getMask(true));
1943 break;
1944 case SELECTED_MASTER_MASK:
1945 l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1946 default:
1947 break;
1948 }
1949 } else {
1950 l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1951 }
1952 } else {
1953 l.applyTo(dst, tmpRect, srcOrigX, srcOrigY);
1954 }
1955 }
1956 if (selectedState == ImageSelectedState.SELECTED_MASK) {
1957 if (canvasOwner != null) {
1958 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, tmpLayer.getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1959 } else {
1960 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, getLayer(selectedLayerId).getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1961 }
1962 } else if (selectedState == ImageSelectedState.SELECTED_MASTER_MASK) {
1963 if (canvasOwner != null) {
1964 canvasOwner.onRender(this, canvas, tmpLayer.getMask(true), masterMask, null, tmpRect, srcOrigX, srcOrigY);
1965 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, tmpLayer.getMask(true), 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1966 } else {
1967 Blender.drawTo(BlendMode.BLEND_MODE_NORMAL, dst, masterMask, 0xAA0000FF, tmpRect, srcOrigX, srcOrigY);
1968 }
1969 }
1970 } else {
1971 throw new IllegalArgumentException("Target bitmap is of incompatible type");
1972 }
1973 return 0;
1974 }
1975
1987 public Rect exportChangedToHeuristic(NBitmap dst) {
1988 Rect r;
1989 Rect master;
1990 Rect masterPreview;
1991 long incrementalArea;
1992 synchronized (toBeRendered) {
1993 master = toBeRendered.pollFirst();
1994 if (master == null) {
1995 return null;
1996 }
1997 incrementalArea = master.getArea();
1998 masterPreview = new Rect(master);
1999 while ((r = toBeRendered.peekFirst()) != null) {
2000 incrementalArea += r.getArea();
2001 masterPreview.cover(r);
2002 if (incrementalArea < masterPreview.getArea()) {
2003 break;
2004 }
2005 master.cover(r);
2006 toBeRendered.removeFirst();
2007 }
2008 }
2009 exportTo(dst, master, master.tlx, master.tly);
2010 return master;
2011 }
2012 }