📄 image.java
字号:
/* w = Toolkit.imgGetWidth( img.nativeData); h = Toolkit.imgGetHeight( img.nativeData); if ( (img.width != w) || (img.height != h) ){ img.width = w; img.height = h; img.stateChange( ImageObserver.WIDTH|ImageObserver.HEIGHT, 0, 0, img.width, img.height); }*/ img.flags |= Image.BLOCK_FRAMELOADER; img.stateChange( ImageObserver.FRAMEBITS, 0, 0, img.width, img.height); } while ( img.observers != null );}}class ImageLoader implements ImageConsumer, Runnable{ Image queueHead; Image queueTail; Image img; static ImageLoader asyncLoader; static ImageLoader syncLoader = new ImageLoader();public synchronized void imageComplete ( int status ) { int s = 0; if ( status == STATICIMAGEDONE ){ s = ImageObserver.ALLBITS; // give native layer a chance to do alpha channel reduction if ( !(img.producer instanceof ImageNativeProducer) ) Toolkit.imgComplete( img.nativeData, status); } else if ( status == SINGLEFRAMEDONE ) { s = ImageObserver.FRAMEBITS; // This is a (indefinite) movie production - move it out of the way (in its own thread) // so that we can go on with useful work. Note that if our producer was a ImageNativeProducer, // the whole external image has been read in already (no IO required, anymore) new ImageFrameLoader( img); } else { if ( (status & IMAGEERROR) != 0 ) s |= ImageObserver.ERROR; if ( (status & IMAGEABORTED) != 0 ) s |= ImageObserver.ABORT; } img.stateChange( s, 0, 0, img.width, img.height); // this has to be called *after* a optional ImageFrameLoader went into action, since // the producer might decide to stop if it doesn't have another consumer img.producer.removeConsumer( this); img = null; // we are done with it, prevent memory leaks if ( this == asyncLoader ) notify(); // in case we had an async producer}static synchronized void load ( Image img ) { if ( asyncLoader == null ){ asyncLoader = new ImageLoader(); asyncLoader.queueHead = asyncLoader.queueTail = img; Thread t = new Thread( asyncLoader, "asyncLoader"); t.setPriority( Thread.NORM_PRIORITY - 1); t.start(); } else { if ( asyncLoader.queueTail == null ) { asyncLoader.queueHead = asyncLoader.queueTail = img; } else { asyncLoader.queueTail.next = img; asyncLoader.queueTail = img; } ImageLoader.class.notify(); }}static void loadSync( Image img ) { synchronized ( syncLoader ) { syncLoader.img = img; img.producer.startProduction(syncLoader); }}public void run () { for (;;) { synchronized ( ImageLoader.class ) { if ( queueHead != null ) { img = queueHead; queueHead = img.next; img.next = null; if ( img == queueTail ) queueTail = null; } else { try { ImageLoader.class.wait( 20000); if ( queueHead == null ) { // Ok, we waited for too long, lets do suicide asyncLoader = null; return; } else { continue; } } catch ( InterruptedException xx ) { xx.printStackTrace(); } } } try { // this is hopefully sync, but who knows what kinds of producers are out there img.producer.startProduction( this); if ( img != null ) { synchronized ( this ){ wait(); } } } catch ( Throwable x ) { x.printStackTrace(); imageComplete( IMAGEERROR | IMAGEABORTED); } }}public void setColorModel ( ColorModel model ) { // No way to pass this to ImageObservers. Since we also get it in setPixels, we // just ignore it}public void setDimensions ( int width, int height ) { img.width = width; img.height = height; // If we were notified by a ImageNativeProducer, the nativeData field is already // set. In case this is just an arbitrary producer, create it so that we have a // target for subsequent setPixel() calls if ( img.nativeData == null ){ img.nativeData = Toolkit.imgCreateImage( width, height); } img.stateChange( ImageObserver.WIDTH|ImageObserver.HEIGHT, 0, 0, width, height);}public void setHints ( int hints ) { // we don't honor them}public void setPixels ( int x, int y, int w, int h, ColorModel model, byte pixels[], int offset, int scansize ) { if ( img.nativeData == null ) { // producer trouble, we haven't got dimensions yet return; } if ( model instanceof IndexColorModel ) { IndexColorModel icm = (IndexColorModel) model; Toolkit.imgSetIdxPels( img.nativeData, x, y, w, h, icm.rgbs, pixels, icm.trans, offset, scansize); img.stateChange( ImageObserver.SOMEBITS, x, y, w, h); } else { System.err.println("Unhandled colorModel: " + model.getClass()); }}public void setPixels ( int x, int y, int w, int h, ColorModel model, int pixels[], int offset, int scansize ) { if ( img.nativeData == null ) { // producer trouble, we haven't got dimensions yet return; } if ( model instanceof JavaColorModel ) { // Ok, nothing to convert here } else if ( model instanceof DirectColorModel ) { // in case our pels aren't default RGB yet, convert them using the ColorModel int xw = x + w; int yh = y + h; int i, j, idx; int i0 = y * scansize + offset; for ( j = y; j < yh; j++, i0 += scansize ) { for ( i = x, idx = i+i0; i < xw; i++, idx++) { // are we allowed to change the array in-situ? pixels[idx] = model.getRGB( pixels[idx]); } } } else { System.out.println("Unhandled colorModel: " + model.getClass()); } Toolkit.imgSetRGBPels( img.nativeData, x, y, w, h, pixels, offset, scansize); img.stateChange( ImageObserver.SOMEBITS, x, y, w, h);}public void setProperties ( Hashtable properties ) { img.props = properties; img.stateChange( img.flags | ImageObserver.PROPERTIES, 0, 0, img.width, img.height);}}/** * This shouldn't be a inner class since you can easily grab the source of an * image and use it outside of this image (e.g. to create other images - whatever * it might be good for) */class ImageNativeProducer implements ImageProducer{ Object consumer; Object src; int off; int len;ImageNativeProducer ( Image img ) { src = img;}ImageNativeProducer ( Image img, File file ) { src = file; // check if we can produce immediately if ( file.exists() ) { if ( file.length() < Defaults.FileImageThreshold ){ img.flags |= Image.PRODUCING; img.producer = this; ImageLoader.loadSync(img); } } else { img.flags = ImageObserver.ERROR | ImageObserver.ABORT; }}ImageNativeProducer ( Image img, byte[] data, int off, int len ) { src = data; this.off = off; this.len = len; if ( len < Defaults.DataImageThreshold ) { img.flags |= Image.PRODUCING; synchronized ( ImageLoader.syncLoader ) { ImageLoader.syncLoader.img = img; img.producer = this; startProduction( ImageLoader.syncLoader); } }}ImageNativeProducer ( URL url ) { src = url;}public void addConsumer ( ImageConsumer ic ) { if ( consumer == null ){ consumer = ic; } else if ( this.consumer instanceof Vector ) { ((Vector)consumer).addElement( ic); } else { Vector v = new Vector(3); v.addElement( consumer); v.addElement( ic); consumer = v; }}void imageComplete ( int flags ){ if ( consumer instanceof ImageConsumer ){ ((ImageConsumer)consumer).imageComplete( flags); } else if ( consumer instanceof Vector) { Vector v = (Vector) consumer; int i, n = v.size(); for ( i=0; i<n; i++ ){ ((ImageConsumer)v.elementAt( i)).imageComplete( flags); } }}public boolean isConsumer ( ImageConsumer ic ) { if ( consumer instanceof ImageConsumer ) return (consumer == ic); else if ( consumer instanceof Vector ) return ((Vector)consumer).contains( ic); else return false;}void produceFrom ( File file ) { Ptr ptr; if ( file.exists() && (ptr = Toolkit.imgCreateFromFile( file.getAbsolutePath())) != null ){ produceFrom( ptr); } else { imageComplete( ImageConsumer.IMAGEERROR | ImageConsumer.IMAGEABORTED); }}void produceFrom ( Ptr ptr ) { if ( consumer instanceof ImageLoader ) { ImageLoader loader = (ImageLoader)consumer; Image img = loader.img; img.nativeData = ptr; img.width = Toolkit.imgGetWidth( ptr); img.height = Toolkit.imgGetHeight( ptr); loader.setDimensions( img.width, img.height); loader.imageComplete( Toolkit.imgIsMultiFrame( ptr) ? ImageConsumer.SINGLEFRAMEDONE : ImageConsumer.STATICIMAGEDONE); } else { Toolkit.imgProduceImage( this, ptr); Toolkit.imgFreeImage( ptr); }}void produceFrom ( URL url ) { // since this is most likely used in a browser context (no file // system), the only thing we can do (in the absence of a suspendable // native image production) is to temporarily store the data in // memory. Note that this is done via kaffe.io.AccessibleBAOStream, // to prevent the inacceptable memory consumption duplication of // "toByteArray()". // Ideally, we would have a suspendable image production (that can // deal with reading and processing "incomplete" data), but that // simply isn't supported by many native image conversion libraries. // Some could be done in Java (at the expense of a significant speed // degradation - this is the classical native functionality), but // things like Jpeg ? try { URLConnection conn = url.openConnection(); if (conn != null) { int sz = conn.getContentLength(); if (sz <= 0) { // it's unknown, let's assume some size sz = 4096; } AccessibleBAOStream out = new AccessibleBAOStream(sz); InputStream in = conn.getInputStream(); if ( in != null ) { out.readFrom(in); in.close(); Ptr ptr = Toolkit.imgCreateFromData(out.getBuffer(), 0, out.size()); if ( ptr != null ){ produceFrom( ptr); return; } } } } catch ( Exception x ) {} imageComplete( ImageConsumer.IMAGEERROR|ImageConsumer.IMAGEABORTED);}void produceFrom ( byte[] data, int off, int len ) { Ptr ptr; if ( (ptr = Toolkit.imgCreateFromData( data, off, len)) != null ) produceFrom( ptr); else imageComplete( ImageConsumer.IMAGEERROR | ImageConsumer.IMAGEABORTED);}public void removeConsumer ( ImageConsumer ic ) { if ( consumer == ic ){ consumer = null; } else if ( consumer instanceof Vector ) { Vector v = (Vector) consumer; v.removeElement( ic); if ( v.size() == 1 ) consumer = v.elementAt( 0); }}public void requestTopDownLeftRightResend ( ImageConsumer consumer ) { // ignored}void setColorModel ( ColorModel model ){ if ( consumer instanceof ImageConsumer ){ ((ImageConsumer)consumer).setColorModel( model); } else if ( consumer instanceof Vector) { Vector v = (Vector)consumer; int i, n = v.size(); for ( i=0; i<n; i++ ){ ((ImageConsumer)v.elementAt( i)).setColorModel( model); } }}void setDimensions ( int width, int height ){ if ( consumer instanceof ImageConsumer ){ ((ImageConsumer)consumer).setDimensions( width, height); } else if ( consumer instanceof Vector) { Vector v = (Vector)consumer; int i, n = v.size(); for ( i=0; i<n; i++ ){ ((ImageConsumer)v.elementAt( i)).setDimensions( width, height); } }}void setHints ( int hints ){ if ( consumer instanceof ImageConsumer ){ ((ImageConsumer)consumer).setHints( hints); } else if ( consumer instanceof Vector) { Vector v = (Vector)consumer; int i, n = v.size(); for ( i=0; i<n; i++ ){ ((ImageConsumer)v.elementAt( i)).setHints( hints); } }}void setPixels ( int x, int y, int w, int h, ColorModel model, int pixels[], int offset, int scansize ) { if ( consumer instanceof ImageConsumer ){ ((ImageConsumer)consumer).setPixels( x, y, w, h, model, pixels, offset, scansize); } else if ( consumer instanceof Vector) { Vector v = (Vector)consumer; int i, n = v.size(); for ( i=0; i<n; i++ ){ ((ImageConsumer)v.elementAt( i)).setPixels( x, y, w, h, model, pixels, offset, scansize); } }}public void startProduction ( ImageConsumer ic ) { addConsumer( ic); if ( src instanceof File ) { produceFrom( (File)src); } else if ( src instanceof URL ) { produceFrom( (URL)src); } else if ( src instanceof byte[] ) { produceFrom( (byte[])src, off, len); } else if ( src instanceof Image ) { Toolkit.imgProduceImage( this, ((Image)src).nativeData); } else { System.err.println( "unsupported production source: " + src.getClass()); } removeConsumer( ic);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -