001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Jean-Marc Orliaguet, Chalmers 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.theme.presets; 016 017import java.awt.Color; 018import java.io.ByteArrayInputStream; 019import java.io.DataInputStream; 020import java.io.IOException; 021import java.util.LinkedHashMap; 022import java.util.Map; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026 027public class PhotoshopPaletteParser extends PaletteParser { 028 029 private static final Log log = LogFactory.getLog(PhotoshopPaletteParser.class); 030 031 private static final int RGB = 0; 032 033 private static final int HSB = 1; 034 035 private static final int CMYK = 2; 036 037 private static final int LAB = 7; 038 039 private static final int GRAYSCALE = 8; 040 041 private static final int WIDE_CMYK = 9; 042 043 public static boolean checkSanity(byte[] bytes) { 044 return true; 045 } 046 047 public static Map<String, String> parse(byte[] bytes) { 048 Map<String, String> entries = new LinkedHashMap<String, String>(); 049 ByteArrayInputStream is = new ByteArrayInputStream(bytes); 050 DataInputStream dis = new DataInputStream(is); 051 052 char[] words = new char[bytes.length]; 053 int size = 0; 054 while (true) { 055 try { 056 words[size] = dis.readChar(); 057 size++; 058 } catch (IOException e) { 059 break; 060 } 061 } 062 063 try { 064 is.close(); 065 dis.close(); 066 } catch (IOException e) { 067 log.error(e, e); 068 } 069 070 int offset = 1; 071 int version = words[0] & 0xffff; 072 int nc = words[1] & 0xffff; 073 074 // get version 2 if it exists 075 if (version == 1 && size > nc * 5 + 2) { 076 offset += nc * 5 + 2; 077 version = words[offset - 1] & 0xffff; 078 nc = words[offset] & 0xffff; 079 } 080 081 if (version == 1) { 082 log.debug("Found ACO v1 color file (Photoshop < 7.0)"); 083 } else if (version == 2) { 084 log.debug("Found ACO v2 color file (Photoshop >= 7.0)"); 085 } else { 086 log.error("Unknown ACO file version: " + version); 087 return entries; 088 } 089 090 log.debug("Found " + nc + " colors."); 091 092 int counter = 1; 093 for (int j = 0; j < nc; j++) { 094 String value = null; 095 int colorSpace = words[offset + 1] & 0xff; 096 int w = words[offset + 2] & 0xffff; 097 int x = words[offset + 3] & 0xffff; 098 int y = words[offset + 4] & 0xffff; 099 int z = words[offset + 5] & 0xffff; 100 101 if (colorSpace == RGB) { 102 value = rgbToHex(w / 256, x / 256, y / 256); 103 104 } else if (colorSpace == HSB) { 105 float hue = w / 65535F; // [0.0-1.0] 106 float saturation = x / 65535F; // [0.0-1.0] 107 float brightness = y / 65535F; // [0.0-1.0] 108 Color color = Color.getHSBColor(hue, saturation, brightness); 109 value = rgbToHex(color.getRed(), color.getGreen(), color.getBlue()); 110 111 } else if (colorSpace == CMYK) { 112 float cyan = 1F - w / 65535F; // [0.0-1.0] 113 float magenta = 1F - x / 65535F; // [0.0-1.0] 114 float yellow = 1F - y / 65535F; // [0.0-1.0] 115 float black = 1F - z / 65535F; // [0.0-1.0] 116 // TODO: do the conversion to RGB. An ICC profile is required. 117 log.warn("Unsupported color space: CMYK"); 118 119 } else if (colorSpace == GRAYSCALE) { 120 int gray = (int) (w * 256F / 10000F); // [0-256] 121 value = rgbToHex(gray, gray, gray); 122 123 } else if (colorSpace == LAB) { 124 float l = w / 100F; 125 float a = x / 100F; 126 float b = y / 100F; 127 // TODO: do the conversion to RGB. An ICC profile is required. 128 log.warn("Unsupported color space: CIE Lab"); 129 130 } else if (colorSpace == WIDE_CMYK) { 131 float cyan = w / 10000F; // [0.0-1.0] 132 float magenta = x / 10000F; // [0.0-1.0] 133 float yellow = y / 10000F; // [0.0-1.0] 134 float black = z / 10000F; // [0.0-1.0] 135 // TODO: do the conversion to RGB. An ICC profile is required. 136 log.warn("Unsupported color space: Wide CMYK"); 137 138 } else { 139 log.warn("Unknown color space: " + colorSpace); 140 } 141 142 String name = ""; 143 if (version == 1) { 144 name = String.format("Color %s", counter); 145 } 146 147 else if (version == 2) { 148 int len = (words[offset + 7] & 0xffff) - 1; 149 name = String.copyValueOf(words, offset + 8, len); 150 offset += len + 3; 151 152 String n = name; 153 int c = 2; 154 while (entries.containsKey(n)) { 155 n = String.format("%s %s", name, c); 156 c++; 157 } 158 name = n; 159 } 160 161 if (value != null) { 162 entries.put(name, value); 163 } 164 165 offset += 5; 166 counter++; 167 } 168 169 return entries; 170 } 171 172}