001package net.gdface.image; 002 003import java.io.File; 004import java.io.FileNotFoundException; 005import java.io.IOException; 006import java.io.OutputStream; 007import java.util.Iterator; 008import java.util.ServiceLoader; 009 010import net.gdface.utils.Assert; 011import net.gdface.utils.BaseVolatile; 012import net.gdface.utils.FaceUtilits; 013import net.gdface.utils.ILazyInitVariable; 014import net.gdface.utils.Judge; 015/** 016 * å›¾åƒæ•°æ®å¤„ç†å¯¹è±¡<br> 017 * @author guyadong 018 * 019 */ 020public abstract class BaseLazyImage implements ImageMatrix { 021 private static final ILazyInitVariable<LazyImageFactory> lazyImageFactory = new BaseVolatile<LazyImageFactory>(){ 022 023 @Override 024 protected LazyImageFactory doGet() { 025 /* SPI(Service Provider Interface)æœºåˆ¶åŠ è½½ {@link LazyImageFactory}实例,没有找到则抛出异常 */ 026 ServiceLoader<LazyImageFactory> providers = ServiceLoader.load(LazyImageFactory.class); 027 Iterator<LazyImageFactory> itor = providers.iterator(); 028 if(!itor.hasNext()){ 029 throw new NotFoundLazyImageFactoryException(); 030 } 031 return itor.next(); 032 }}; 033 /** 034 * 图åƒåŽŸå§‹æ•°æ®(未解ç ) 035 */ 036 protected byte[] imgBytes = null; 037 /** 038 * å›¾åƒæ•°æ®æœ¬åœ°å˜å‚¨æ–‡ä»¶ 039 */ 040 protected File localFile = null; 041 /** 042 * å›¾åƒæ•°æ®çš„MD5æ ¡éªŒç 043 */ 044 protected String md5 = null; 045 /** 046 * å›¾åƒæ–‡ä»¶åŽç¼€ 047 */ 048 protected String suffix = null; 049 /** 050 * 是å¦åœ¨è¯»å–图åƒç»“æŸæ—¶è‡ªåŠ¨æ‰§è¡Œ {@link #close()}释放资æº<br> 051 * 默认为{@code true} 052 */ 053 protected boolean autoClose = true; 054 protected int width; 055 protected int height; 056 /** 057 * RGBæ ¼å¼çš„图åƒçŸ©é˜µæ•°æ®(全图) 058 */ 059 protected byte[] matrixRGB = null; 060 /** 061 * BGRæ ¼å¼çš„图åƒçŸ©é˜µæ•°æ®(全图) 062 */ 063 protected byte[] matrixBGR = null; 064 /** 065 * ç°åº¦å›¾åƒçŸ©é˜µæ•°æ®(全图) 066 */ 067 protected byte[] matrixGray = null; 068 /** 069 * RGBAæ ¼å¼çš„图åƒçŸ©é˜µæ•°æ®(全图) 070 */ 071 protected byte[] matrixRGBA = null; 072 073 protected BaseLazyImage() { 074 } 075 /** 076 * @param imgBytes å›¾åƒæ•°æ®,{@code imgBytes}为null或为空,则抛出 {@link IllegalArgumentException} 077 */ 078 public BaseLazyImage(byte[] imgBytes) { 079 Assert.notEmpty(imgBytes, "imgBytes"); 080 this.imgBytes=imgBytes; 081 } 082 /** 083 * ç”¨æœ¬åœ°å›¾åƒæ–‡ä»¶åˆ›å»ºå¯¹è±¡ 084 * @param src 085 * @param md5 文件的MD5æ ¡éªŒç ,为{@code null}时自动计算 086 * @throws FileNotFoundException 087 */ 088 public BaseLazyImage(File src, String md5) throws FileNotFoundException { 089 Assert.notNull(src, "src"); 090 this.localFile = src; 091 if(!localFile.exists()||!localFile.isFile()||0==localFile.length()){ 092 throw new FileNotFoundException(String.format("NOT EXIST OR NOT FILE OR ZERO bytes%s",localFile.getAbsolutePath())); 093 } 094 String fileName = localFile.getName(); 095 this.suffix = fileName.substring(fileName.lastIndexOf(".") + 1); 096 this.md5 = md5; 097 } 098 /** 099 * è¿”å›žå›¾åƒæ•°æ®å—节数组<br> 100 * å¦‚æžœå›¾åƒæ•°æ®åœ¨æœ¬åœ°æ–‡ä»¶ä¸ï¼Œåˆ™æ–¹æ³•第一次被调用时将数æ®ä»Žæ–‡ä»¶ä¸è¯»å–åˆ°å†…å˜ 101 * @return the imgBytes,å¦‚æžœä¸ºæ— æ•ˆå›¾åƒï¼Œåˆ™è¿”回null 102 * @throws IllegalArgumentException 傿•°é”™è¯¯ 103 */ 104 public byte[] getImgBytes() { 105 106 if(null==imgBytes){ 107 if(null!=localFile){ 108 try { 109 imgBytes = FaceUtilits.getBytesNotEmpty(localFile); 110 } catch (IOException e) { 111 throw new RuntimeException(e); 112 } 113 }else 114 throw new IllegalArgumentException("while isValidImage be true localFile & imgBytes can't be NULL all"); 115 } 116 return imgBytes; 117 } 118 119 /** 120 * @return the md5 121 */ 122 public String getMd5() { 123 if (null == md5) 124 md5 = FaceUtilits.getMD5String(getImgBytes()); 125 return md5; 126 } 127 128 /** 129 * @return the suffix 130 */ 131 public String getSuffix() { 132 return suffix; 133 } 134 135 /** 136 * @return localFile 137 */ 138 public File getLocalFile() { 139 return localFile; 140 } 141 142 @Override 143 public int getWidth() { 144 return width; 145 } 146 147 @Override 148 public int getHeight() { 149 return height; 150 } 151 152 /** 153 * 在执行 {@link #read()}或 {@link #open()}之å‰è°ƒç”¨,æ‰æœ‰æ•ˆ 154 * @param autoClose è¦è®¾ç½®çš„ autoClose 155 * @return 156 * @see #autoClose 157 */ 158 public BaseLazyImage setAutoClose(boolean autoClose) { 159 this.autoClose = autoClose; 160 return this; 161 } 162 /** 163 * é‡Šæ”¾èµ„æº 164 * @throws IOException 165 */ 166 public void close() throws IOException{ 167 168 } 169 @Override 170 public void finalize() throws Throwable { 171 close(); 172 this.imgBytes=null; 173 this.localFile=null; 174 } 175 /** 176 * 读å–图åƒåŸºæœ¬ä¿¡æ¯ï¼Œæ£€æŸ¥å›¾åƒæ•°æ®æœ‰æ•ˆæ€§ 177 * @return 178 * @throws UnsupportedFormatException 179 * @throws NotImageException 180 */ 181 public abstract <T extends BaseLazyImage>T open() throws UnsupportedFormatException, NotImageException; 182 /** 183 * 以 {@link #md5}为åå—将文件ä¿å˜åœ¨{@code folder}文件夹下<br> 184 * 如果åŒå文件å˜åœ¨ï¼Œä¸”长度ä¸ä¸º0æ—¶ä¸è¦†ç›– 185 * @param folder 186 * @return 187 * @throws IOException 188 * @see FaceUtilits#saveBytes(byte[], File, boolean) 189 */ 190 public File save(File folder) throws IOException { 191 File file = new File(folder,getMd5()+(Judge.isEmpty(this.suffix)?"":"."+this.suffix)); 192 localFile= FaceUtilits.saveBytes(getImgBytes(), file, file.exists()&&file.isFile()&&0==file.length()); 193 return localFile; 194 } 195 public abstract byte[] wirtePNGBytes(); 196 public abstract byte[] wirteJPEGBytes(); 197 public void wirtePNGB(OutputStream out) throws IOException{ 198 Assert.notNull(out, "out"); 199 out.write(wirtePNGBytes()); 200 } 201 public void wirteJPEG(OutputStream out) throws IOException{ 202 Assert.notNull(out, "out"); 203 out.write(wirteJPEGBytes()); 204 } 205 /** 206 * è¿”å›žå½“å‰ {@link LazyImageFactory}实例 207 * @return 208 * @throws NotFoundLazyImageFactoryException 209 */ 210 public static final LazyImageFactory getLazyImageFactory() throws NotFoundLazyImageFactoryException{ 211 return lazyImageFactory.get(); 212 } 213 214}