Skip to content

Package: ConvertColorProfileJ2DOp

ConvertColorProfileJ2DOp

nameinstructionbranchcomplexitylinemethod
ConvertColorProfileJ2DOp()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
execute(ConvertColorProfileOp, EditableImage, BufferedImage)
M: 95 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 21 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * *********************************************************************************************************************
3: *
4: * Mistral: open source imaging engine
5: * http://tidalwave.it/projects/mistral
6: *
7: * Copyright (C) 2003 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/mistral-src
23: * git clone https://github.com/tidalwave-it/mistral-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.image.java2d;
28:
29: import javax.annotation.Nonnull;
30: import javax.annotation.concurrent.Immutable;
31: import java.util.Collections;
32: import java.awt.RenderingHints;
33: import java.awt.color.ColorSpace;
34: import java.awt.color.ICC_ColorSpace;
35: import java.awt.color.ICC_Profile;
36: import java.awt.image.BufferedImage;
37: import java.awt.image.ColorConvertOp;
38: import java.awt.image.ColorModel;
39: import java.awt.image.DataBuffer;
40: import java.awt.image.DirectColorModel;
41: import java.awt.image.Raster;
42: import it.tidalwave.image.EditableImage;
43: import it.tidalwave.image.ImageUtils;
44: import it.tidalwave.image.op.ConvertColorProfileOp;
45: import it.tidalwave.image.op.OperationImplementation;
46: import lombok.extern.slf4j.Slf4j;
47:
48: /***********************************************************************************************************************
49: *
50: * @author Fabrizio Giudici
51: *
52: **********************************************************************************************************************/
53: @Immutable @Slf4j
54: public class ConvertColorProfileJ2DOp extends OperationImplementation<ConvertColorProfileOp, BufferedImage>
55: {
56: @Override @Nonnull
57: protected BufferedImage execute (@Nonnull final ConvertColorProfileOp operation,
58: @Nonnull final EditableImage image,
59: @Nonnull final BufferedImage bufferedImage)
60: {
61: final var targetProfile = operation.getIccProfile();
62: log.debug("convertColorProfile({})", ImageUtils.getICCProfileName(targetProfile));
63: Java2DUtils.logImage(log, ">>>> source bufferedImage", bufferedImage);
64:
65: final var sourceProfile = ImageUtils.getICCProfile(bufferedImage);
66: final var sourceProfileName = ImageUtils.getICCProfileName(sourceProfile);
67: log.debug(">>>> Converting profile from {} to {}",
68: sourceProfileName,
69: ImageUtils.getICCProfileName(targetProfile));
70:
71: final var hints = new RenderingHints(Collections.emptyMap());
72: hints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
73: final var ccOp = new ColorConvertOp(new ICC_Profile[]{targetProfile}, hints);
74:
75: // Strategy 1: it would be the best, but reduces depth to 8 bit and converts to PixelInterleavedRaster, which
76: // is SLOW!
77: // image = ccOp.filter(image, null); // - produce PixelInt BYTE
78: // Strategy 2: create a dest image which is already an 8-bit packed raster
79: // FIXME: this reduces the depth to 8 bit, which we don't want!
80: log.warn(">>>> **** WARNING: convertColorProfile() is reducing depth to 8 bit!");
81:
82: final var raster = Raster.createPackedRaster(DataBuffer.TYPE_INT,
83: bufferedImage.getWidth(),
84: bufferedImage.getHeight(),
85: 3,
86: 8,
87: null);
88: final ColorSpace colorSpace = new ICC_ColorSpace(targetProfile);
89: final ColorModel colorModel =
90: new DirectColorModel(colorSpace, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0, false, DataBuffer.TYPE_INT);
91:
92: final var image2 =
93: new BufferedImage(colorModel, raster, false, Java2DUtils.getProperties(bufferedImage));
94: final var result = ccOp.filter(bufferedImage, image2);
95:
96: // Strategy 3: work in place. It would be the best, but it does not work: produces a dark image.
97: // ccOp.filter(image, image);
98: // Strategy 4: create an explicity destination image with the same SampleModel as the source, but produces a dark image
99: // BufferedImage image2 = createCopy2(false); // - stessa conseguenza dell'in place
100: // image = ccOp.filter(image, image2);
101: Java2DUtils.logImage(log, ">>>> >>>> convertColorProfile() returning ", result);
102:
103: return result;
104: }
105: }